From 4df2b77fdf42046fe19bd371be7c7255986b5980 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 6 Mar 2012 13:36:39 +0100 Subject: renamed hooks to addons, new filemanager and database, many new api methods you will loose ALL your LINKS, webinterface will NOT work --- module/AddonManager.py | 253 + module/Api.py | 770 ++- module/FileManager.py | 564 ++ module/HookManager.py | 253 - module/PyFile.py | 211 +- module/PyPackage.py | 82 +- module/database/DatabaseBackend.py | 237 +- module/database/FileDatabase.py | 1033 +--- module/database/UserDatabase.py | 56 +- module/database/__init__.py | 4 +- module/interaction/CaptchaManager.py | 158 - module/interaction/EventManager.py | 12 +- module/interaction/InteractionManager.py | 33 +- module/interaction/InteractionTask.py | 87 +- module/network/HTTPDownload.py | 2 + module/plugins/Account.py | 28 +- module/plugins/Addon.py | 203 + module/plugins/Base.py | 9 +- module/plugins/Crypter.py | 26 +- module/plugins/Hook.py | 176 - module/plugins/Hoster.py | 4 +- module/plugins/MultiHoster.py | 2 +- module/plugins/PluginManager.py | 16 +- module/plugins/addons/CaptchaTrader.py | 159 + module/plugins/addons/ClickAndLoad.py | 89 + module/plugins/addons/EasybytezCom.py | 32 + module/plugins/addons/Ev0InFetcher.py | 87 + module/plugins/addons/ExternalScripts.py | 118 + module/plugins/addons/ExtractArchive.py | 314 ++ module/plugins/addons/HotFolder.py | 85 + module/plugins/addons/IRCInterface.py | 425 ++ module/plugins/addons/MergeFiles.py | 94 + module/plugins/addons/MultiHome.py | 82 + module/plugins/addons/MultiHoster.py | 102 + module/plugins/addons/MultishareCz.py | 36 + module/plugins/addons/Premium4Me.py | 46 + module/plugins/addons/RehostTo.py | 39 + module/plugins/addons/UpdateManager.py | 199 + module/plugins/addons/XMPPInterface.py | 276 + module/plugins/addons/__init__.py | 0 module/plugins/hooks/CaptchaTrader.py | 159 - module/plugins/hooks/ClickAndLoad.py | 89 - module/plugins/hooks/EasybytezCom.py | 32 - module/plugins/hooks/Ev0InFetcher.py | 87 - module/plugins/hooks/ExternalScripts.py | 118 - module/plugins/hooks/ExtractArchive.py | 314 -- module/plugins/hooks/HotFolder.py | 85 - module/plugins/hooks/IRCInterface.py | 425 -- module/plugins/hooks/MergeFiles.py | 94 - module/plugins/hooks/MultiHome.py | 82 - module/plugins/hooks/MultiHoster.py | 102 - module/plugins/hooks/MultishareCz.py | 36 - module/plugins/hooks/Premium4Me.py | 46 - module/plugins/hooks/RehostTo.py | 39 - module/plugins/hooks/UpdateManager.py | 199 - module/plugins/hooks/XMPPInterface.py | 276 - module/plugins/hooks/__init__.py | 0 module/plugins/internal/AbstractExtractor.py | 2 +- module/remote/socketbackend/ttypes.py | 347 +- module/remote/thriftbackend/pyload.thrift | 436 +- .../thriftbackend/thriftgen/pyload/Pyload-remote | 448 +- .../thriftbackend/thriftgen/pyload/Pyload.py | 5663 ++++++++++++-------- .../thriftbackend/thriftgen/pyload/ttypes.py | 667 ++- module/setup.py | 1 + module/threads/AddonThread.py | 65 + module/threads/DecrypterThread.py | 3 +- module/threads/DownloadThread.py | 12 +- module/threads/HookThread.py | 65 - module/threads/InfoThread.py | 6 +- module/threads/ThreadManager.py | 6 +- module/utils/__init__.py | 29 +- module/web/api_app.py | 15 +- module/web/json_app.py | 13 +- module/web/pyload_app.py | 16 +- module/web/utils.py | 1 + module/web/webinterface.py | 4 +- 76 files changed, 9061 insertions(+), 7323 deletions(-) create mode 100644 module/AddonManager.py create mode 100644 module/FileManager.py delete mode 100644 module/HookManager.py delete mode 100644 module/interaction/CaptchaManager.py create mode 100644 module/plugins/Addon.py delete mode 100644 module/plugins/Hook.py create mode 100644 module/plugins/addons/CaptchaTrader.py create mode 100644 module/plugins/addons/ClickAndLoad.py create mode 100644 module/plugins/addons/EasybytezCom.py create mode 100644 module/plugins/addons/Ev0InFetcher.py create mode 100644 module/plugins/addons/ExternalScripts.py create mode 100644 module/plugins/addons/ExtractArchive.py create mode 100644 module/plugins/addons/HotFolder.py create mode 100644 module/plugins/addons/IRCInterface.py create mode 100644 module/plugins/addons/MergeFiles.py create mode 100644 module/plugins/addons/MultiHome.py create mode 100644 module/plugins/addons/MultiHoster.py create mode 100644 module/plugins/addons/MultishareCz.py create mode 100644 module/plugins/addons/Premium4Me.py create mode 100644 module/plugins/addons/RehostTo.py create mode 100644 module/plugins/addons/UpdateManager.py create mode 100644 module/plugins/addons/XMPPInterface.py create mode 100644 module/plugins/addons/__init__.py delete mode 100644 module/plugins/hooks/CaptchaTrader.py delete mode 100644 module/plugins/hooks/ClickAndLoad.py delete mode 100644 module/plugins/hooks/EasybytezCom.py delete mode 100644 module/plugins/hooks/Ev0InFetcher.py delete mode 100644 module/plugins/hooks/ExternalScripts.py delete mode 100644 module/plugins/hooks/ExtractArchive.py delete mode 100644 module/plugins/hooks/HotFolder.py delete mode 100644 module/plugins/hooks/IRCInterface.py delete mode 100644 module/plugins/hooks/MergeFiles.py delete mode 100644 module/plugins/hooks/MultiHome.py delete mode 100644 module/plugins/hooks/MultiHoster.py delete mode 100644 module/plugins/hooks/MultishareCz.py delete mode 100644 module/plugins/hooks/Premium4Me.py delete mode 100644 module/plugins/hooks/RehostTo.py delete mode 100644 module/plugins/hooks/UpdateManager.py delete mode 100644 module/plugins/hooks/XMPPInterface.py delete mode 100644 module/plugins/hooks/__init__.py create mode 100644 module/threads/AddonThread.py delete mode 100644 module/threads/HookThread.py (limited to 'module') diff --git a/module/AddonManager.py b/module/AddonManager.py new file mode 100644 index 000000000..cec650c92 --- /dev/null +++ b/module/AddonManager.py @@ -0,0 +1,253 @@ +# -*- 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 . + + @author: RaNaN, mkaay +""" +import __builtin__ + +from traceback import print_exc +from thread import start_new_thread +from threading import RLock + +from types import MethodType + +from module.threads.AddonThread import AddonThread +from module.plugins.PluginManager import literal_eval +from utils import lock, to_string + +class AddonManager: + """ Manages addons, loading, unloading. """ + + def __init__(self, core): + self.core = core + self.config = self.core.config + + __builtin__.addonManager = self #needed to let addons register themself + + self.log = self.core.log + self.plugins = {} + self.methods = {} # dict of names and list of methods usable by rpc + self.events = {} # Contains event that will be registred + + self.lock = RLock() + self.createIndex() + + #registering callback for config event + self.config.changeCB = MethodType(self.dispatchEvent, "configChanged", basestring) + + # manage addons an config change + self.addEvent("configChanged", self.manageAddons) + + @lock + def callInHooks(self, event, *args): + """ Calls a method in all addons and catch / log errors""" + for plugin in self.plugins.itervalues(): + self.call(plugin, event, *args) + self.dispatchEvent(event, *args) + + def call(self, addon, f, *args): + try: + func = getattr(addon, f) + return func(*args) + except Exception, e: + addon.logError(_("Error when executing %s" % f), e) + if self.core.debug: + print_exc() + + def addRPC(self, plugin, func, doc): + doc = doc.strip() if doc else "" + + if plugin in self.methods: + self.methods[plugin][func] = doc + else: + self.methods[plugin] = {func: doc} + + def callRPC(self, plugin, func, args): + if not args: args = [] + else: + args = literal_eval(args) + + plugin = self.plugins[plugin] + f = getattr(plugin, func) + return f(*args) + + @lock + def createIndex(self): + active = [] + deactive = [] + + for pluginname in self.core.pluginManager.getPlugins("addons"): + try: + # check first for builtin plugin + attrs = self.core.pluginManager.loadAttributes("addons", pluginname) + internal = attrs.get("internal", False) + + if internal or self.core.config.get(pluginname, "activated"): + pluginClass = self.core.pluginManager.loadClass("addons", pluginname) + + if not pluginClass: continue + + plugin = pluginClass(self.core, self) + self.plugins[pluginClass.__name__] = plugin + + # hide internals from printing + if not internal and plugin.isActivated(): + active.append(pluginClass.__name__) + else: + self.log.debug("Loaded internal plugin: %s" % pluginClass.__name__) + else: + deactive.append(pluginname) + + + except: + self.log.warning(_("Failed activating %(name)s") % {"name": pluginname}) + if self.core.debug: + print_exc() + + self.log.info(_("Activated addons: %s") % ", ".join(sorted(active))) + self.log.info(_("Deactivate addons: %s") % ", ".join(sorted(deactive))) + + def manageAddons(self, plugin, name, value): + # check if section was a plugin + if plugin not in self.core.pluginManager.getPlugins("addons"): + return + + if name == "activated" and value: + self.activateAddon(plugin) + elif name == "activated" and not value: + self.deactivateAddon(plugin) + + @lock + def activateAddon(self, plugin): + #check if already loaded + if plugin in self.plugins: + return + + pluginClass = self.core.pluginManager.loadClass("addons", plugin) + + if not pluginClass: return + + self.log.debug("Plugin loaded: %s" % plugin) + + plugin = pluginClass(self.core, self) + self.plugins[pluginClass.__name__] = plugin + + # active the addon in new thread + start_new_thread(plugin.activate, tuple()) + self.registerEvents() + + @lock + def deactivateAddon(self, plugin): + if plugin not in self.plugins: + return + else: + addon = self.plugins[plugin] + + if addon.__internal__: return + + self.call(addon, "deactivate") + self.log.debug("Plugin deactivated: %s" % plugin) + + #remove periodic call + self.log.debug("Removed callback %s" % self.core.scheduler.removeJob(addon.cb)) + del self.plugins[addon.__name__] + + #remove event listener + for f in dir(addon): + if f.startswith("__") or type(getattr(addon, f)) != MethodType: + continue + self.core.eventManager.removeFromEvents(getattr(addon, f)) + + def activateAddons(self): + self.log.info(_("Activating Plugins...")) + for plugin in self.plugins.itervalues(): + if plugin.isActivated(): + self.call(plugin, "activate") + + self.registerEvents() + + def deactivateAddons(self): + """ Called when core is shutting down """ + self.log.info(_("Deactivating Plugins...")) + for plugin in self.plugins.itervalues(): + self.call(plugin, "deactivate") + + def downloadPreparing(self, pyfile): + self.callInHooks("downloadPreparing", pyfile) + + def downloadFinished(self, pyfile): + self.callInHooks("downloadFinished", pyfile) + + def downloadFailed(self, pyfile): + self.callInHooks("downloadFailed", pyfile) + + def packageFinished(self, package): + self.callInHooks("packageFinished", package) + + def beforeReconnecting(self, ip): + self.callInHooks("beforeReconnecting", ip) + + def afterReconnecting(self, ip): + self.callInHooks("afterReconnecting", ip) + + @lock + def startThread(self, function, *args, **kwargs): + AddonThread(self.core.threadManager, function, args, kwargs) + + def activePlugins(self): + """ returns all active plugins """ + return [x for x in self.plugins.itervalues() if x.isActivated()] + + def getAllInfo(self): + """returns info stored by addon plugins""" + info = {} + for name, plugin in self.plugins.iteritems(): + if plugin.info: + #copy and convert so str + info[name] = dict( + [(x, to_string(y)) for x, y in plugin.info.iteritems()]) + return info + + def getInfo(self, plugin): + info = {} + if plugin in self.plugins and self.plugins[plugin].info: + info = dict([(x, to_string(y)) + for x, y in self.plugins[plugin].info.iteritems()]) + + return info + + def addEventListener(self, plugin, func, event): + if plugin not in self.events: + self.events[plugin] = [] + self.events[plugin].append((func, event)) + + def registerEvents(self): + for name, plugin in self.plugins.iteritems(): + if name in self.events: + for func, event in self.events[name]: + self.addEvent(event, getattr(plugin, func)) + # clean up + del self.events[name] + + def addConfigHandler(self, plugin, func): + pass #TODO + + def addEvent(self, *args): + self.core.eventManager.addEvent(*args) + + def dispatchEvent(self, *args): + self.core.eventManager.dispatchEvent(*args) + diff --git a/module/Api.py b/module/Api.py index e5d26631f..84712af18 100644 --- a/module/Api.py +++ b/module/Api.py @@ -23,12 +23,6 @@ from os.path import join, isabs from time import time from itertools import chain - -from PyFile import PyFile -from utils import compare_time, to_string -from utils.fs import free_space -from common.packagetools import parseNames -from network.RequestFactory import getURL from remote import activated if activated: @@ -43,6 +37,12 @@ if activated: else: from remote.socketbackend.ttypes import * +from PyFile import PyFile +from utils import compare_time, to_string, bits_set +from utils.fs import free_space +from common.packagetools import parseNames +from network.RequestFactory import getURL + # contains function names mapped to their permissions # unlisted functions are for admins only permMap = {} @@ -64,12 +64,13 @@ class PERMS: ADD = 1 # can add packages DELETE = 2 # can delete packages STATUS = 4 # see and change server status - LIST = 16 # see queue and collector + LIST = 16 # see listed downloads MODIFY = 32 # moddify some attribute of downloads DOWNLOAD = 64 # can download from webinterface SETTINGS = 128 # can access settings ACCOUNTS = 256 # can access accounts LOGS = 512 # can see server logs + INTERACTION = 1024 # can interact with plugins class ROLE: @@ -78,15 +79,14 @@ class ROLE: def has_permission(userperms, perms): - # bytewise or perms before if needed - return perms == (userperms & perms) + return bits_set(perms, userperms) class Api(Iface): """ **pyLoads API** - This is accessible either internal via core.api or via thrift backend. + This is accessible either internal via core.api, thrift backend or json api. see Thrift specification file remote/thriftbackend/pyload.thrift\ for information about data structures and what methods are usuable with rpc. @@ -101,73 +101,30 @@ class Api(Iface): def __init__(self, core): self.core = core - def _convertPyFile(self, p): - f = FileData(p["id"], p["url"], p["name"], p["plugin"], p["size"], - p["format_size"], p["status"], p["statusmsg"], - p["package"], p["error"], p["order"]) - return f - - @permission(PERMS.SETTINGS) - def getConfigValue(self, section, option): - """Retrieve config value. - - :param section: name of category, or plugin - :param option: config option - :return: config value as string - """ - value = self.core.config.get(section, option) - return to_string(value) - - @permission(PERMS.SETTINGS) - def setConfigValue(self, section, option, value): - """Set new config value. - - :param section: - :param option: - :param value: new config value - """ - if option in ("limit_speed", "max_speed"): #not so nice to update the limit - self.core.requestFactory.updateBucket() - - self.core.config.set(section, option, value) - - @permission(PERMS.SETTINGS) - def getConfig(self): - """Retrieves complete config of core. - - :return: list of `ConfigSection` - """ - return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [ - ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for - option, d in data.config.iteritems()])) for - section, data in self.core.config.getBaseSections()]) + ########################## + # Server Status + ########################## + @permission(PERMS.ALL) + def getServerVersion(self): + """pyLoad Core version """ + return self.core.version - @permission(PERMS.SETTINGS) - def getPluginConfig(self): - """Retrieves complete config for all plugins. + @permission(PERMS.LIST) + def statusServer(self): + """Some general information about the current status of pyLoad. - :return: list of `ConfigSection` + :return: `ServerStatus` """ - return dict([(section, ConfigSection(section, - data.name, data.description, data.long_desc)) for - section, data in self.core.config.getPluginSections()]) - - def configureSection(self, section): - data = self.core.config.config[section] - sec = ConfigSection(section, data.name, data.description, data.long_desc) - sec.items = [ConfigItem(option, d.name, d.description, - d.type, to_string(d.default), to_string(self.core.config.get(section, option))) - for - option, d in data.config.iteritems()] - - #TODO: config handler + serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()), + self.core.files.getQueueCount(), self.core.files.getFileCount(), 0, + not self.core.threadManager.pause and self.isTimeDownload(), + self.core.config['reconnect']['activated'] and self.isTimeReconnect()) - return sec + for pyfile in [x.active for x in self.core.threadManager.threads if x.active and isinstance(x.active, PyFile)]: + serverStatus.speed += pyfile.getSpeed() #bytes/s - def getConfigPointer(self): - """Config instance, not for RPC""" - return self.core.config + return serverStatus @permission(PERMS.STATUS) def pauseServer(self): @@ -197,31 +154,11 @@ class Api(Iface): self.core.config["reconnect"]["activated"] ^= True return self.core.config["reconnect"]["activated"] - @permission(PERMS.LIST) - def statusServer(self): - """Some general information about the current status of pyLoad. - - :return: `ServerStatus` - """ - serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()), - self.core.files.getQueueCount(), self.core.files.getFileCount(), 0, - not self.core.threadManager.pause and self.isTimeDownload(), - self.core.config['reconnect']['activated'] and self.isTimeReconnect()) - - for pyfile in [x.active for x in self.core.threadManager.threads if x.active and isinstance(x.active, PyFile)]: - serverStatus.speed += pyfile.getSpeed() #bytes/s - - return serverStatus - @permission(PERMS.STATUS) def freeSpace(self): """Available free space at download directory in bytes""" return free_space(self.core.config["general"]["download_folder"]) - @permission(PERMS.ALL) - def getServerVersion(self): - """pyLoad Core version """ - return self.core.version def kill(self): """Clean way to quit pyLoad""" @@ -269,18 +206,22 @@ class Api(Iface): end = self.core.config['reconnect']['endTime'].split(":") return compare_time(start, end) and self.core.config["reconnect"]["activated"] - @permission(PERMS.LIST) - def statusDownloads(self): - """ Status off all currently running downloads. - :return: list of `DownloadStatus` + def scanDownloadFolder(self): + pass + + @permission(PERMS.STATUS) + def getProgressInfo(self): + """ Status of all currently running tasks + + :return: list of `ProgressInfo` """ data = [] for pyfile in self.core.threadManager.getActiveFiles(): if not isinstance(pyfile, PyFile): continue - data.append(DownloadInfo( + data.append(ProgressInfo( pyfile.id, pyfile.name, pyfile.getSpeed(), pyfile.getETA(), pyfile.formatETA(), pyfile.getBytesLeft(), pyfile.getSize(), pyfile.formatSize(), pyfile.getPercent(), pyfile.status, pyfile.getStatusName(), pyfile.formatWait(), @@ -288,49 +229,81 @@ class Api(Iface): return data - @permission(PERMS.ADD) - def addPackage(self, name, links, dest=Destination.Queue, password=""): - """Adds a package, with links to desired destination. + ########################## + # Configuration + ########################## - :param name: name of the new package - :param links: list of urls - :param dest: `Destination` - :param password: password as string, can be empty - :return: package id of the new package + @permission(PERMS.SETTINGS) + def getConfigValue(self, section, option): + """Retrieve config value. + + :param section: name of category, or plugin + :param option: config option + :return: config value as string """ - if self.core.config['general']['folder_per_package']: - folder = name - else: - folder = "" + value = self.core.config.get(section, option) + return to_string(value) - if isabs(folder): - folder = folder.replace("/", "_") + @permission(PERMS.SETTINGS) + def setConfigValue(self, section, option, value): + """Set new config value. - folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "") + :param section: + :param option: + :param value: new config value + """ + if option in ("limit_speed", "max_speed"): #not so nice to update the limit + self.core.requestFactory.updateBucket() + + self.core.config.set(section, option, value) - self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)}) - pid = self.core.files.addPackage(name, folder, dest, password) - self.addFiles(pid, links) + @permission(PERMS.SETTINGS) + def getConfig(self): + """Retrieves complete config of core. - return pid + :return: list of `ConfigSection` + """ + return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [ + ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for + option, d in data.config.iteritems()])) for + section, data in self.core.config.getBaseSections()]) - @permission(PERMS.ADD) - def addFiles(self, pid, links): - """Adds files to specific package. - :param pid: package id - :param links: list of urls + @permission(PERMS.SETTINGS) + def getPluginConfig(self): + """Retrieves complete config for all plugins. + + :return: list of `ConfigSection` """ - hoster, crypter = self.core.pluginManager.parseUrls(links) + return dict([(section, ConfigSection(section, + data.name, data.description, data.long_desc)) for + section, data in self.core.config.getPluginSections()]) - if hoster: - self.core.files.addLinks(hoster, pid) + @permission(PERMS.SETTINGS) + def configureSection(self, section): + data = self.core.config.config[section] + sec = ConfigSection(section, data.name, data.description, data.long_desc) + sec.items = [ConfigItem(option, d.name, d.description, + d.type, to_string(d.default), to_string(self.core.config.get(section, option))) + for + option, d in data.config.iteritems()] - self.core.threadManager.createInfoThread(hoster, pid) - self.core.threadManager.createDecryptThread(crypter, pid) + #TODO: config handler - self.core.log.debug("Added %d links to package #%d " % (len(hoster), pid)) - self.core.files.save() + return sec + + + @permission(PERMS.SETTINGS) + def setConfigHandler(self, plugin, iid, value): + pass + + def getConfigRef(self): + """Config instance, not for RPC""" + return self.core.config + + ########################## + # Download Preparing + ########################## @permission(PERMS.ADD) def parseURLs(self, html=None, url=None): @@ -375,12 +348,12 @@ class Api(Iface): """ initiates online status check, will also decrypt files. :param urls: - :return: initial set of data as `OnlineCheck` instance containing the result id + :return: initial set of data as :class:`OnlineCheck` instance containing the result id """ data, crypter = self.core.pluginManager.parseUrls(urls) # initial result does not contain the crypter links - tmp = [(url, (url, OnlineStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data] + tmp = [(url, (url, LinkStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data] data = parseNames(tmp) result = {} @@ -401,7 +374,7 @@ class Api(Iface): :param urls: list of urls :param container: container file name :param data: file content - :return: online check + :return: :class:`OnlineCheck` """ th = open(join(self.core.config["general"]["download_folder"], "tmp_" + container), "wb") th.write(str(data)) @@ -435,67 +408,110 @@ class Api(Iface): result = parseNames((x, x) for x in links) return result + ########################## + # Adding/Deleting + ########################## + @permission(PERMS.ADD) - def generateAndAddPackages(self, links, dest=Destination.Queue): + def generateAndAddPackages(self, links, paused=False): """Generates and add packages :param links: list of urls - :param dest: `Destination` + :param paused: paused package :return: list of package ids """ - return [self.addPackage(name, urls, dest) for name, urls + return [self.addPackageP(name, urls, "", paused) for name, urls in self.generatePackages(links).iteritems()] + @permission(PERMS.ADD) + def autoAddLinks(self, links): + pass - @permission(PERMS.LIST) - def getPackageData(self, pid): - """Returns complete information about package, and included files. + @permission(PERMS.ADD) + def createPackage(self, name, folder, root, password="", site="", comment="", paused=False): + """Create a new package. - :param pid: package id - :return: `PackageData` with .links attribute + :param name: display name of the package + :param folder: folder name or relative path, abs path are not allowed + :param root: package id of root package, -1 for top level package + :param password: single pw or list of passwords seperated with new line + :param site: arbitrary url to site for more information + :param comment: arbitrary comment + :param paused: No downloads will be started when True + :return: pid of newly created package """ - data = self.core.files.getPackageData(int(pid)) - if not data: - raise PackageDoesNotExists(pid) + if isabs(folder): + folder = folder.replace("/", "_") - pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"], - data["queue"], data["order"], - links=[self._convertPyFile(x) for x in data["links"].itervalues()]) + folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "") - return pdata + self.core.log.info(_("Added package %(name)s as folder %(folder)s") % {"name": name, "folder": folder}) + pid = self.core.files.addPackage(name, folder, root, password, site, comment, paused) - @permission(PERMS.LIST) - def getPackageInfo(self, pid): - """Returns information about package, without detailed information about containing files + return pid - :param pid: package id - :return: `PackageData` with .fid attribute + + @permission(PERMS.ADD) + def addPackage(self, name, links, password=""): + """Convenient method to add a package to top-level and adding links. + + :return: package id """ - data = self.core.files.getPackageData(int(pid)) + self.addPackageChild(name, links, password, -1, False) - if not data: - raise PackageDoesNotExists(pid) + @permission(PERMS.ADD) + def addPackageP(self, name, links, password, paused): + """ Same as above with additional paused attribute. """ + self.addPackageChild(name, links, password, -1, paused) - pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"], - data["queue"], data["order"], - fids=[int(x) for x in data["links"]]) + @permission(PERMS.ADD) + def addPackageChild(self, name, links, password, root, paused): + """Adds a package, with links to desired package. - return pdata + :param root: parents package id + :return: package id of the new package + """ + if self.core.config['general']['folder_per_package']: + folder = name + else: + folder = "" - @permission(PERMS.LIST) - def getFileData(self, fid): - """Get complete information about a specific file. + pid = self.createPackage(name, folder, root, password) + self.addLinks(pid, links) - :param fid: file id - :return: `FileData` - """ - info = self.core.files.getFileData(int(fid)) - if not info: - raise FileDoesNotExists(fid) + return pid + + @permission(PERMS.ADD) + def addLinks(self, pid, links): + """Adds links to specific package. Automatical starts online status fetching. + + :param pid: package id + :param links: list of urls + """ + hoster, crypter = self.core.pluginManager.parseUrls(links) + + if hoster: + self.core.files.addLinks(hoster, pid) + self.core.threadManager.createInfoThread(hoster, pid) + + self.core.threadManager.createDecryptThread(crypter, pid) + + self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster)) + self.core.files.save() + + @permission(PERMS.ADD) + def uploadContainer(self, filename, data): + """Uploads and adds a container file to pyLoad. + + :param filename: filename, extension is important so it can correctly decrypted + :param data: file content + """ + th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb") + th.write(str(data)) + th.close() - fdata = self._convertPyFile(info.values()[0]) - return fdata + return self.addPackage(th.name, [th.name]) @permission(PERMS.DELETE) def deleteFiles(self, fids): @@ -503,8 +519,8 @@ class Api(Iface): :param fids: list of file ids """ - for id in fids: - self.core.files.deleteLink(int(id)) + for fid in fids: + self.core.files.deleteFile(fid) self.core.files.save() @@ -514,76 +530,113 @@ class Api(Iface): :param pids: list of package ids """ - for id in pids: - self.core.files.deletePackage(int(id)) + for pid in pids: + self.core.files.deletePackage(pid) self.core.files.save() + ########################## + # Collector + ########################## + @permission(PERMS.LIST) - def getQueue(self): - """Returns info about queue and packages, **not** about files, see `getQueueData` \ - or `getPackageData` instead. + def getCollector(self): + pass - :return: list of `PackageInfo` - """ - return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"], - pack["password"], pack["queue"], pack["order"], - pack["linksdone"], pack["sizedone"], pack["sizetotal"], - pack["linkstotal"]) - for pack in self.core.files.getInfoData(Destination.Queue).itervalues()] + @permission(PERMS.ADD) + def addToCollector(self, links): + pass + + @permission(PERMS.ADD) + def addFromCollector(self, name, paused): + pass + + @permission(PERMS.DELETE) + def deleteCollPack(self, name): + pass + + @permission(PERMS.DELETE) + def deleteCollLink(self, url): + pass + + @permission(PERMS.ADD) + def renameCollPack(self, name, new_name): + pass + + ############################# + # File Information retrival + ############################# @permission(PERMS.LIST) - def getQueueData(self): - """Return complete data about everything in queue, this is very expensive use it sparely.\ - See `getQueue` for alternative. + def getAllFiles(self): + """ same as `getFileTree` for toplevel root and full tree""" + return self.getFileTree(-1, True) - :return: list of `PackageData` - """ - return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"], - pack["password"], pack["queue"], pack["order"], - pack["linksdone"], pack["sizedone"], pack["sizetotal"], - links=[self._convertPyFile(x) for x in pack["links"].itervalues()]) - for pack in self.core.files.getCompleteData(Destination.Queue).itervalues()] + @permission(PERMS.LIST) + def getAllUnfinishedFiles(self): + """ same as `getUnfinishedFileTree for toplevel root and full tree""" + return self.getUnfinishedFileTree(-1, True) @permission(PERMS.LIST) - def getCollector(self): - """same as `getQueue` for collector. + def getFileTree(self, pid, full): + """ Retrieve data for specific package. full=True will retrieve all data available + and can result in greater delays. - :return: list of `PackageInfo` + :param pid: package id + :param full: go down the complete tree or only the first layer + :return: :class:`PackageView` """ - return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"], - pack["password"], pack["queue"], pack["order"], - pack["linksdone"], pack["sizedone"], pack["sizetotal"], - pack["linkstotal"]) - for pack in self.core.files.getInfoData(Destination.Collector).itervalues()] + return self.core.files.getView(pid, full, False) @permission(PERMS.LIST) - def getCollectorData(self): - """same as `getQueueData` for collector. + def getUnfinishedFileTree(self, pid, full): + """ Same as `getFileTree` but only contains unfinished files. - :return: list of `PackageInfo` + :param pid: package id + :param full: go down the complete tree or only the first layer + :return: :class:`PackageView` """ - return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"], - pack["password"], pack["queue"], pack["order"], - pack["linksdone"], pack["sizedone"], pack["sizetotal"], - links=[self._convertPyFile(x) for x in pack["links"].itervalues()]) - for pack in self.core.files.getCompleteData(Destination.Collector).itervalues()] + return self.core.files.getView(pid, full, False) - @permission(PERMS.MODIFY) - def pushToQueue(self, pid): - """Moves package from Collector to Queue. + @permission(PERMS.LIST) + def getPackageContent(self, pid): + """ Only retrieve content of a specific package. see `getFileTree`""" + return self.getFileTree(pid, False) + + @permission(PERMS.LIST) + def getPackageInfo(self, pid): + """Returns information about package, without detailed information about containing files :param pid: package id + :raises PackageDoesNotExists: + :return: :class:`PackageInfo` """ - self.core.files.setPackageLocation(pid, Destination.Queue) + info = self.core.files.getPackageInfo(pid) + if not info: + raise PackageDoesNotExists(pid) + return info - @permission(PERMS.MODIFY) - def pullFromQueue(self, pid): - """Moves package from Queue to Collector. + @permission(PERMS.LIST) + def getFileInfo(self, fid): + """ Info for specific file + + :param fid: file id + :raises FileDoesNotExists: + :return: :class:`FileInfo` - :param pid: package id """ - self.core.files.setPackageLocation(pid, Destination.Collector) + info = self.core.files.getFileInfo(fid) + if not info: + raise FileDoesNotExists(fid) + return info + + @permission(PERMS.LIST) + def findFiles(self, pattern): + pass + + ############################# + # Modify Downloads + ############################# @permission(PERMS.MODIFY) def restartPackage(self, pid): @@ -591,30 +644,26 @@ class Api(Iface): :param pid: package id """ - self.core.files.restartPackage(int(pid)) + self.core.files.restartPackage(pid) @permission(PERMS.MODIFY) def restartFile(self, fid): """Resets file status, so it will be downloaded again. - :param fid: file id + :param fid: file id """ - self.core.files.restartFile(int(fid)) + self.core.files.restartFile(fid) @permission(PERMS.MODIFY) def recheckPackage(self, pid): - """Proofes online status of all files in a package, also a default action when package is added. - - :param pid: - :return: - """ - self.core.files.reCheckPackage(int(pid)) + """Check online status of all files in a package, also a default action when package is added. """ + self.core.files.reCheckPackage(pid) @permission(PERMS.MODIFY) def stopAllDownloads(self): """Aborts all running downloads.""" - pyfiles = self.core.files.cache.values() + pyfiles = self.core.files.cachedFiles() for pyfile in pyfiles: pyfile.abortDownload() @@ -625,75 +674,76 @@ class Api(Iface): :param fids: list of file ids :return: """ - pyfiles = self.core.files.cache.values() - + pyfiles = self.core.files.cachedFiles() for pyfile in pyfiles: if pyfile.id in fids: pyfile.abortDownload() @permission(PERMS.MODIFY) - def setPackageName(self, pid, name): - """Renames a package. + def restartFailed(self): + """Restarts all failed failes.""" + self.core.files.restartFailed() - :param pid: package id - :param name: new package name - """ - pack = self.core.files.getPackage(pid) - pack.name = name - pack.sync() + ############################# + # Modify Files/Packages + ############################# @permission(PERMS.MODIFY) - def movePackage(self, destination, pid): - """Set a new package location. + def setFilePaused(self, fid, paused): + pass + + @permission(PERMS.MODIFY) + def setPackagePaused(self, pid, paused): + pass + + @permission(PERMS.MODIFY) + def setPackageFolder(self, pid, path): + pass + + @permission(PERMS.MODIFY) + def movePackage(self, pid, root): + """ Set a new root for specific package. This will also moves the files on disk\ + and will only work when no file is currently downloading. - :param destination: `Destination` :param pid: package id + :param root: package id of new root + :raises PackageDoesNotExists: When pid or root is missing + :return: False if package can't be moved """ - if destination not in (0, 1): return - self.core.files.setPackageLocation(pid, destination) + return self.core.files.movePackage(pid, root) @permission(PERMS.MODIFY) def moveFiles(self, fids, pid): - """Move multiple files to another package + """Move multiple files to another package. This will move the files on disk and\ + only work when files are not downloading. All files needs to be continuous ordered + in the current package. :param fids: list of file ids :param pid: destination package - :return: - """ - #TODO: implement - pass - - - @permission(PERMS.ADD) - def uploadContainer(self, filename, data): - """Uploads and adds a container file to pyLoad. - - :param filename: filename, extension is important so it can correctly decrypted - :param data: file content + :return: False if files can't be moved """ - th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb") - th.write(str(data)) - th.close() - - return self.addPackage(th.name, [th.name]) + return self.core.files.moveFiles(fids, pid) @permission(PERMS.MODIFY) def orderPackage(self, pid, position): - """Gives a package a new position. + """Set new position for a package. :param pid: package id - :param position: + :param position: new position, 0 for very beginning """ - self.core.files.reorderPackage(pid, position) + self.core.files.orderPackage(pid, position) @permission(PERMS.MODIFY) - def orderFile(self, fid, position): - """Gives a new position to a file within its package. + def orderFiles(self, fids, pid, position): + """ Set a new position for a bunch of files within a package. + All files have to be in the same package and must be **continuous**\ + in the package. That means no gaps between them. - :param fid: file id - :param position: + :param fids: list of file ids + :param pid: package id of parent package + :param position: new position: 0 for very beginning """ - self.core.files.reorderFile(fid, position) + self.core.files.orderFiles(fids, pid, position) @permission(PERMS.MODIFY) def setPackageData(self, pid, data): @@ -712,104 +762,38 @@ class Api(Iface): p.sync() self.core.files.save() - @permission(PERMS.DELETE) - def deleteFinished(self): - """Deletes all finished files and completly finished packages. - - :return: list of deleted package ids - """ - return self.core.files.deleteFinishedLinks() - - @permission(PERMS.MODIFY) - def restartFailed(self): - """Restarts all failed failes.""" - self.core.files.restartFailed() - - @permission(PERMS.LIST) - def getPackageOrder(self, destination): - """Returns information about package order. + ############################# + # User Interaction + ############################# - :param destination: `Destination` - :return: dict mapping order to package id - """ - - packs = self.core.files.getInfoData(destination) - order = {} - - for pid in packs: - pack = self.core.files.getPackageData(int(pid)) - while pack["order"] in order.keys(): #just in case - pack["order"] += 1 - order[pack["order"]] = pack["id"] - return order - - @permission(PERMS.LIST) - def getFileOrder(self, pid): - """Information about file order within package. - - :param pid: - :return: dict mapping order to file id - """ - rawData = self.core.files.getPackageData(int(pid)) - order = {} - for id, pyfile in rawData["links"].iteritems(): - while pyfile["order"] in order.keys(): #just in case - pyfile["order"] += 1 - order[pyfile["order"]] = pyfile["id"] - return order - - - @permission(PERMS.STATUS) - def isCaptchaWaiting(self): - """Indicates wether a captcha task is available - :return: bool - """ - self.core.lastClientConnected = time() - task = self.core.captchaManager.getTask() - return not task is None + @permission(PERMS.INTERACTION) + def isInteractionWaiting(self, mode): + pass - @permission(PERMS.STATUS) - def getCaptchaTask(self, exclusive=False): - """Returns a captcha task - - :param exclusive: unused - :return: `CaptchaTask` - """ - self.core.lastClientConnected = time() - task = self.core.captchaManager.getTask() - if task: - task.setWatingForUser(exclusive=exclusive) - data, type, result = task.getCaptcha() - t = CaptchaTask(int(task.id), standard_b64encode(data), type, result) - return t - else: - return CaptchaTask(-1) + @permission(PERMS.INTERACTION) + def getInteractionTask(self, mode): + pass - @permission(PERMS.STATUS) - def getCaptchaTaskStatus(self, tid): - """Get information about captcha task + @permission(PERMS.INTERACTION) + def setInteractionResult(self, iid, result): + pass - :param tid: task id - :return: string - """ - self.core.lastClientConnected = time() - t = self.core.captchaManager.getTaskByID(tid) - return t.getStatus() if t else "" + @permission(PERMS.INTERACTION) + def getAddonHandler(self): + pass - @permission(PERMS.STATUS) - def setCaptchaResult(self, tid, result): - """Set result for a captcha task + @permission(PERMS.INTERACTION) + def callAddonHandler(self, plugin, func, pid_or_fid): + pass - :param tid: task id - :param result: captcha result - """ - self.core.lastClientConnected = time() - task = self.core.captchaManager.getTaskByID(tid) - if task: - task.setResult(result) - self.core.captchaManager.removeTask(task) + @permission(PERMS.DOWNLOAD) + def generateDownloadLink(self, fid, timeout): + pass + ############################# + # Event Handling + ############################# @permission(PERMS.STATUS) def getEvents(self, uuid): @@ -821,6 +805,10 @@ class Api(Iface): # TODO pass + ############################# + # Account Methods + ############################# + @permission(PERMS.ACCOUNTS) def getAccounts(self, refresh): """Get information about all entered accounts. @@ -857,6 +845,10 @@ class Api(Iface): """ self.core.accountManager.removeAccount(plugin, account) + ############################# + # Auth+User Information + ############################# + @permission(PERMS.ALL) def login(self, username, password, remoteip=None): """Login into pyLoad, this **must** be called when using rpc before any methods can be used. @@ -881,6 +873,8 @@ class Api(Iface): if self.core.startedInGui and remoteip == "127.0.0.1": return "local" + self.core.log.info(_("User '%s' tried to log in") % username) + return self.core.db.checkAuth(username, password) def isAuthorized(self, func, userdata): @@ -907,7 +901,6 @@ class Api(Iface): raise UserDoesNotExists(username) - def getAllUserData(self): """returns all known user and info""" res = {} @@ -916,58 +909,57 @@ class Api(Iface): return res - @permission(PERMS.STATUS) + def changePassword(self, user, oldpw, newpw): + """ changes password for specific user """ + return self.core.db.changePassword(user, oldpw, newpw) + + def setUserPermission(self, user, permission, role): + self.core.db.setPermission(user, permission) + self.core.db.setRole(user, role) + + ############################# + # RPC Plugin Methods + ############################# + + @permission(PERMS.INTERACTION) def getServices(self): - """ A dict of available services, these can be defined by hook plugins. + """ A dict of available services, these can be defined by addon plugins. :return: dict with this style: {"plugin": {"method": "description"}} """ data = {} - for plugin, funcs in self.core.hookManager.methods.iteritems(): + for plugin, funcs in self.core.addonManager.methods.iteritems(): data[plugin] = funcs return data - @permission(PERMS.STATUS) + @permission(PERMS.INTERACTION) def hasService(self, plugin, func): - """Checks wether a service is available. + pass - :param plugin: - :param func: - :return: bool - """ - cont = self.core.hookManager.methods - return plugin in cont and func in cont[plugin] + @permission(PERMS.INTERACTION) + def call(self, plugin, func, arguments): + """Calls a service (a method in addon plugin). - @permission(PERMS.STATUS) - def call(self, info): - """Calls a service (a method in hook plugin). - - :param info: `ServiceCall` - :return: result :raises: ServiceDoesNotExists, when its not available :raises: ServiceException, when a exception was raised """ - plugin = info.plugin - func = info.func - args = info.arguments - if not self.hasService(plugin, func): raise ServiceDoesNotExists(plugin, func) try: - ret = self.core.hookManager.callRPC(plugin, func, args) - return str(ret) + ret = self.core.addonManager.callRPC(plugin, func, arguments) + return to_string(ret) except Exception, e: raise ServiceException(e.message) @permission(PERMS.STATUS) def getAllInfo(self): - """Returns all information stored by hook plugins. Values are always strings + """Returns all information stored by addon plugins. Values are always strings :return: {"plugin": {"name": value } } """ - return self.core.hookManager.getAllInfo() + return self.core.addonManager.getAllInfo() @permission(PERMS.STATUS) def getInfoByPlugin(self, plugin): @@ -976,12 +968,4 @@ class Api(Iface): :param plugin: pluginname :return: dict of attr names mapped to value {"name": value} """ - return self.core.hookManager.getInfo(plugin) - - def changePassword(self, user, oldpw, newpw): - """ changes password for specific user """ - return self.core.db.changePassword(user, oldpw, newpw) - - def setUserPermission(self, user, permission, role): - self.core.db.setPermission(user, permission) - self.core.db.setRole(user, role) + return self.core.addonManager.getInfo(plugin) diff --git a/module/FileManager.py b/module/FileManager.py new file mode 100644 index 000000000..cb3b2ae96 --- /dev/null +++ b/module/FileManager.py @@ -0,0 +1,564 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from time import time +from threading import RLock +from module.utils import lock + +from Api import PackageStatus, DownloadStatus as DS, PackageView, PackageDoesNotExists, FileDoesNotExists +from PyFile import PyFile +from PyPackage import PyPackage, RootPackage + +# invalidates the cache +def invalidate(func): + def new(*args): + args[0].filecount = -1 + args[0].queuecount = -1 + args[0].jobCache = {} + return func(*args) + + return new + + +class FileManager: + """Handles all request made to obtain information, + modify status or other request for links or packages""" + + ROOT_PACKAGE = -1 + + def __init__(self, core): + """Constructor""" + self.core = core + self.evm = core.eventManager + + # translations + self.statusMsg = [_("none"), _("offline"), _("online"), _("queued"), _("paused"), + _("finished"), _("skipped"), _("failed"), _("starting"), + _("waiting"), _("downloading"), _("temp. offline"), _("aborted"), + _("decrypting"), _("processing"), _("custom"), _("unknown")] + + self.files = {} # holds instances for files + self.packages = {} # same for packages + + self.jobCache = {} + + # locking the cache, db is already locked implicit + self.lock = RLock() + #self.lock._Verbose__verbose = True + + self.filecount = -1 # if an invalid value is set get current value from db + self.queuecount = -1 # number of package to be loaded + + self.db = self.core.db + + def save(self): + """saves all data to backend""" + self.db.commit() + + @lock + def syncSave(self): + """saves all data to backend and waits until all data are written""" + for pyfile in self.files.values(): + pyfile.sync() + + for pypack in self.packages.values(): + pypack.sync() + + self.db.syncSave() + + def cachedFiles(self): + return self.files.values() + + def cachedPackages(self): + return self.packages.values() + + def getCollector(self): + pass + + @invalidate + def addLinks(self, data, package): + """Add links, data = (plugin, url) tuple. Internal method should use API.""" + self.db.addLinks(data, package) + self.evm.dispatchEvent("packageUpdated", package) + + + @invalidate + def addPackage(self, name, folder, root, password, site, comment, paused): + """Adds a package to database""" + pid = self.db.addPackage(name, folder, root, password, site, comment, + PackageStatus.Paused if paused else PackageStatus.Ok) + p = self.db.getPackageInfo(pid) + + self.evm.dispatchEvent("packageInserted", pid, p.root, p.packageorder) + return pid + + + @lock + def getPackage(self, pid): + """return package instance""" + if pid == self.ROOT_PACKAGE: + return RootPackage(self) + elif pid in self.packages: + pack = self.packages[pid] + pack.timestamp = time() + return pack + else: + info = self.db.getPackageInfo(pid, False) + if not info: return None + + pack = PyPackage.fromInfoData(self, info) + self.packages[pid] = pack + + return pack + + @lock + def getPackageInfo(self, pid): + """returns dict with package information""" + if pid == self.ROOT_PACKAGE: + pack = RootPackage(self).toInfoData() + elif pid in self.packages: + pack = self.packages[pid].toInfoData() + pack.stats = self.db.getStatsForPackage(pid) + else: + pack = self.db.getPackageInfo(pid) + + if not pack: return None + + #todo: fill child packs and files + packs = self.db.getAllPackages(root=pid) + if pid in packs: del packs[pid] + pack.pids = packs.keys() + + files = self.db.getAllFiles(package=pid) + pack.fids = files.keys() + + return pack + + @lock + def getFile(self, fid): + """returns pyfile instance""" + if fid in self.files: + return self.files[fid] + else: + info = self.db.getFileInfo(fid) + if not info: return None + + f = PyFile.fromInfoData(self, info) + self.files[fid] = f + return f + + @lock + def getFileInfo(self, fid): + """returns dict with file information""" + if fid in self.files: + return self.files[fid].toInfoData() + + return self.db.getFileInfo(fid) + + @lock + def getView(self, pid, full, unfinished): + """ return a PackageView and fill the info data of containing packages. + optional filter only unfnished files + """ + view = PackageView(pid) + + # for depth=1, we dont need to retrieve all files/packages + root = pid if not full else None + + packs = self.db.getAllPackages(root) + files = self.db.getAllFiles(package=root, unfinished=unfinished) + + # updating from cache + for fid, f in self.files.iteritems(): + if fid in files: + files[fid] = f.toInfoData() + + # foreign pid, dont overwrite local pid ! + for fpid, p in self.packages.iteritems(): + if fpid in packs: + # copy the stats data + stats = packs[fpid].stats + packs[fpid] = p.toInfoData() + packs[fpid].stats = stats + + # root package is not in database, create an instance + if pid == self.ROOT_PACKAGE: + view.root = RootPackage(self).toInfoData() + packs[self.ROOT_PACKAGE] = view.root + elif pid in packs: + view.root = packs[pid] + else: # package does not exists + return view + + # linear traversal over all data + for fpid, p in packs.iteritems(): + if p.fids is None: p.fids = [] + if p.pids is None: p.pids = [] + + root = packs.get(p.root, None) + if root: + if root.pids is None: root.pids = [] + root.pids.append(fpid) + + for fid, f in files.iteritems(): + p = packs.get(f.package, None) + if p: p.fids.append(fid) + + + # cutting of tree is not good in runtime, only saves bandwidth + # need to remove some entries + if full and pid > -1: + keep = [] + queue = [pid] + while queue: + fpid = queue.pop() + keep.append(fpid) + queue.extend(packs[fpid].pids) + + # now remove unneeded data + for fpid in packs.keys(): + if fpid not in keep: + del packs[fpid] + + for fid, f in files.items(): + if f.package not in keep: + del files[fid] + + #remove root + del packs[pid] + view.files = files + view.packages = packs + + return view + + + @lock + def getJob(self, occ): + """get suitable job""" + + #TODO needs to be approved for new database + #TODO clean mess + #TODO improve selection of valid jobs + + if occ in self.jobCache: + if self.jobCache[occ]: + id = self.jobCache[occ].pop() + if id == "empty": + pyfile = None + self.jobCache[occ].append("empty") + else: + pyfile = self.getFile(id) + else: + jobs = self.db.getJob(occ) + jobs.reverse() + if not jobs: + self.jobCache[occ].append("empty") + pyfile = None + else: + self.jobCache[occ].extend(jobs) + pyfile = self.getFile(self.jobCache[occ].pop()) + + else: + self.jobCache = {} #better not caching to much + jobs = self.db.getJob(occ) + jobs.reverse() + self.jobCache[occ] = jobs + + if not jobs: + self.jobCache[occ].append("empty") + pyfile = None + else: + pyfile = self.getFile(self.jobCache[occ].pop()) + + + return pyfile + + + def getFileCount(self): + """returns number of files""" + + if self.filecount == -1: + self.filecount = self.db.filecount() + + return self.filecount + + def getQueueCount(self, force=False): + """number of files that have to be processed""" + if self.queuecount == -1 or force: + self.queuecount = self.db.queuecount() + + return self.queuecount + + def scanDownloadFolder(self): + pass + + def searchFile(self, pattern): + return self.db.getAllFiles(search=pattern) + + @lock + @invalidate + def deletePackage(self, pid): + """delete package and all contained links""" + + p = self.getPackage(pid) + if not p: return + + oldorder = p.packageorder + root = p.root + + for pyfile in self.cachedFiles(): + if pyfile.packageid == pid: + pyfile.abortDownload() + + # TODO: delete child packages + # TODO: delete folder + + self.db.deletePackage(pid) + self.releasePackage(pid) + + for pack in self.cachedPackages(): + if pack.root == root and pack.order > oldorder: + pack.order -= 1 + + self.evm.dispatchEvent("packageDeleted", pid) + + @lock + @invalidate + def deleteFile(self, fid): + """deletes links""" + + f = self.getFile(fid) + if not f: return + + pid = f.packageid + order = f.fileorder + + if fid in self.core.threadManager.processingIds(): + f.abortDownload() + + # TODO: delete real file + + self.db.deleteFile(fid, f.fileorder, f.packageid) + self.releaseFile(fid) + + for pyfile in self.files.itervalues(): + if pyfile.packageid == pid and pyfile.fileorder > order: + pyfile.fileorder -= 1 + + self.evm.dispatchEvent("fileDeleted", fid, pid) + + @lock + def releaseFile(self, fid): + """removes pyfile from cache""" + if fid in self.files: + del self.files[fid] + + @lock + def releasePackage(self, pid): + """removes package from cache""" + if pid in self.packages: + del self.packages[pid] + + def updateFile(self, pyfile): + """updates file""" + self.db.updateFile(pyfile) + self.evm.dispatchEvent("fileUpdated", pyfile.fid, pyfile.packageid) + + def updatePackage(self, pypack): + """updates a package""" + self.db.updatePackage(pypack) + self.evm.dispatchEvent("packageUpdated", pypack.pid) + + @invalidate + def updateFileInfo(self, data, pid): + """ updates file info (name, size, status,[ hash,] url)""" + self.db.updateLinkInfo(data) + self.evm.dispatchEvent("packageUpdated", pid) + + def checkAllLinksFinished(self): + """checks if all files are finished and dispatch event""" + + if not self.getQueueCount(True): + self.core.addonManager.dispatchEvent("allDownloadsFinished") + self.core.log.debug("All downloads finished") + return True + + return False + + def checkAllLinksProcessed(self, fid=-1): + """checks if all files was processed and pyload would idle now, needs fid which will be ignored when counting""" + + # reset count so statistic will update (this is called when dl was processed) + self.resetCount() + + if not self.db.processcount(fid): + self.core.addonManager.dispatchEvent("allDownloadsProcessed") + self.core.log.debug("All downloads processed") + return True + + return False + + def checkPackageFinished(self, pyfile): + """ checks if package is finished and calls addonmanager """ + + ids = self.db.getUnfinished(pyfile.packageid) + if not ids or (pyfile.id in ids and len(ids) == 1): + if not pyfile.package().setFinished: + self.core.log.info(_("Package finished: %s") % pyfile.package().name) + self.core.addonManager.packageFinished(pyfile.package()) + pyfile.package().setFinished = True + + def resetCount(self): + self.queuecount = -1 + + @lock + @invalidate + def restartPackage(self, pid): + """restart package""" + for pyfile in self.cachedFiles(): + if pyfile.packageid == pid: + self.restartFile(pyfile.id) + + self.db.restartPackage(pid) + + if pid in self.packages: + self.packages[pid].setFinished = False + + self.evm.dispatchEvent("packageUpdated", pid) + + @lock + @invalidate + def restartFile(self, fid): + """ restart file""" + if fid in self.files: + f = self.files[fid] + f.status = DS.Queued + f.name = f.url + f.error = "" + f.abortDownload() + + self.db.restartFile(fid) + self.evm.dispatchEvent("fileUpdated", fid) + + + @lock + @invalidate + def orderPackage(self, pid, position): + + p = self.getPackageInfo(pid) + self.db.orderPackage(pid, p.root, p.packageorder, position) + + for pack in self.packages.itervalues(): + if pack.root != p.root or pack.packageorder < 0: continue + if pack.pid == pid: + pack.packageorder = position + if p.packageorder > position: + if position <= pack.packageorder < p.packageorder: + pack.packageorder += 1 + elif p.order < position: + if position >= pack.packageorder > p.packageorder: + pack.packageorder -= 1 + + self.db.commit() + + self.evm.dispatchEvent("packageReordered", pid, position, p.root) + + @lock + @invalidate + def orderFiles(self, fids, pid, position): + + files = [self.getFileInfo(fid) for fid in fids] + orders = [f.fileorder for f in files] + if min(orders) + len(files) != max(orders) + 1: + raise Exception("Tried to reorder non continous block of files") + + # minimum fileorder + f = reduce(lambda x,y: x if x.fileorder < y.fileorder else y, files) + order = f.fileorder + + self.db.orderFiles(pid, fids, order, position) + diff = len(fids) + + if f.fileorder > position: + for pyfile in self.files.itervalues(): + if pyfile.packageid != f.package or pyfile.fileorder < 0: continue + if position <= pyfile.fileorder < f.fileorder: + pyfile.fileorder += diff + + for i, fid in enumerate(fids): + if fid in self.files: + self.files[fid].fileorder = position + i + + elif f.fileorder < position: + for pyfile in self.files.itervalues(): + if pyfile.packageid != f.package or pyfile.fileorder < 0: continue + if position >= pyfile.fileorder >= f.fileorder+diff: + pyfile.fileorder -= diff + + for i, fid in enumerate(fids): + if fid in self.files: + self.files[fid].fileorder = position -diff + i + 1 + + self.db.commit() + + self.evm.dispatchEvent("filesReordered", pid) + + @lock + @invalidate + def movePackage(self, pid, root): + """ move pid - root """ + + p = self.getPackageInfo(pid) + dest = self.getPackageInfo(root) + if not p: raise PackageDoesNotExists(pid) + if not dest: raise PackageDoesNotExists(root) + + # cantor won't be happy if we put the package in itself + if pid == root or p.root == root: return False + + # TODO move real folders + + # we assume pack is not in use anyway, so we can release it + self.releasePackage(pid) + self.db.movePackage(p.root, p.packageorder, pid, root) + + return True + + + + @lock + @invalidate + def moveFiles(self, fids, pid): + """ move all fids to pid """ + + f = self.getFileInfo(fids[0]) + if not f or f.package == pid: + return False + if not self.getPackageInfo(pid): + raise PackageDoesNotExists(pid) + + # TODO move real files + + self.db.moveFiles(f.package, fids, pid) + + return True + + + def reCheckPackage(self, pid): + """ recheck links in package """ + data = self.db.getPackageData(pid) + + urls = [] + + for pyfile in data.itervalues(): + if pyfile.status not in (DS.NA, DS.Finished, DS.Skipped): + urls.append((pyfile.url, pyfile.pluginname)) + + self.core.threadManager.createInfoThread(urls, pid) + + + @invalidate + def restartFailed(self): + """ restart all failed links """ + # failed should not be in cache anymore, so working on db is sufficient + self.db.restartFailed() diff --git a/module/HookManager.py b/module/HookManager.py deleted file mode 100644 index f3201738d..000000000 --- a/module/HookManager.py +++ /dev/null @@ -1,253 +0,0 @@ -# -*- 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 . - - @author: RaNaN, mkaay -""" -import __builtin__ - -from traceback import print_exc -from thread import start_new_thread -from threading import RLock - -from types import MethodType - -from module.threads.HookThread import HookThread -from module.plugins.PluginManager import literal_eval -from utils import lock, to_string - -class HookManager: - """ Manages hooks, loading, unloading. """ - - def __init__(self, core): - self.core = core - self.config = self.core.config - - __builtin__.hookManager = self #needed to let hooks register themself - - self.log = self.core.log - self.plugins = {} - self.methods = {} # dict of names and list of methods usable by rpc - self.events = {} # Contains event that will be registred - - self.lock = RLock() - self.createIndex() - - #registering callback for config event - self.config.changeCB = MethodType(self.dispatchEvent, "configChanged", basestring) - - # manage hooks an config change - self.addEvent("configChanged", self.manageHooks) - - @lock - def callInHooks(self, event, *args): - """ Calls a method in all hooks and catch / log errors""" - for plugin in self.plugins.itervalues(): - self.call(plugin, event, *args) - self.dispatchEvent(event, *args) - - def call(self, hook, f, *args): - try: - func = getattr(hook, f) - return func(*args) - except Exception, e: - hook.logError(_("Error when executing %s" % f), e) - if self.core.debug: - print_exc() - - def addRPC(self, plugin, func, doc): - doc = doc.strip() if doc else "" - - if plugin in self.methods: - self.methods[plugin][func] = doc - else: - self.methods[plugin] = {func: doc} - - def callRPC(self, plugin, func, args): - if not args: args = [] - else: - args = literal_eval(args) - - plugin = self.plugins[plugin] - f = getattr(plugin, func) - return f(*args) - - @lock - def createIndex(self): - active = [] - deactive = [] - - for pluginname in self.core.pluginManager.getPlugins("hooks"): - try: - # check first for builtin plugin - attrs = self.core.pluginManager.loadAttributes("hooks", pluginname) - internal = attrs.get("internal", False) - - if internal or self.core.config.get(pluginname, "activated"): - pluginClass = self.core.pluginManager.loadClass("hooks", pluginname) - - if not pluginClass: continue - - plugin = pluginClass(self.core, self) - self.plugins[pluginClass.__name__] = plugin - - # hide internals from printing - if not internal and plugin.isActivated(): - active.append(pluginClass.__name__) - else: - self.log.debug("Loaded internal plugin: %s" % pluginClass.__name__) - else: - deactive.append(pluginname) - - - except: - self.log.warning(_("Failed activating %(name)s") % {"name": pluginname}) - if self.core.debug: - print_exc() - - self.log.info(_("Activated plugins: %s") % ", ".join(sorted(active))) - self.log.info(_("Deactivate plugins: %s") % ", ".join(sorted(deactive))) - - def manageHooks(self, plugin, name, value): - # check if section was a plugin - if plugin not in self.core.pluginManager.getPlugins("hooks"): - return - - if name == "activated" and value: - self.activateHook(plugin) - elif name == "activated" and not value: - self.deactivateHook(plugin) - - @lock - def activateHook(self, plugin): - #check if already loaded - if plugin in self.plugins: - return - - pluginClass = self.core.pluginManager.loadClass("hooks", plugin) - - if not pluginClass: return - - self.log.debug("Plugin loaded: %s" % plugin) - - plugin = pluginClass(self.core, self) - self.plugins[pluginClass.__name__] = plugin - - # active the hook in new thread - start_new_thread(plugin.activate, tuple()) - self.registerEvents() - - @lock - def deactivateHook(self, plugin): - if plugin not in self.plugins: - return - else: - hook = self.plugins[plugin] - - if hook.__internal__: return - - self.call(hook, "deactivate") - self.log.debug("Plugin deactivated: %s" % plugin) - - #remove periodic call - self.log.debug("Removed callback %s" % self.core.scheduler.removeJob(hook.cb)) - del self.plugins[hook.__name__] - - #remove event listener - for f in dir(hook): - if f.startswith("__") or type(getattr(hook, f)) != MethodType: - continue - self.core.eventManager.removeFromEvents(getattr(hook, f)) - - def activateHooks(self): - self.log.info(_("Activating Plugins...")) - for plugin in self.plugins.itervalues(): - if plugin.isActivated(): - self.call(plugin, "activate") - - self.registerEvents() - - def deactivateHooks(self): - """ Called when core is shutting down """ - self.log.info(_("Deactivating Plugins...")) - for plugin in self.plugins.itervalues(): - self.call(plugin, "deactivate") - - def downloadPreparing(self, pyfile): - self.callInHooks("downloadPreparing", pyfile) - - def downloadFinished(self, pyfile): - self.callInHooks("downloadFinished", pyfile) - - def downloadFailed(self, pyfile): - self.callInHooks("downloadFailed", pyfile) - - def packageFinished(self, package): - self.callInHooks("packageFinished", package) - - def beforeReconnecting(self, ip): - self.callInHooks("beforeReconnecting", ip) - - def afterReconnecting(self, ip): - self.callInHooks("afterReconnecting", ip) - - @lock - def startThread(self, function, *args, **kwargs): - HookThread(self.core.threadManager, function, args, kwargs) - - def activePlugins(self): - """ returns all active plugins """ - return [x for x in self.plugins.itervalues() if x.isActivated()] - - def getAllInfo(self): - """returns info stored by hook plugins""" - info = {} - for name, plugin in self.plugins.iteritems(): - if plugin.info: - #copy and convert so str - info[name] = dict( - [(x, to_string(y)) for x, y in plugin.info.iteritems()]) - return info - - def getInfo(self, plugin): - info = {} - if plugin in self.plugins and self.plugins[plugin].info: - info = dict([(x, to_string(y)) - for x, y in self.plugins[plugin].info.iteritems()]) - - return info - - def addEventListener(self, plugin, func, event): - if plugin not in self.events: - self.events[plugin] = [] - self.events[plugin].append((func, event)) - - def registerEvents(self): - for name, plugin in self.plugins.iteritems(): - if name in self.events: - for func, event in self.events[name]: - self.addEvent(event, getattr(plugin, func)) - # clean up - del self.events[name] - - def addConfigHandler(self, plugin, func): - pass #TODO - - def addEvent(self, *args): - self.core.eventManager.addEvent(*args) - - def dispatchEvent(self, *args): - self.core.eventManager.dispatchEvent(*args) - diff --git a/module/PyFile.py b/module/PyFile.py index 4f8b95124..5e6a3fae3 100644 --- a/module/PyFile.py +++ b/module/PyFile.py @@ -14,78 +14,101 @@ along with this program; if not, see . @author: RaNaN - @author: mkaay """ - from time import sleep, time from threading import RLock -from module.utils import formatSize, lock +from module.utils import format_size, format_time, lock + +from Api import FileInfo, DownloadInfo, DownloadStatus statusMap = { - "finished": 0, - "offline": 1, - "online": 2, - "queued": 3, - "skipped": 4, - "waiting": 5, - "temp. offline": 6, - "starting": 7, - "failed": 8, - "aborted": 9, - "decrypting": 10, - "custom": 11, - "downloading": 12, - "processing": 13, - "unknown": 14, -} - - -def setSize(self, value): - self._size = int(value) + "none": 0, + "offline": 1, + "online": 2, + "queued": 3, + "paused": 4, + "finished": 5, + "skipped": 6, + "failed": 7, + "starting": 8, + "waiting": 9, + "downloading": 10, + "temp. offline": 11, + "aborted": 12, + "decrypting": 13, + "processing": 14, + "custom": 15, + "unknown": 16, + } class PyFile(object): """ Represents a file object at runtime """ - __slots__ = ("m", "id", "url", "_name", "name", "size", "_size", "status", "pluginname", "packageid", - "error", "order", "lock", "plugin", "waitUntil", "active", "abort", "statusname", + __slots__ = ("m", "fid", "_name", "_size", "filestatus", "media", "added", "fileorder", + "url", "pluginname", "hash", "status", "error", "packageid", + "lock", "plugin", "waitUntil", "active", "abort", "statusname", "reconnected", "progress", "maxprogress", "pluginclass") - def __init__(self, manager, id, url, name, size, status, error, pluginname, package, order): + @staticmethod + def fromInfoData(m, info): + f = PyFile(m, info.fid, info.name, info.size, info.status, info.media, info.added, info.fileorder, + "", "", "", DownloadStatus.NA, "", info.package) + if info.download: + f.url = info.download.url + f.pluginname = info.download.plugin + f.hash = info.download.hash + f.status = info.download.status + f.error = info.download.error + + return f + + def __init__(self, manager, fid, name, size, filestatus, media, added, fileorder, + url, pluginname, hash, status, error, package): + self.m = manager - - self.id = int(id) - self.url = url + + self.fid = int(fid) self._name = name - self.size = size - self.status = status + self._size = size + self.filestatus = filestatus + self.media = media + self.added = added + self.fileorder = fileorder + self.url = url self.pluginname = pluginname - self.packageid = package #should not be used, use package() instead + self.hash = hash + self.status = status self.error = error - self.order = order + self.packageid = package #should not be used, use package() instead # database information ends here self.lock = RLock() - + self.plugin = None #self.download = None - + self.waitUntil = 0 # time() + time to wait - + # status attributes self.active = False #obsolete? self.abort = False self.reconnected = False self.statusname = None - + self.progress = 0 self.maxprogress = 100 - self.m.cache[int(id)] = self + @property + def id(self): + self.m.core.log.debug("Deprecated attr .id, use .fid instead") + return self.fid + def setSize(self, value): + self._size = int(value) # will convert all sizes to ints size = property(lambda self: self._size, setSize) @@ -120,19 +143,17 @@ class PyFile(object): @lock def hasPlugin(self): - """Thread safe way to determine this file has initialized plugin attribute - - :return: - """ + """Thread safe way to determine this file has initialized plugin attribute""" return hasattr(self, "plugin") and self.plugin - + def package(self): """ return package instance""" return self.m.getPackage(self.packageid) def setStatus(self, status): self.status = statusMap[status] - self.sync() #@TODO needed aslong no better job approving exists + # needs to sync so status is written to database + self.sync() def setCustomStatus(self, msg, status="processing"): self.statusname = msg @@ -143,60 +164,36 @@ class PyFile(object): return self.m.statusMsg[self.status] else: return self.statusname - + def hasStatus(self, status): return statusMap[status] == self.status - + def sync(self): """sync PyFile instance with database""" - self.m.updateLink(self) + self.m.updateFile(self) @lock def release(self): """sync and remove from cache""" - # file has valid package - if self.packageid > 0: - self.sync() - if hasattr(self, "plugin") and self.plugin: self.plugin.clean() del self.plugin - self.m.releaseLink(self.id) - - def delete(self): - """delete pyfile from database""" - self.m.deleteLink(self.id) - - def toDict(self): - """return dict with all information for interface""" - return self.toDbDict() - - def toDbDict(self): - """return data as dict for databse - - format: - - { - id: {'url': url, 'name': name ... } - } - - """ - return { - self.id: { - 'id': self.id, - 'url': self.url, - 'name': self.name, - 'plugin': self.pluginname, - 'size': self.getSize(), - 'format_size': self.formatSize(), - 'status': self.status, - 'statusmsg': self.getStatusName(), - 'package': self.packageid, - 'error': self.error, - 'order': self.order - } - } + self.m.releaseFile(self.fid) + + + def toInfoData(self): + return FileInfo(self.fid, self.getName(), self.packageid, self.getSize(), self.filestatus, + self.media, self.added, self.fileorder, DownloadInfo( + self.url, self.pluginname, self.hash, self.status, self.getStatusName(), self.error + ) + ) + + def getPath(self): + pass + + def move(self, pid): + pass def abortDownload(self): """abort pyfile if possible""" @@ -205,19 +202,19 @@ class PyFile(object): if self.plugin and self.plugin.req: self.plugin.req.abortDownloads() sleep(0.1) - + self.abort = False if self.hasPlugin() and self.plugin.req: self.plugin.req.abortDownloads() self.release() - + def finishIfDone(self): """set status to finish and release file if every thread is finished with it""" if self.id in self.m.core.threadManager.processingIds(): return False - + self.setStatus("finished") self.release() self.m.checkAllLinksFinished() @@ -225,62 +222,50 @@ class PyFile(object): def checkIfProcessed(self): self.m.checkAllLinksProcessed(self.id) - + def formatWait(self): """ formats and return wait time in humanreadable format """ - seconds = self.waitUntil - time() - - if seconds < 0: return "00:00:00" - - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - + return format_time(self.waitUntil - time()) + def formatSize(self): """ formats size to readable format """ - return formatSize(self.getSize()) + return format_size(self.getSize()) def formatETA(self): """ formats eta to readable format """ - seconds = self.getETA() - - if seconds < 0: return "00:00:00" - - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - + return format_time(self.getETA()) + def getSpeed(self): """ calculates speed """ try: return self.plugin.req.speed except: return 0 - + def getETA(self): """ gets established time of arrival""" try: return self.getBytesLeft() / self.getSpeed() except: return 0 - + def getBytesLeft(self): """ gets bytes left """ try: return self.plugin.req.size - self.plugin.req.arrived except: return 0 - + def getPercent(self): """ get % of download """ - if self.status == 12: + if self.status == DownloadStatus.Downloading: try: return self.plugin.req.percent except: return 0 else: return self.progress - + def getSize(self): """ get size of download """ try: @@ -290,7 +275,7 @@ class PyFile(object): return self.size except: return self.size - + def notifyChange(self): self.m.core.eventManager.dispatchEvent("linkUpdated", self.id, self.packageid) diff --git a/module/PyPackage.py b/module/PyPackage.py index 970982e68..d0739124f 100644 --- a/module/PyPackage.py +++ b/module/PyPackage.py @@ -14,48 +14,60 @@ along with this program; if not, see . @author: RaNaN - @author: mkaay """ -class PyPackage(): +from time import time + +from module.utils.fs import join + +from Api import PackageInfo, PackageStatus + +class PyPackage: """ Represents a package object at runtime """ - def __init__(self, manager, id, name, folder, site, password, queue, order): + + @staticmethod + def fromInfoData(m, info): + return PyPackage(m, info.pid, info.name, info.folder, info.root, + info.site, info.comment, info.password, info.added, info.status, info.packageorder) + + def __init__(self, manager, pid, name, folder, root, site, comment, password, added, status, packageorder): self.m = manager - self.m.packageCache[int(id)] = self - self.id = int(id) + self.pid = pid self.name = name self.folder = folder + self.root = root self.site = site + self.comment = comment self.password = password - self.queue = queue - self.order = order - self.setFinished = False - - def toDict(self): - """ Returns a dictionary representation of the data. - - :return: dict: {id: { attr: value }} - """ - return { - self.id: { - 'id': self.id, - 'name': self.name, - 'folder': self.folder, - 'site': self.site, - 'password': self.password, - 'queue': self.queue, - 'order': self.order, - 'links': {} - } - } + self.added = added + self.status = status + self.packageorder = packageorder + self.timestamp = time() + + @property + def id(self): + self.m.core.log.debug("Deprecated package attr .id, use .pid instead") + return self.pid + + def isStale(self): + return self.timestamp + 30 * 60 > time() + + def toInfoData(self): + return PackageInfo(self.pid, self.name, self.folder, self.root, self.site, + self.comment, self.password, self.added, self.status, self.packageorder + ) def getChildren(self): """get information about contained links""" return self.m.getPackageData(self.id)["links"] + def getPath(self, name=""): + self.timestamp = time() + return join(self.m.getPackage(self.root).getPath(), self.folder, name) + def sync(self): """sync with db""" self.m.updatePackage(self) @@ -77,3 +89,21 @@ class PyPackage(): def notifyChange(self): self.m.core.eventManager.dispatchEvent("packageUpdated", self.id) + + +class RootPackage(PyPackage): + def __init__(self, m): + PyPackage.__init__(self, m, -1, "root", "", -2, "", "", "", 0, PackageStatus.Ok, 0) + + def getPath(self, name=""): + return join(self.m.core.config["general"]["download_folder"], name) + + # no database operations + def sync(self): + pass + + def delete(self): + pass + + def release(self): + pass \ No newline at end of file diff --git a/module/database/DatabaseBackend.py b/module/database/DatabaseBackend.py index 32f75328c..8159446bd 100644 --- a/module/database/DatabaseBackend.py +++ b/module/database/DatabaseBackend.py @@ -16,16 +16,13 @@ @author: RaNaN @author: mkaay """ -from threading import Thread -from threading import Event -from os import remove -from os.path import exists +from threading import Thread, Event from shutil import move from Queue import Queue from traceback import print_exc -from module.utils.fs import chmod +from module.utils.fs import chmod, exists, remove try: from pysqlite2 import dbapi2 as sqlite3 @@ -33,7 +30,7 @@ except: import sqlite3 DB = None -DB_VERSION = 4 +DB_VERSION = 5 def set_DB(db): global DB @@ -67,6 +64,18 @@ def inner(f): return x +class DatabaseMethods: + # stubs for autocompletion + core = None + manager = None + conn = None + c = None + + @classmethod + def register(cls): + DatabaseBackend.registerSub(cls) + + class DatabaseJob(): def __init__(self, f, *args, **kwargs): self.done = Event() @@ -122,34 +131,60 @@ class DatabaseBackend(Thread): Thread.__init__(self) self.setDaemon(True) self.core = core + self.manager = None # setted later + self.running = Event() self.jobs = Queue() - self.setuplock = Event() - set_DB(self) def setup(self): + self.start() - self.setuplock.wait() + self.running.wait() - def run(self): + def init(self): """main loop, which executes commands""" - convert = self._checkVersion() #returns None or current version + + version = self._checkVersion() self.conn = sqlite3.connect(self.DB_FILE) chmod(self.DB_FILE, 0600) - self.c = self.conn.cursor() #compatibility + self.c = self.conn.cursor() - if convert is not None: - self._convertDB(convert) + if version is not None and version < DB_VERSION: + success = self._convertDB(version) - self._createTables() + # delete database + if not success: + self.c.close() + self.conn.close() + try: + self.manager.core.log.warning(_("Filedatabase was deleted due to incompatible version.")) + except: + print "Filedatabase was deleted due to incompatible version." + + remove(self.VERSION_FILE) + move(self.DB_FILE, self.DB_FILE + ".backup") + f = open(self.VERSION_FILE, "wb") + f.write(str(DB_VERSION)) + f.close() + + self.conn = sqlite3.connect(self.DB_FILE) + chmod(self.DB_FILE, 0600) + self.c = self.conn.cursor() + + self._createTables() self.conn.commit() - self.setuplock.set() + + def run(self): + try: + self.init() + finally: + self.running.set() while True: j = self.jobs.get() @@ -159,51 +194,40 @@ class DatabaseBackend(Thread): break j.processJob() - @queue + def shutdown(self): + self.running.clear() + self._shutdown() + + @queue + def _shutdown(self): self.conn.commit() self.jobs.put("quit") def _checkVersion(self): - """ check db version and delete it if needed""" + """ get db version""" if not exists(self.VERSION_FILE): f = open(self.VERSION_FILE, "wb") f.write(str(DB_VERSION)) f.close() return - if exists("files.db") and not exists(self.DB_FILE): - move("files.db", self.DB_FILE) - f = open(self.VERSION_FILE, "rb") v = int(f.read().strip()) f.close() - if v < DB_VERSION: - if v < 2: - try: - self.manager.core.log.warning(_("Filedatabase was deleted due to incompatible version.")) - except: - print "Filedatabase was deleted due to incompatible version." - remove(self.VERSION_FILE) - move(self.DB_FILE, self.DB_FILE + ".backup") - f = open(self.VERSION_FILE, "wb") - f.write(str(DB_VERSION)) - f.close() - return v + + return v def _convertDB(self, v): try: - getattr(self, "_convertV%i" % v)() + return getattr(self, "_convertV%i" % v)() except: - try: - self.core.log.error(_("Filedatabase could NOT be converted.")) - except: - print "Filedatabase could NOT be converted." + return False #--convert scripts start - def _convertV4(self): - pass + def _convertV5(self): + return False #--convert scripts end @@ -211,39 +235,122 @@ class DatabaseBackend(Thread): """create tables for database""" self.c.execute( - 'CREATE TABLE IF NOT EXISTS "packages" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT NOT NULL, "folder" TEXT, "password" TEXT DEFAULT "", "site" TEXT DEFAULT "", "queue" INTEGER DEFAULT 0 NOT NULL, "packageorder" INTEGER DEFAULT 0 NOT NULL)') + 'CREATE TABLE IF NOT EXISTS "packages" (' + '"pid" INTEGER PRIMARY KEY AUTOINCREMENT, ' + '"name" TEXT NOT NULL, ' + '"folder" TEXT DEFAULT "" NOT NULL, ' + '"site" TEXT DEFAULT "" NOT NULL, ' + '"comment" TEXT DEFAULT "" NOT NULL, ' + '"password" TEXT DEFAULT "" NOT NULL, ' + '"added" INTEGER DEFAULT 0 NOT NULL,' # set by trigger + '"status" INTEGER DEFAULT 0 NOT NULL,' + '"packageorder" INTEGER DEFAULT -1 NOT NULL,' #incremented by trigger + '"root" INTEGER DEFAULT -1 NOT NULL,' + 'CHECK (root != pid) ' + ')' + ) + self.c.execute( - 'CREATE TABLE IF NOT EXISTS "links" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "url" TEXT NOT NULL, "name" TEXT, "size" INTEGER DEFAULT 0 NOT NULL, "status" INTEGER DEFAULT 3 NOT NULL, "plugin" TEXT DEFAULT "BasePlugin" NOT NULL, "error" TEXT DEFAULT "", "linkorder" INTEGER DEFAULT 0 NOT NULL, "package" INTEGER DEFAULT 0 NOT NULL, FOREIGN KEY(package) REFERENCES packages(id))') - self.c.execute('CREATE INDEX IF NOT EXISTS "pIdIndex" ON links(package)') + 'CREATE TRIGGER IF NOT EXISTS "insert_package" AFTER INSERT ON "packages"' + 'BEGIN ' + 'UPDATE packages SET added = strftime("%s", "now"), ' + 'packageorder = (SELECT max(p.packageorder) + 1 FROM packages p WHERE p.root=new.root) ' + 'WHERE rowid = new.rowid;' + 'END' + ) + self.c.execute( - 'CREATE TABLE IF NOT EXISTS "storage" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "identifier" TEXT NOT NULL, "key" TEXT NOT NULL, "value" TEXT DEFAULT "")') + 'CREATE TRIGGER IF NOT EXISTS "delete_package" AFTER DELETE ON "packages"' + 'BEGIN ' + 'DELETE FROM files WHERE package = old.pid;' + 'UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > old.packageorder AND root=old.pid;' + 'END' + ) + + self.c.execute('CREATE INDEX IF NOT EXISTS "root_index" ON packages(root)') + self.c.execute( - 'CREATE TABLE IF NOT EXISTS "users" ("name" TEXT PRIMARY KEY NOT NULL, "email" TEXT DEFAULT "" NOT NULL, "password" TEXT NOT NULL, "role" INTEGER DEFAULT 0 NOT NULL, "permission" INTEGER DEFAULT 0 NOT NULL, "template" TEXT DEFAULT "default" NOT NULL)') + 'CREATE TABLE IF NOT EXISTS "files" (' + '"fid" INTEGER PRIMARY KEY AUTOINCREMENT, ' + '"name" TEXT NOT NULL, ' + '"size" INTEGER DEFAULT 0 NOT NULL, ' + '"status" INTEGER DEFAULT 0 NOT NULL, ' + '"media" INTEGER DEFAULT 1 NOT NULL,' + '"added" INTEGER DEFAULT 0 NOT NULL,' + '"fileorder" INTEGER DEFAULT -1 NOT NULL, ' + '"url" TEXT DEFAULT "" NOT NULL, ' + '"plugin" TEXT DEFAULT "" NOT NULL, ' + '"hash" TEXT DEFAULT "" NOT NULL, ' + '"dlstatus" INTEGER DEFAULT 0 NOT NULL, ' + '"error" TEXT DEFAULT "" NOT NULL, ' + '"package" INTEGER NOT NULL, ' + 'FOREIGN KEY(package) REFERENCES packages(id)' + ')' + ) + + self.c.execute('CREATE INDEX IF NOT EXISTS "package_index" ON files(package)') + self.c.execute( - 'CREATE TABLE IF NOT EXISTS "accounts" ("plugin" TEXT NOT NULL, "loginname" TEXT NOT NULL, "activated" INTEGER DEFAULT 1, "password" TEXT DEFAULT "", "options" TEXT DEFAULT "", PRIMARY KEY (plugin, loginname) ON CONFLICT REPLACE)') + 'CREATE TRIGGER IF NOT EXISTS "insert_file" AFTER INSERT ON "files"' + 'BEGIN ' + 'UPDATE files SET added = strftime("%s", "now"), ' + 'fileorder = (SELECT max(f.fileorder) + 1 FROM files f WHERE f.package=new.package) ' + 'WHERE rowid = new.rowid;' + 'END' + ) - self.c.execute('CREATE VIEW IF NOT EXISTS "pstats" AS \ - SELECT p.id AS id, SUM(l.size) AS sizetotal, COUNT(l.id) AS linkstotal, linksdone, sizedone\ - FROM packages p JOIN links l ON p.id = l.package LEFT OUTER JOIN\ - (SELECT p.id AS id, COUNT(*) AS linksdone, SUM(l.size) AS sizedone \ - FROM packages p JOIN links l ON p.id = l.package AND l.status in (0,4,13) GROUP BY p.id) s ON s.id = p.id \ - GROUP BY p.id') + self.c.execute( + 'CREATE TABLE IF NOT EXISTS "collector" (' + '"url" TEXT NOT NULL, ' + '"name" TEXT NOT NULL, ' + '"plugin" TEXT DEFAULT "BasePlugin" NOT NULL, ' + '"size" INTEGER DEFAULT 0 NOT NULL, ' + '"status" INTEGER DEFAULT 3 NOT NULL, ' + '"packagename" TEXT DEFAULT "" NOT NULL, ' + 'PRIMARY KEY (url, packagename) ON CONFLICT REPLACE' + ') ' + ) + + self.c.execute( + 'CREATE TABLE IF NOT EXISTS "storage" (' + '"identifier" TEXT NOT NULL, ' + '"key" TEXT NOT NULL, ' + '"value" TEXT DEFAULT "", ' + 'PRIMARY KEY (identifier, key) ON CONFLICT REPLACE' + ')' + ) + + self.c.execute( + 'CREATE TABLE IF NOT EXISTS "users" (' + '"name" TEXT PRIMARY KEY NOT NULL, ' + '"email" TEXT DEFAULT "" NOT NULL, ' + '"password" TEXT NOT NULL, ' + '"role" INTEGER DEFAULT 0 NOT NULL, ' + '"permission" INTEGER DEFAULT 0 NOT NULL, ' + '"template" TEXT DEFAULT "default" NOT NULL' + ')' + ) + + self.c.execute( + 'CREATE TABLE IF NOT EXISTS "accounts" (' + '"plugin" TEXT NOT NULL, ' + '"loginname" TEXT NOT NULL, ' + '"activated" INTEGER DEFAULT 1, ' + '"password" TEXT DEFAULT "", ' + '"options" TEXT DEFAULT "", ' + 'PRIMARY KEY (plugin, loginname) ON CONFLICT REPLACE' + ')' + ) #try to lower ids - self.c.execute('SELECT max(id) FROM LINKS') + self.c.execute('SELECT max(fid) FROM files') fid = self.c.fetchone()[0] - if fid: - fid = int(fid) - else: - fid = 0 - self.c.execute('UPDATE SQLITE_SEQUENCE SET seq=? WHERE name=?', (fid, "links")) + fid = int(fid) if fid else 0 + self.c.execute('UPDATE SQLITE_SEQUENCE SET seq=? WHERE name=?', (fid, "files")) - self.c.execute('SELECT max(id) FROM packages') + self.c.execute('SELECT max(pid) FROM packages') pid = self.c.fetchone()[0] - if pid: - pid = int(pid) - else: - pid = 0 + pid = int(pid) if pid else 0 self.c.execute('UPDATE SQLITE_SEQUENCE SET seq=? WHERE name=?', (pid, "packages")) self.c.execute('VACUUM') @@ -273,7 +380,8 @@ class DatabaseBackend(Thread): args = (self, ) + args job = DatabaseJob(f, *args, **kwargs) self.jobs.put(job) - job.wait() + # only wait when db is running + if self.running.isSet(): job.wait() return job.result @classmethod @@ -288,6 +396,7 @@ class DatabaseBackend(Thread): for sub in DatabaseBackend.subs: if hasattr(sub, attr): return getattr(sub, attr) + raise AttributeError(attr) if __name__ == "__main__": db = DatabaseBackend() diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py index eb76f468b..08b18765d 100644 --- a/module/database/FileDatabase.py +++ b/module/database/FileDatabase.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +# -*- 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 @@ -14,781 +16,331 @@ along with this program; if not, see . @author: RaNaN - @author: mkaay """ +from new_collections import OrderedDict +from module.Api import DownloadInfo, LinkStatus, FileInfo, PackageInfo, PackageStats +from module.database import DatabaseMethods, queue, async, inner -from threading import RLock -from time import time - -from module.utils import formatSize, lock -from module.PyPackage import PyPackage -from module.PyFile import PyFile -from module.database import DatabaseBackend, queue, async, inner - -try: - from pysqlite2 import dbapi2 as sqlite3 -except: - import sqlite3 - - -class FileHandler: - """Handles all request made to obtain information, - modify status or other request for links or packages""" - - def __init__(self, core): - """Constructor""" - self.core = core - self.evm = core.eventManager - - # translations - self.statusMsg = [_("finished"), _("offline"), _("online"), _("queued"), _("skipped"), _("waiting"), _("temp. offline"), _("starting"), _("failed"), _("aborted"), _("decrypting"), _("custom"), _("downloading"), _("processing"), _("unknown")] - - self.cache = {} # holds instances for files - self.packageCache = {} # same for packages - #@TODO: purge the cache - - self.jobCache = {} - - self.lock = RLock() #@TODO should be a Lock w/o R - #self.lock._Verbose__verbose = True - - self.filecount = -1 # if an invalid value is set get current value from db - self.queuecount = -1 # number of package to be loaded - - self.db = self.core.db - - def change(func): - def new(*args): - args[0].filecount = -1 - args[0].queuecount = -1 - args[0].jobCache = {} - return func(*args) - return new - - #---------------------------------------------------------------------- - def save(self): - """saves all data to backend""" - self.db.commit() - - #---------------------------------------------------------------------- - def syncSave(self): - """saves all data to backend and waits until all data are written""" - pyfiles = self.cache.values() - for pyfile in pyfiles: - pyfile.sync() - - pypacks = self.packageCache.values() - for pypack in pypacks: - pypack.sync() - - self.db.syncSave() - - @lock - def getCompleteData(self, queue=1): - """gets a complete data representation""" - - data = self.db.getAllLinks(queue) - packs = self.db.getAllPackages(queue) - - data.update([(x.id, x.toDbDict()[x.id]) for x in self.cache.values()]) - - for x in self.packageCache.itervalues(): - if x.queue != queue or x.id not in packs: continue - packs[x.id].update(x.toDict()[x.id]) - - for key, value in data.iteritems(): - if value["package"] in packs: - packs[value["package"]]["links"][key] = value - - return packs - - @lock - def getInfoData(self, queue=1): - """gets a data representation without links""" - - packs = self.db.getAllPackages(queue) - for x in self.packageCache.itervalues(): - if x.queue != queue or x.id not in packs: continue - packs[x.id].update(x.toDict()[x.id]) - - return packs - - @lock - @change - def addLinks(self, data, package): - """Add links, data = (plugin, url) tuple. Internal method you should use API.""" - self.db.addLinks(data, package) - self.evm.dispatchEvent("packageUpdated", package) - - - @lock - @change - def addPackage(self, name, folder, queue=0, password=""): - """adds a package, default to link collector""" - pid = self.db.addPackage(name, folder, queue, password) - p = self.db.getPackage(pid) - - self.evm.dispatchEvent("packageInserted", pid, p.queue, p.order) - return pid - - - @lock - @change - def deletePackage(self, id): - """delete package and all contained links""" - - p = self.getPackage(id) - if not p: - if id in self.packageCache: del self.packageCache[id] - return - - oldorder = p.order - queue = p.queue - - - pyfiles = self.cache.values() - - for pyfile in pyfiles: - if pyfile.packageid == id: - pyfile.abortDownload() - pyfile.release() - - self.db.deletePackage(p) - self.evm.dispatchEvent("packageDeleted", id) - - if id in self.packageCache: - del self.packageCache[id] - - packs = self.packageCache.values() - for pack in packs: - if pack.queue == queue and pack.order > oldorder: - pack.order -= 1 - pack.notifyChange() - - - @lock - @change - def deleteLink(self, id): - """deletes links""" - - f = self.getFile(id) - if not f: - return None - - pid = f.packageid - oldorder = f.order - - if id in self.core.threadManager.processingIds(): - self.cache[id].abortDownload() - - if id in self.cache: - del self.cache[id] - - self.db.deleteLink(f) - - self.evm.dispatchEvent("linkDeleted", id, pid) - - p = self.getPackage(pid) - p.deleteIfEmpty() - - pyfiles = self.cache.values() - for pyfile in pyfiles: - if pyfile.packageid == pid and pyfile.order > oldorder: - pyfile.order -= 1 - pyfile.notifyChange() - - def releaseLink(self, id): - """removes pyfile from cache""" - if id in self.cache: - del self.cache[id] - - def releasePackage(self, id): - """removes package from cache""" - if id in self.packageCache: - del self.packageCache[id] - - def updateLink(self, pyfile): - """updates link""" - self.db.updateLink(pyfile) - self.evm.dispatchEvent("linkUpdated", pyfile.id, pyfile.packageid) - - def updatePackage(self, pypack): - """updates a package""" - self.db.updatePackage(pypack) - self.evm.dispatchEvent("packageUpdated", pypack.id) - - def getPackage(self, id): - """return package instance""" - - if id in self.packageCache: - return self.packageCache[id] - else: - return self.db.getPackage(id) - - def getPackageData(self, id): - """returns dict with package information""" - pack = self.getPackage(id) - - if not pack: - return None - - pack = pack.toDict()[id] - - data = self.db.getPackageData(id) - - tmplist = [] - - cache = self.cache.values() - for x in cache: - if int(x.toDbDict()[x.id]["package"]) == int(id): - tmplist.append((x.id, x.toDbDict()[x.id])) - data.update(tmplist) - - pack["links"] = data - - return pack - - - def getFileData(self, id): - """returns dict with file information""" - if id in self.cache: - return self.cache[id].toDbDict() - - return self.db.getLinkData(id) - - - def getFile(self, id): - """returns pyfile instance""" - if id in self.cache: - return self.cache[id] - else: - return self.db.getFile(id) - - - @lock - def getJob(self, occ): - """get suitable job""" - - #@TODO clean mess - #@TODO improve selection of valid jobs - - if occ in self.jobCache: - if self.jobCache[occ]: - id = self.jobCache[occ].pop() - if id == "empty": - pyfile = None - self.jobCache[occ].append("empty") - else: - pyfile = self.getFile(id) - else: - jobs = self.db.getJob(occ) - jobs.reverse() - if not jobs: - self.jobCache[occ].append("empty") - pyfile = None - else: - self.jobCache[occ].extend(jobs) - pyfile = self.getFile(self.jobCache[occ].pop()) - - else: - self.jobCache = {} #better not caching to much - jobs = self.db.getJob(occ) - jobs.reverse() - self.jobCache[occ] = jobs - - if not jobs: - self.jobCache[occ].append("empty") - pyfile = None - else: - pyfile = self.getFile(self.jobCache[occ].pop()) - - #@TODO: maybe the new job has to be approved... - - - #pyfile = self.getFile(self.jobCache[occ].pop()) - return pyfile - - - def getFileCount(self): - """returns number of files""" - - if self.filecount == -1: - self.filecount = self.db.filecount(1) - - return self.filecount - - def getQueueCount(self, force=False): - """number of files that have to be processed""" - if self.queuecount == -1 or force: - self.queuecount = self.db.queuecount(1) - - return self.queuecount - - def checkAllLinksFinished(self): - """checks if all files are finished and dispatch event""" - - if not self.getQueueCount(True): - self.core.hookManager.dispatchEvent("allDownloadsFinished") - self.core.log.debug("All downloads finished") - return True - - return False - - def checkAllLinksProcessed(self, fid): - """checks if all files was processed and pyload would idle now, needs fid which will be ignored when counting""" - - # reset count so statistic will update (this is called when dl was processed) - self.resetCount() - - if not self.db.processcount(1, fid): - self.core.hookManager.dispatchEvent("allDownloadsProcessed") - self.core.log.debug("All downloads processed") - return True - - return False - - def resetCount(self): - self.queuecount = -1 - - @lock - @change - def restartPackage(self, id): - """restart package""" - pyfiles = self.cache.values() - for pyfile in pyfiles: - if pyfile.packageid == id: - self.restartFile(pyfile.id) - - self.db.restartPackage(id) - - if id in self.packageCache: - self.packageCache[id].setFinished = False - - self.evm.dispatchEvent("packageUpdated", id) - - @lock - @change - def restartFile(self, id): - """ restart file""" - if id in self.cache: - self.cache[id].status = 3 - self.cache[id].name = self.cache[id].url - self.cache[id].error = "" - self.cache[id].abortDownload() - - - self.db.restartFile(id) - self.evm.dispatchEvent("linkUpdated", id) - - - @lock - @change - def setPackageLocation(self, id, queue): - """push package to queue""" - - p = self.db.getPackage(id) - oldorder = p.order - p.queue = queue +default = PackageStats(0, 0, 0, 0) - self.db.clearPackageOrder(p) - self.db.updatePackage(p) - self.db.reorderPackage(p, -1, True) - - packs = self.packageCache.values() - for pack in packs: - if pack.queue != queue and pack.order > oldorder: - pack.order -= 1 - pack.notifyChange() - - self.db.commit() - self.releasePackage(id) - - self.evm.dispatchEvent("packageDeleted", id) - self.evm.dispatchEvent("packageInserted", id, p.queue, p.order) - - @lock - @change - def reorderPackage(self, id, position): - p = self.getPackage(id) - - self.db.reorderPackage(p, position) - - packs = self.packageCache.values() - for pack in packs: - if pack.queue != p.queue or pack.order < 0 or pack == p: continue - if p.order > position: - if position <= pack.order < p.order: - pack.order += 1 - pack.notifyChange() - elif p.order < position: - if position >= pack.order > p.order: - pack.order -= 1 - pack.notifyChange() - - p.order = position - self.db.commit() - - self.evm.dispatchEvent("packageDeleted", id) - self.evm.dispatchEvent("packageInserted", id, p.queue, p.order) - - @lock - @change - def reorderFile(self, id, position): - f = self.getFileData(id) - f = f[id] - - self.db.reorderLink(f, position) - - pyfiles = self.cache.values() - for pyfile in pyfiles: - if pyfile.packageid != f["package"] or pyfile.order < 0: continue - if f["order"] > position: - if position <= pyfile.order < f["order"]: - pyfile.order += 1 - pyfile.notifyChange() - elif f["order"] < position: - if position >= pyfile.order > f["order"]: - pyfile.order -= 1 - pyfile.notifyChange() - - if id in self.cache: - self.cache[id].order = position - - self.db.commit() - - self.evm.dispatchEvent("packageUpdated", f["package"]) - - - @change - def updateFileInfo(self, data, pid): - """ updates file info (name, size, status, url)""" - ids = self.db.updateLinkInfo(data) - self.evm.dispatchEvent("packageUpdated", pid) - - def checkPackageFinished(self, pyfile): - """ checks if package is finished and calls hookmanager """ - - ids = self.db.getUnfinished(pyfile.packageid) - if not ids or (pyfile.id in ids and len(ids) == 1): - if not pyfile.package().setFinished: - self.core.log.info(_("Package finished: %s") % pyfile.package().name) - self.core.hookManager.packageFinished(pyfile.package()) - pyfile.package().setFinished = True - - - def reCheckPackage(self, pid): - """ recheck links in package """ - data = self.db.getPackageData(pid) - - urls = [] - - for pyfile in data.itervalues(): - if pyfile["status"] not in (0, 12, 13): - urls.append((pyfile["url"], pyfile["plugin"])) - - self.core.threadManager.createInfoThread(urls, pid) - - @lock - @change - def deleteFinishedLinks(self): - """ deletes finished links and packages, return deleted packages """ - - old_packs = self.getInfoData(0) - old_packs.update(self.getInfoData(1)) - - self.db.deleteFinished() - - new_packs = self.db.getAllPackages(0) - new_packs.update(self.db.getAllPackages(1)) - #get new packages only from db - - deleted = [] - for id in old_packs.iterkeys(): - if id not in new_packs: - deleted.append(id) - self.deletePackage(int(id)) - - return deleted - - @lock - @change - def restartFailed(self): - """ restart all failed links """ - self.db.restartFailed() - -class FileMethods(): +class FileMethods(DatabaseMethods): @queue - def filecount(self, queue): - """returns number of files in queue""" - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue, )) + def filecount(self): + """returns number of files""" + self.c.execute("SELECT COUNT(*) FROM files") return self.c.fetchone()[0] @queue - def queuecount(self, queue): + def queuecount(self): """ number of files in queue not finished yet""" - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0,4)", (queue, )) + # status not in NA, finished, skipped + self.c.execute("SELECT COUNT(*) FROM files WHERE dlstatus NOT IN (0,5,6)") return self.c.fetchone()[0] @queue - def processcount(self, queue, fid): + def processcount(self, fid): """ number of files which have to be proccessed """ - self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2,3,5,7,12) AND l.id != ?", (queue, str(fid))) + # status in online, queued, starting, waiting, downloading + self.c.execute("SELECT COUNT(*) FROM files as WHERE dlstatus IN (2,3,8,9,10) AND fid != ?", (str(fid), )) return self.c.fetchone()[0] - @inner - def _nextPackageOrder(self, queue=0): - self.c.execute('SELECT MAX(packageorder) FROM packages WHERE queue=?', (queue,)) - max = self.c.fetchone()[0] - if max is not None: - return max + 1 - else: - return 0 - - @inner - def _nextFileOrder(self, package): - self.c.execute('SELECT MAX(linkorder) FROM links WHERE package=?', (package,)) - max = self.c.fetchone()[0] - if max is not None: - return max + 1 - else: - return 0 - @queue def addLink(self, url, name, plugin, package): - order = self._nextFileOrder(package) - self.c.execute('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', (url, name, plugin, package, order)) + # mark filestatus initially as missing, dlstatus - queued + self.c.execute('INSERT INTO files(url, name, plugin, status, dlstatus, package) VALUES(?,?,?,1,3,?)', + (url, name, plugin, package)) return self.c.lastrowid - @queue + @async def addLinks(self, links, package): - """ links is a list of tupels (url,plugin)""" - order = self._nextFileOrder(package) - orders = [order + x for x in range(len(links))] - links = [(x[0], x[0], x[1], package, o) for x, o in zip(links, orders)] - self.c.executemany('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', links) + """ links is a list of tupels (url, plugin)""" + links = [(x[0], x[0], x[1], package) for x in links] + self.c.executemany('INSERT INTO files(url, name, plugin, status, dlstatus, package) VALUES(?,?,?,1,3,?)', links) @queue - def addPackage(self, name, folder, queue, password): - order = self._nextPackageOrder(queue) - self.c.execute('INSERT INTO packages(name, folder, queue, packageorder, password) VALUES(?,?,?,?,?)', (name, folder, queue, order, password)) + def addFile(self, name, size, media, package): + # filestatus - ok, dl status NA + self.c.execute('INSERT INTO files(name, size, media, package) VALUES(?,?,?,?)', + (name, size, media, package)) return self.c.lastrowid @queue - def deletePackage(self, p): + def addPackage(self, name, folder, root, password, site, comment, status): + self.c.execute('INSERT INTO packages(name, folder, root, password, site, comment, status) VALUES(?,?,?,?,?,?,?)' + , + (name, folder, root, password, site, comment, status)) + return self.c.lastrowid - self.c.execute('DELETE FROM links WHERE package=?', (str(p.id),)) - self.c.execute('DELETE FROM packages WHERE id=?', (str(p.id),)) - self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=?', (p.order, p.queue)) + @async + def deletePackage(self, pid): + # order updated by trigger + self.c.execute('DELETE FROM packages WHERE pid=?', (pid,)) - @queue - def deleteLink(self, f): + @async + def deleteFile(self, fid, order, package): + """ To delete a file order and package of it is needed """ + self.c.execute('DELETE FROM files WHERE fid=?', (fid,)) + self.c.execute('UPDATE files SET fileorder=fileorder-1 WHERE fileorder > ? AND package=?', + (order, package)) - self.c.execute('DELETE FROM links WHERE id=?', (str(f.id),)) - self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder > ? AND package=?', (f.order, str(f.packageid))) + @async + def addCollector(self, plugin, package, data): + """ fill collector, data as (name, size, status,[ hash,] url) list """ + if data and len(data[0]) == 4: + data = [(r[0], r[1], r[2], r[3], plugin, package) for r in data] + else: + data = [(r[0], r[1], r[2], r[4], plugin, package) for r in data] + self.c.executemany("INSERT INTO collector(name, size, status, url, plugin, packagename) VALUES (?,?,?,?,?,?)", + data) - @queue - def getAllLinks(self, q): - """return information about all links in queue q + @async + def deleteCollector(self, package=None, url=None): + qry = 'DELETE FROM collector' + if package: + self.c.execute(qry + " WHERE packagename=?", (package,)) + elif url: + self.c.execute(qry + " WHERE url=?", (url,)) + else: + self.c.execute(qry) - q0 queue - q1 collector + @queue + def getCollector(self, package=None): + """ get collector data, optionally filtered by package """ + qry = 'SELECT url, name, plugin, size, status, packagename FROM collector' + if package: + self.c.execute(qry + " WHERE packagename=?", (package,)) + else: + self.c.execute(qry) - format: + return [LinkStatus(*r) for r in self.c] - { - id: {'name': name, ... 'package': id }, ... - } + @queue + def getAllFiles(self, package=None, search=None, unfinished=False): + """ Return dict with file information + :param package: optional package to filter out + :param search: or search string for file name + :param unfinished: filter by dlstatus not finished """ - self.c.execute('SELECT l.id,l.url,l.name,l.size,l.status,l.error,l.plugin,l.package,l.linkorder FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? ORDER BY l.linkorder', (q,)) - data = {} + qry = ('SELECT fid, name, size, status, media, added, fileorder, ' + 'url, plugin, hash, dlstatus, error, package FROM files') + + if unfinished: + qry += ' WHERE dlstatus NOT IN (0, 5, 6)' + + if package is not None: + qry += ' AND' if unfinished else ' WHERE' + self.c.execute(qry + ' package=? ORDER BY package, fileorder', (package,)) + elif search is not None: + qry += ' AND' if unfinished else ' WHERE' + search = "%%%s%%" % search.strip("%") + self.c.execute(qry + ' name LIKE ? ORDER BY package, fileorder', (search,)) + + else: + self.c.execute(qry) + + data = OrderedDict() for r in self.c: - data[r[0]] = { - 'id': r[0], - 'url': r[1], - 'name': r[2], - 'size': r[3], - 'format_size': formatSize(r[3]), - 'status': r[4], - 'statusmsg': self.manager.statusMsg[r[4]], - 'error': r[5], - 'plugin': r[6], - 'package': r[7], - 'order': r[8], - } + f = FileInfo(r[0], r[1], r[12], r[2], r[3], r[4], r[5], r[6]) + if r[10] > 0: # dl status != NA + f.download = DownloadInfo(r[7], r[8], r[9], r[10], self.manager.statusMsg[r[10]], r[11]) + + data[r[0]] = f return data @queue - def getAllPackages(self, q): - """return information about packages in queue q - (only useful in get all data) + def getAllPackages(self, root=None): + """ Return dict with package information + + :param root: optional root to filter + """ + qry = ('SELECT pid, name, folder, root, site, comment, password, added, status, packageorder ' + 'FROM packages%s ORDER BY root, packageorder') - q0 queue - q1 collector + if root is None: + stats = self.getPackageStats() + self.c.execute(qry % "") + else: + stats = self.getPackageStats(root=root) + self.c.execute(qry % ' WHERE root=? OR pid=?', (root, root)) - format: + data = OrderedDict() + for r in self.c: + data[r[0]] = PackageInfo( + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], stats.get(r[0], default) + ) - { - id: {'name': name ... 'links': {} }, ... - } - """ - self.c.execute('SELECT p.id, p.name, p.folder, p.site, p.password, p.queue, p.packageorder, s.sizetotal, s.sizedone, s.linksdone, s.linkstotal \ - FROM packages p LEFT OUTER JOIN pstats s ON p.id = s.id \ - WHERE p.queue=? ORDER BY p.packageorder', str(q)) + return data + + @inner + def getPackageStats(self, pid=None, root=None): + qry = ("SELECT p.pid, SUM(f.size) AS sizetotal, COUNT(f.fid) AS linkstotal, sizedone, linksdone " + "FROM packages p JOIN files f ON p.pid = f.package AND f.dlstatus > 0 %(sub)s LEFT OUTER JOIN " + "(SELECT p.pid AS pid, SUM(f.size) AS sizedone, COUNT(f.fid) AS linksdone " + "FROM packages p JOIN files f ON p.pid = f.package %(sub)s AND f.dlstatus in (5,6) GROUP BY p.pid) s ON s.pid = p.pid " + "GROUP BY p.pid") + + # status in (finished, skipped, processing) + + if root is not None: + self.c.execute(qry % {"sub": "AND (p.root=:root OR p.pid=:root)"}, locals()) + elif pid is not None: + self.c.execute(qry % {"sub": "AND p.pid=:pid"}, locals()) + else: + self.c.execute(qry % {"sub": ""}) data = {} for r in self.c: - data[r[0]] = { - 'id': r[0], - 'name': r[1], - 'folder': r[2], - 'site': r[3], - 'password': r[4], - 'queue': r[5], - 'order': r[6], - 'sizetotal': int(r[7]) if r[7] else 0, - 'sizedone': int(r[8]) if r[8] else 0, #these can be None - 'linksdone': r[9] if r[9] else 0, - 'linkstotal': r[10] if r[10] else 0, - 'links': {} - } + data[r[0]] = PackageStats( + r[2] if r[2] else 0, + r[4] if r[4] else 0, + int(r[1]) if r[1] else 0, + int(r[3]) if r[3] else 0, + ) return data - + @queue - def getLinkData(self, id): - """get link information as dict""" - self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE id=?', (str(id), )) - data = {} + def getStatsForPackage(self, pid): + return self.getPackageStats(pid=pid)[pid] + + @queue + def getFileInfo(self, fid, force=False): + """get data for specific file""" + self.c.execute('SELECT fid, name, size, status, media, added, fileorder, ' + 'url, plugin, hash, dlstatus, error, package FROM files ' + 'WHERE fid=?', (fid,)) r = self.c.fetchone() if not r: return None - data[r[0]] = { - 'id': r[0], - 'url': r[1], - 'name': r[2], - 'size': r[3], - 'format_size': formatSize(r[3]), - 'status': r[4], - 'statusmsg': self.manager.statusMsg[r[4]], - 'error': r[5], - 'plugin': r[6], - 'package': r[7], - 'order': r[8], - } + else: + f = FileInfo(r[0], r[1], r[12], r[2], r[3], r[4], r[5], r[6]) + if r[10] > 0 or force: + f.download = DownloadInfo(r[7], r[8], r[9], r[10], self.manager.statusMsg[r[10]], r[11]) - return data + return f @queue - def getPackageData(self, id): - """get data about links for a package""" - self.c.execute('SELECT id,url,name,size,status,error,plugin,package,linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id), )) + def getPackageInfo(self, pid, stats=True): + """get data for specific package, optional with package stats""" + if stats: + stats = self.getPackageStats(pid=pid) - data = {} - for r in self.c: - data[r[0]] = { - 'id': r[0], - 'url': r[1], - 'name': r[2], - 'size': r[3], - 'format_size': formatSize(r[3]), - 'status': r[4], - 'statusmsg': self.manager.statusMsg[r[4]], - 'error': r[5], - 'plugin': r[6], - 'package': r[7], - 'order': r[8], - } + self.c.execute('SELECT pid, name, folder, root, site, comment, password, added, status, packageorder ' + 'FROM packages WHERE pid=?', (pid,)) - return data + r = self.c.fetchone() + if not r: + return None + else: + return PackageInfo( + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], stats.get(r[0], default) if stats else None + ) + @async + def updateLinkInfo(self, data): + """ data is list of tupels (name, size, status,[ hash,] url)""" + if data and len(data[0]) == 4: + self.c.executemany('UPDATE files SET name=?, size=?, dlstatus=? WHERE url=? AND dlstatus IN (0,1,2,3,14)', + data) + else: + self.c.executemany( + 'UPDATE files SET name=?, size=?, dlstatus=?, hash=? WHERE url=? AND dlstatus IN (0,1,2,3,14)', data) @async - def updateLink(self, f): - self.c.execute('UPDATE links SET url=?,name=?,size=?,status=?,error=?,package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id))) + def updateFile(self, f): + self.c.execute('UPDATE files SET name=?, size=?, status=?,' + 'media=?, url=?, hash=?, dlstatus=?, error=? WHERE fid=?', + (f.name, f.size, f.filestatus, f.media, f.url, + f.hash, f.status, f.error, f.fid)) - @queue + @async def updatePackage(self, p): - self.c.execute('UPDATE packages SET name=?,folder=?,site=?,password=?,queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id))) - - @queue - def updateLinkInfo(self, data): - """ data is list of tupels (name, size, status, url) """ - self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1,2,3,14)', data) - ids = [] - self.c.execute('SELECT id FROM links WHERE url IN (\'%s\')' % "','".join([x[3] for x in data])) - for r in self.c: - ids.append(int(r[0])) - return ids - - @queue - def reorderPackage(self, p, position, noMove=False): - if position == -1: - position = self._nextPackageOrder(p.queue) - if not noMove: - if p.order > position: - self.c.execute('UPDATE packages SET packageorder=packageorder+1 WHERE packageorder >= ? AND packageorder < ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue)) - elif p.order < position: - self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder <= ? AND packageorder > ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue)) - - self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (position, str(p.id))) - - @queue - def reorderLink(self, f, position): - """ reorder link with f as dict for pyfile """ - if f["order"] > position: - self.c.execute('UPDATE links SET linkorder=linkorder+1 WHERE linkorder >= ? AND linkorder < ? AND package=?', (position, f["order"], f["package"])) - elif f["order"] < position: - self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder <= ? AND linkorder > ? AND package=?', (position, f["order"], f["package"])) - - self.c.execute('UPDATE links SET linkorder=? WHERE id=?', (position, f["id"])) - - - @queue - def clearPackageOrder(self, p): - self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (-1, str(p.id))) - self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=? AND id != ?', (p.order, p.queue, str(p.id))) - + self.c.execute('UPDATE packages SET name=?, folder=?, site=?, comment=?, password=?, status=? WHERE pid=?', + (p.name, p.folder, p.site, p.comment, p.password, p.status, p.pid)) + @async - def restartFile(self, id): - self.c.execute('UPDATE links SET status=3,error="" WHERE id=?', (str(id),)) + def orderPackage(self, pid, root, oldorder, order): + if oldorder > order: # package moved upwards + self.c.execute( + 'UPDATE packages SET packageorder=packageorder+1 WHERE packageorder >= ? AND packageorder < ? AND root=? AND packageorder >= 0' + , (order, oldorder, root)) + elif oldorder < order: # moved downwards + self.c.execute( + 'UPDATE packages SET packageorder=packageorder-1 WHERE packageorder <= ? AND packageorder > ? AND root=? AND packageorder >= 0' + , (order, oldorder, root)) + + self.c.execute('UPDATE packages SET packageorder=? WHERE pid=?', (order, pid)) @async - def restartPackage(self, id): - self.c.execute('UPDATE links SET status=3 WHERE package=?', (str(id),)) - - @queue - def getPackage(self, id): - """return package instance from id""" - self.c.execute("SELECT name,folder,site,password,queue,packageorder FROM packages WHERE id=?", (str(id), )) + def orderFiles(self, pid, fids, oldorder, order): + diff = len(fids) + data = [] + + if oldorder > order: # moved upwards + self.c.execute('UPDATE files SET fileorder=fileorder+? WHERE fileorder >= ? AND fileorder < ? AND package=?' + , (diff, order, oldorder, pid)) + data = [(order + i, fid) for i, fid in enumerate(fids)] + elif oldorder < order: + self.c.execute( + 'UPDATE files SET fileorder=fileorder-? WHERE fileorder <= ? AND fileorder >= ? AND package=?' + , (diff, order, oldorder + diff, pid)) + data = [(order - diff + i + 1, fid) for i, fid in enumerate(fids)] + + self.c.executemany('UPDATE files SET fileorder=? WHERE fid=?', data) + + @async + def moveFiles(self, pid, fids, package): + self.c.execute('SELECT max(fileorder) FROM files WHERE package=?', (package,)) r = self.c.fetchone() - if not r: return None - return PyPackage(self.manager, id, * r) + order = (r[0] if r[0] else 0) + 1 + self.c.execute('UPDATE files SET fileorder=fileorder-? WHERE fileorder > ? AND package=?', + (len(fids), order, pid)) - @queue - def getFile(self, id): - """return link instance from id""" - self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id), )) + data = [(package, order + i, fid) for i, fid in enumerate(fids)] + self.c.executemany('UPDATE files SET package=?, fileorder=? WHERE fid=?', data) + + @async + def movePackage(self, root, order, pid, dpid): + self.c.execute('SELECT max(packageorder) FROM packages WHERE root=?', (dpid,)) r = self.c.fetchone() - if not r: return None - return PyFile(self.manager, id, * r) + max = (r[0] if r[0] else 0) + 1 + print max + self.c.execute('SELECT pid, packageorder FROM packages WHERE root=?', (dpid,)) + for r in self.c: + print r + + self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND root=?', + (order, root)) + + self.c.execute('UPDATE packages SET root=?, packageorder=? WHERE pid=?', (dpid, max, pid)) + + @async + def restartFile(self, fid): + # status -> queued + self.c.execute('UPDATE files SET dlstatus=3, error="" WHERE fid=?', (fid,)) + + @async + def restartPackage(self, pid): + # status -> queued + self.c.execute('UPDATE files SET status=3 WHERE package=?', (pid,)) @queue def getJob(self, occ): """return pyfile ids, which are suitable for download and dont use a occupied plugin""" - cmd = "(" - for i, item in enumerate(occ): - if i: cmd += ", " - cmd += "'%s'" % item + cmd = "(%s)" % ", ".join(["'%s'" % x for x in occ]) + #TODO - cmd += ")" + # dlstatus in online, queued | package status = ok + cmd = ("SELECT f.fid FROM files as f INNER JOIN packages as p ON f.package=p.pid " + "WHERE f.plugin NOT IN %s AND f.dlstatus IN (2,3) AND p.status=0 " + "ORDER BY p.packageorder ASC, f.fileorder ASC LIMIT 5") % cmd - cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=1 AND l.plugin NOT IN %s AND l.status IN (2,3,14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % cmd self.c.execute(cmd) # very bad! return [x[0] for x in self.c] @@ -796,79 +348,34 @@ class FileMethods(): @queue def getUnfinished(self, pid): """return list of max length 3 ids with pyfiles in package not finished or processed""" - - self.c.execute("SELECT id FROM links WHERE package=? AND status NOT IN (0, 4, 13) LIMIT 3", (str(pid),)) - return [r[0] for r in self.c] - @queue - def deleteFinished(self): - self.c.execute("DELETE FROM links WHERE status IN (0,4)") - self.c.execute("DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE packages.id=links.package)") + # status in finished, skipped, processing + self.c.execute("SELECT fid FROM files WHERE package=? AND dlstatus NOT IN (5, 6, 14) LIMIT 3", (pid,)) + return [r[0] for r in self.c] @queue def restartFailed(self): - self.c.execute("UPDATE links SET status=3,error='' WHERE status IN (8, 9)") + # status=queued, where status in failed, aborted, temp offline + self.c.execute("UPDATE files SET dlstatus=3, error='' WHERE dlstatus IN (7, 11, 12)") @queue def findDuplicates(self, id, folder, filename): """ checks if filename exists with different id and same package """ - self.c.execute("SELECT l.plugin FROM links as l INNER JOIN packages as p ON l.package=p.id AND p.folder=? WHERE l.id!=? AND l.status=0 AND l.name=?", (folder, id, filename)) + # TODO + self.c.execute( + "SELECT l.plugin FROM files f INNER JOIN packages as p ON f.package=p.pid AND p.folder=? WHERE f.fid!=? AND l.status=0 AND l.name=?" + , (folder, id, filename)) return self.c.fetchone() @queue def purgeLinks(self): - self.c.execute("DELETE FROM links;") - self.c.execute("DELETE FROM packages;") - -DatabaseBackend.registerSub(FileMethods) - -if __name__ == "__main__": - - pypath = "." - _ = lambda x: x - - db = FileHandler(None) - - #p = PyFile(db, 5) - #sleep(0.1) - - a = time() - - #print db.addPackage("package", "folder" , 1) - - pack = db.db.addPackage("package", "folder", 1) - - updates = [] - - - for x in range(0, 200): - x = str(x) - db.db.addLink("http://somehost.com/hoster/file/download?file_id=" + x, x, "BasePlugin", pack) - updates.append(("new name" + x, 0, 3, "http://somehost.com/hoster/file/download?file_id=" + x)) - - - for x in range(0, 100): - updates.append(("unimportant%s" % x, 0, 3, "a really long non existent url%s" % x)) - - db.db.commit() - - b = time() - print "adding 200 links, single sql execs, no commit", b-a - - print db.getCompleteData(1) - - c = time() - - - db.db.updateLinkInfo(updates) - - d = time() - - print "updates", d-c - - print db.getCompleteData(1) - - - e = time() - - print "complete data", e-d + # fstatus = missing + self.c.execute("DELETE FROM files WHERE status == 1") + + @queue + def purgeAll(self): # only used for debugging + self.c.execute("DELETE FROM packages") + self.c.execute("DELETE FROM files") + self.c.execute("DELETE FROM collector") + +FileMethods.register() \ No newline at end of file diff --git a/module/database/UserDatabase.py b/module/database/UserDatabase.py index 43fd93df3..6bfb02bbd 100644 --- a/module/database/UserDatabase.py +++ b/module/database/UserDatabase.py @@ -19,14 +19,13 @@ from hashlib import sha1 import random -from DatabaseBackend import DatabaseBackend, queue, async +from DatabaseBackend import DatabaseMethods, queue, async -class UserMethods(): +class UserMethods(DatabaseMethods): @queue - def checkAuth(db, user, password): - c = db.c - c.execute('SELECT rowid, name, password, role, permission, template, email FROM "users" WHERE name=?', (user, )) - r = c.fetchone() + def checkAuth(self, user, password): + self.c.execute('SELECT rowid, name, password, role, permission, template, email FROM "users" WHERE name=?', (user, )) + r = self.c.fetchone() if not r: return {} @@ -40,23 +39,22 @@ class UserMethods(): return {} @queue - def addUser(db, user, password): + def addUser(self, user, password): salt = reduce(lambda x, y: x + y, [str(random.randint(0, 9)) for i in range(0, 5)]) h = sha1(salt + password) password = salt + h.hexdigest() - c = db.c - c.execute('SELECT name FROM users WHERE name=?', (user, )) - if c.fetchone() is not None: - c.execute('UPDATE users SET password=? WHERE name=?', (password, user)) + self.c.execute('SELECT name FROM users WHERE name=?', (user, )) + if self.c.fetchone() is not None: + self.c.execute('UPDATE users SET password=? WHERE name=?', (password, user)) else: - c.execute('INSERT INTO users (name, password) VALUES (?, ?)', (user, password)) + self.c.execute('INSERT INTO users (name, password) VALUES (?, ?)', (user, password)) @queue - def changePassword(db, user, oldpw, newpw): - db.c.execute('SELECT rowid, name, password FROM users WHERE name=?', (user, )) - r = db.c.fetchone() + def changePassword(self, user, oldpw, newpw): + self.c.execute('SELECT rowid, name, password FROM users WHERE name=?', (user, )) + r = self.c.fetchone() if not r: return False @@ -68,40 +66,40 @@ class UserMethods(): h = sha1(salt + newpw) password = salt + h.hexdigest() - db.c.execute("UPDATE users SET password=? WHERE name=?", (password, user)) + self.c.execute("UPDATE users SET password=? WHERE name=?", (password, user)) return True return False @async - def setPermission(db, user, perms): - db.c.execute("UPDATE users SET permission=? WHERE name=?", (perms, user)) + def setPermission(self, user, perms): + self.c.execute("UPDATE users SET permission=? WHERE name=?", (perms, user)) @async - def setRole(db, user, role): - db.c.execute("UPDATE users SET role=? WHERE name=?", (role, user)) + def setRole(self, user, role): + self.c.execute("UPDATE users SET role=? WHERE name=?", (role, user)) @queue - def listUsers(db): - db.c.execute('SELECT name FROM users') + def listUsers(self): + self.c.execute('SELECT name FROM users') users = [] - for row in db.c: + for row in self.c: users.append(row[0]) return users @queue - def getAllUserData(db): - db.c.execute("SELECT name, permission, role, template, email FROM users") + def getAllUserData(self): + self.c.execute("SELECT name, permission, role, template, email FROM users") user = {} - for r in db.c: + for r in self.c: user[r[0]] = {"permission": r[1], "role": r[2], "template": r[3], "email": r[4]} return user @queue - def removeUser(db, user): - db.c.execute('DELETE FROM users WHERE name=?', (user, )) + def removeUser(self, user): + self.c.execute('DELETE FROM users WHERE name=?', (user, )) -DatabaseBackend.registerSub(UserMethods) +UserMethods.register() diff --git a/module/database/__init__.py b/module/database/__init__.py index 39848ac58..bf4ead872 100644 --- a/module/database/__init__.py +++ b/module/database/__init__.py @@ -1,6 +1,6 @@ -from DatabaseBackend import DatabaseBackend, queue, async, inner +from DatabaseBackend import DatabaseMethods, DatabaseBackend, queue, async, inner -from FileDatabase import FileHandler +from FileDatabase import FileMethods from UserDatabase import UserMethods from StorageDatabase import StorageMethods from AccountDatabase import AccountMethods \ No newline at end of file diff --git a/module/interaction/CaptchaManager.py b/module/interaction/CaptchaManager.py deleted file mode 100644 index 02cd10a11..000000000 --- a/module/interaction/CaptchaManager.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- 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 . - - @author: mkaay, RaNaN -""" - -from time import time -from traceback import print_exc -from threading import Lock - -class CaptchaManager(): - def __init__(self, core): - self.lock = Lock() - self.core = core - self.tasks = [] #task store, for outgoing tasks only - - self.ids = 0 #only for internal purpose - - def newTask(self, img, format, file, result_type): - task = CaptchaTask(self.ids, img, format, file, result_type) - self.ids += 1 - return task - - def removeTask(self, task): - self.lock.acquire() - if task in self.tasks: - self.tasks.remove(task) - self.lock.release() - - def getTask(self): - self.lock.acquire() - for task in self.tasks: - if task.status in ("waiting", "shared-user"): - self.lock.release() - return task - self.lock.release() - return None - - def getTaskByID(self, tid): - self.lock.acquire() - for task in self.tasks: - if task.id == str(tid): #task ids are strings - self.lock.release() - return task - self.lock.release() - return None - - def handleCaptcha(self, task): - cli = self.core.isClientConnected() - - if cli: #client connected -> should solve the captcha - task.setWaiting(50) #wait 50 sec for response - - for plugin in self.core.hookManager.activePlugins(): - try: - plugin.newCaptchaTask(task) - except: - if self.core.debug: - print_exc() - - if task.handler or cli: #the captcha was handled - self.tasks.append(task) - return True - - task.error = _("No Client connected for captcha decrypting") - - return False - - -class CaptchaTask(): - def __init__(self, id, img, format, file, result_type='textual'): - self.id = str(id) - self.captchaImg = img - self.captchaFormat = format - self.captchaFile = file - self.captchaResultType = result_type - self.handler = [] #the hook plugins that will take care of the solution - self.result = None - self.waitUntil = None - self.error = None #error message - - self.status = "init" - self.data = {} #handler can store data here - - def getCaptcha(self): - return self.captchaImg, self.captchaFormat, self.captchaResultType - - def setResult(self, text): - if self.isTextual(): - self.result = text - if self.isPositional(): - try: - parts = text.split(',') - self.result = (int(parts[0]), int(parts[1])) - except: - self.result = None - - def getResult(self): - try: - res = self.result.encode("utf8", "replace") - except: - res = self.result - - return res - - def getStatus(self): - return self.status - - def setWaiting(self, sec): - """ let the captcha wait secs for the solution """ - self.waitUntil = max(time() + sec, self.waitUntil) - self.status = "waiting" - - def isWaiting(self): - if self.result or self.error or time() > self.waitUntil: - return False - - return True - - def isTextual(self): - """ returns if text is written on the captcha """ - return self.captchaResultType == 'textual' - - def isPositional(self): - """ returns if user have to click a specific region on the captcha """ - return self.captchaResultType == 'positional' - - def setWatingForUser(self, exclusive): - if exclusive: - self.status = "user" - else: - self.status = "shared-user" - - def timedOut(self): - return time() > self.waitUntil - - def invalid(self): - """ indicates the captcha was not correct """ - [x.captchaInvalid(self) for x in self.handler] - - def correct(self): - [x.captchaCorrect(self) for x in self.handler] - - def __str__(self): - return "" % self.id diff --git a/module/interaction/EventManager.py b/module/interaction/EventManager.py index 38faa3c46..02ecb82fb 100644 --- a/module/interaction/EventManager.py +++ b/module/interaction/EventManager.py @@ -1,14 +1,17 @@ # -*- coding: utf-8 -*- +from threading import Lock from traceback import print_exc from time import time +from module.utils import lock + class EventManager: """ Handles all Event related task, also stores an Event queue for clients, so they can retrieve them later. **Known Events:** - Most hook methods exists as events. These are some additional known events. + Most addon methods exists as events. These are some additional known events. ===================== ================ =========================================================== Name Arguments Description @@ -38,6 +41,8 @@ class EventManager: self.clients = {} self.events = {"metaEvent": []} + self.lock = Lock() + def getEvents(self, uuid): """ Get accumulated events for uuid since last call, this also registeres new client """ if uuid not in self.clients: @@ -80,6 +85,10 @@ class EventManager: if self.core.debug: print_exc() + self.updateClients(event, args) + + @lock + def updateClients(self, event, args): # append to client event queue if event in self.CLIENT_EVENTS: for uuid, client in self.clients.items(): @@ -88,7 +97,6 @@ class EventManager: else: client.append(event, args) - def removeFromEvents(self, func): """ Removes func from all known events """ for name, events in self.events.iteritems(): diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py index 5ebcd1fcd..c547e1c97 100644 --- a/module/interaction/InteractionManager.py +++ b/module/interaction/InteractionManager.py @@ -15,10 +15,13 @@ @author: RaNaN """ -from utils import lock from traceback import print_exc from threading import Lock +from module.utils import lock, bits_set + +from InteractionTask import InteractionTask + class InteractionManager: """ Class that gives ability to interact with the user. @@ -30,13 +33,25 @@ class InteractionManager: self.core = core self.tasks = [] #task store, for outgoing tasks only + self.last_clients = {} + self.ids = 0 #only for internal purpose + def work(self): - """Mainloop that gets the work done""" + pass + + @lock + def newNotification(self): + pass + + @lock + def newQueryTask(self): + pass - def newTask(self, img, format, file, result_type): - task = CaptchaTask(self.ids, img, format, file, result_type) + @lock + def newCaptchaTask(self, img, format, file, result_type): + task = InteractionTask(self.ids, img, format, file, result_type) self.ids += 1 return task @@ -48,14 +63,12 @@ class InteractionManager: @lock def getTask(self): for task in self.tasks: - if task.status in ("waiting", "shared-user"): - return task + return task @lock - def getTaskByID(self, tid): + def getTaskByID(self, iid): for task in self.tasks: - if task.id == str(tid): #task ids are strings - self.lock.release() + if task.id == iid: return task def handleCaptcha(self, task): @@ -64,7 +77,7 @@ class InteractionManager: if cli: #client connected -> should solve the captcha task.setWaiting(50) #wait 50 sec for response - for plugin in self.core.hookManager.activePlugins(): + for plugin in self.core.addonManager.activePlugins(): try: plugin.newCaptchaTask(task) except: diff --git a/module/interaction/InteractionTask.py b/module/interaction/InteractionTask.py index 97cb16794..7963a5c72 100644 --- a/module/interaction/InteractionTask.py +++ b/module/interaction/InteractionTask.py @@ -16,6 +16,8 @@ @author: RaNaN """ +from time import time + from module.Api import InteractionTask as BaseInteractionTask from module.Api import Input, Output @@ -27,103 +29,48 @@ class InteractionTask(BaseInteractionTask): #: Plugins can put needed data here storage = None #: Timestamp when task expires - waitUntil = 0 - #: Default data to be used, or True if preset should be used - default = None + wait_until = 0 #: The received result as string representation result = None #: List of registered handles handler = None - #: Callback functions - callbacks = None #: Error Message error = None - #: Status string - status = None def __init__(self, *args, **kwargs): BaseInteractionTask.__init__(self, *args, **kwargs) # additional internal attributes self.storage = {} - self.default = [] self.handler = [] - self.callbacks = [] - - -class CaptchaTask: - def __init__(self, id, img, format, file, result_type='textual'): - self.id = str(id) - self.captchaImg = img - self.captchaFormat = format - self.captchaFile = file - self.captchaResultType = result_type - self.handler = [] #the hook plugins that will take care of the solution - self.result = None - self.waitUntil = None - self.error = None #error message - - self.status = "init" - self.data = {} #handler can store data here - - def getCaptcha(self): - return self.captchaImg, self.captchaFormat, self.captchaResultType - - def setResult(self, text): - if self.isTextual(): - self.result = text - if self.isPositional(): - try: - parts = text.split(',') - self.result = (int(parts[0]), int(parts[1])) - except: - self.result = None + self.wait_until = 0 - def getResult(self): - try: - res = self.result.encode("utf8", "replace") - except: - res = self.result + def convertResult(self, value): + return value - return res + def getResult(self): + return self.result - def getStatus(self): - return self.status + def setResult(self, value): + pass def setWaiting(self, sec): - """ let the captcha wait secs for the solution """ - self.waitUntil = max(time() + sec, self.waitUntil) - self.status = "waiting" + self.wait_until = max(time() + sec, self.wait_until) - def isWaiting(self): + def isWaiting(self, sec): if self.result or self.error or time() > self.waitUntil: return False return True - def isTextual(self): - """ returns if text is written on the captcha """ - return self.captchaResultType == 'textual' - - def isPositional(self): - """ returns if user have to click a specific region on the captcha """ - return self.captchaResultType == 'positional' - - def setWatingForUser(self, exclusive): - if exclusive: - self.status = "user" - else: - self.status = "shared-user" - def timedOut(self): return time() > self.waitUntil - def invalid(self): - """ indicates the captcha was not correct """ - [x.captchaInvalid(self) for x in self.handler] - def correct(self): - [x.captchaCorrect(self) for x in self.handler] + [x.taskCorrect(self) for x in self.handler] + + def invalid(self): + [x.taskInvalid(self) for x in self.handler] def __str__(self): - return "" % self.id + return "" % self.id \ No newline at end of file diff --git a/module/network/HTTPDownload.py b/module/network/HTTPDownload.py index 59d38beee..520a4e5f4 100644 --- a/module/network/HTTPDownload.py +++ b/module/network/HTTPDownload.py @@ -31,6 +31,8 @@ from HTTPRequest import BadHeader from module.plugins.Hoster import Abort from module.utils.fs import save_join, fs_encode +# TODO: save content-disposition for resuming + class HTTPDownload(): """ loads a url http + ftp """ diff --git a/module/plugins/Account.py b/module/plugins/Account.py index 323c8b545..28d1387fd 100644 --- a/module/plugins/Account.py +++ b/module/plugins/Account.py @@ -4,7 +4,7 @@ from time import time from traceback import print_exc from threading import RLock -from module.utils import compare_time, formatSize, parseFileSize, lock, from_string +from module.utils import compare_time, format_size, parseFileSize, lock, from_string from module.Api import AccountInfo from module.network.CookieJar import CookieJar @@ -23,11 +23,15 @@ class Account(Base, AccountInfo): fields of AccountInfo ttype, and can be set easily at runtime. """ + # constants for special values + UNKNOWN = -1 + UNLIMITED = -2 + # Default values valid = True - validuntil = None - trafficleft = None - maxtraffic = None + validuntil = -1 + trafficleft = -1 + maxtraffic = -1 premium = True activated = True @@ -39,7 +43,6 @@ class Account(Base, AccountInfo): # known options known_opt = ("time", "limitDL") - def __init__(self, manager, loginname, password, options): Base.__init__(self, manager.core) @@ -231,7 +234,7 @@ class Account(Base, AccountInfo): except: self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) - if 0 < self.validuntil < time(): + if 0 <= self.validuntil < time(): return False if self.trafficleft is 0: # test explicity for 0 return False @@ -244,7 +247,7 @@ class Account(Base, AccountInfo): def formatTrafficleft(self): if self.trafficleft is None: self.getAccountInfo(force=True) - return formatSize(self.trafficleft*1024) + return format_size(self.trafficleft*1024) def wrongPassword(self): raise WrongPassword @@ -257,12 +260,13 @@ class Account(Base, AccountInfo): self.trafficleft = 0 self.scheduleRefresh(30 * 60) - def expired(self, user): - if user in self.infos: - self.logWarning(_("Account %s is expired, checking again in 1h") % user) + def expired(self, user=None): + if user: self.logDebug("Deprecated argument user for .expired()", user) + + self.logWarning(_("Account %s is expired, checking again in 1h") % user) - self.validuntil = time() - 1 - self.scheduleRefresh(60 * 60) + self.validuntil = time() - 1 + self.scheduleRefresh(60 * 60) def scheduleRefresh(self, time=0, force=True): """ add task to refresh account info to sheduler """ diff --git a/module/plugins/Addon.py b/module/plugins/Addon.py new file mode 100644 index 000000000..fe9ae4817 --- /dev/null +++ b/module/plugins/Addon.py @@ -0,0 +1,203 @@ +# -*- 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 . + + @author: RaNaN +""" + +from traceback import print_exc + +#from functools import wraps +from module.utils import has_method + +from Base import Base + +def class_name(p): + return p.rpartition(".")[2] + +class Expose(object): + """ Used for decoration to declare rpc services. You can use any arbitrary method """ + def __new__(cls, f, *args, **kwargs): + addonManager.addRPC(class_name(f.__module__), f.func_name, f.func_doc) + return f + +def AddEventListener(event): + """ Used to register method for events. Arguments needs to match parameter of event """ + class _klass(object): + def __new__(cls, f, *args, **kwargs): + addonManager.addEventListener(class_name(f.__module__), f.func_name, event) + return f + return _klass + +class ConfigHandler(object): + """ Register method as config handler. + + Your method signature has to be: + def foo(value=None): + + value will be passed to use your method to set the config. + When value is None your method needs to return an interaction task for configuration. + """ + + def __new__(cls, f, *args, **kwargs): + addonManager.addConfigHandler(class_name(f.__module__), f.func_name) + return f + +def FileHandler(desc, media, package=False): + """ Register Handler for Files or packages. + Depending on package=True the decorated method needs to accept pid or fid as argument + + :param desc: verbose description + :param media: media type for which your method will be used + :param package: True if it works on packages + """ + pass + +def AddonInfo(desc): + """ Called to retrieve information about the current state. + Decorated method must return anything convertable into string. + + :param desc: verbose description + """ + pass + +def threaded(f): + #@wraps(f) + def run(*args,**kwargs): + addonManager.startThread(f, *args, **kwargs) + return run + +class Addon(Base): + """ + Base class for addon plugins. Use @threaded decorator for all longer running task. + + Decorate methods with @Expose, @AddventListener, @ConfigHandler + + """ + + #: automatically register event listeners for functions, attribute will be deleted dont use it yourself + event_map = None + + # Alternative to event_map + #: List of events the plugin can handle, name the functions exactly like eventname. + event_list = None # dont make duplicate entries in event_map + + #: periodic call interval in secondc + interval = 60 + + def __init__(self, core, manager): + Base.__init__(self, core) + + #: Provide information in dict here, usable by API `getInfo` + self.info = None + + #: Callback of periodical job task, used by addonmanager + self.cb = None + + #: `AddonManager` + self.manager = manager + + #register events + if self.event_map: + for event, funcs in self.event_map.iteritems(): + if type(funcs) in (list, tuple): + for f in funcs: + self.evm.addEvent(event, getattr(self,f)) + else: + self.evm.addEvent(event, getattr(self,funcs)) + + #delete for various reasons + self.event_map = None + + if self.event_list: + for f in self.event_list: + self.evm.addEvent(f, getattr(self,f)) + + self.event_list = None + + self.initPeriodical() + self.init() + self.setup() + + def initPeriodical(self): + if self.interval >=1: + self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False) + + def _periodical(self): + try: + if self.isActivated(): self.periodical() + except Exception, e: + self.core.log.error(_("Error executing addons: %s") % str(e)) + if self.core.debug: + print_exc() + + self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False) + + + def __repr__(self): + return "" % self.__name__ + + def isActivated(self): + """ checks if addon is activated""" + return True if self.__internal__ else self.getConfig("activated") + + def init(self): + pass + + def setup(self): + """ more init stuff if needed """ + pass + + def activate(self): + """ Used to activate the addon """ + if has_method(self.__class__, "coreReady"): + self.logDebug("Deprecated method .coreReady() use activate() instead") + self.coreReady() + + def deactivate(self): + """ Used to deactivate the addon. """ + pass + + def periodical(self): + pass + + def newInteractionTask(self, task): + """ new interaction task for the plugin, it MUST set the handler and timeout or will be ignored """ + pass + + def taskCorrect(self, task): + pass + + def taskInvalid(self, task): + pass + + # public events starts from here + def downloadPreparing(self, pyfile): + pass + + def downloadFinished(self, pyfile): + pass + + def downloadFailed(self, pyfile): + pass + + def packageFinished(self, pypack): + pass + + def beforeReconnecting(self, ip): + pass + + def afterReconnecting(self, ip): + pass \ No newline at end of file diff --git a/module/plugins/Base.py b/module/plugins/Base.py index 29ff3a723..b846bbd60 100644 --- a/module/plugins/Base.py +++ b/module/plugins/Base.py @@ -39,7 +39,7 @@ class Base(object): __version__ = "0.1" #: Regexp pattern which will be matched for download/crypter plugins __pattern__ = r"" - #: Internal Hook plugin which is always loaded + #: Internal addon plugin which is always loaded __internal__ = False #: Config definition: list of (name, type, verbose_name, default_value) or #: (name, type, verbose_name, short_description, default_value) @@ -50,7 +50,9 @@ class Base(object): __long_description__ = """""" #: List of needed modules __dependencies__ = tuple() - #: Tags to categorize the plugin + #: Used to assign a category to addon plugins + __category__ = "" + #: Tags to categorize the plugin, see documentation for further info __tags__ = tuple() #: Base64 encoded .png icon, please don't use sizes above ~3KB __icon__ = "" @@ -79,7 +81,7 @@ class Base(object): #: :class:`EventManager` self.evm = core.eventManager #: :class:`InteractionManager` - self.im = core.interActionManager + self.im = core.interactionManager def logInfo(self, *args, **kwargs): """ Print args to log at specific level @@ -104,7 +106,6 @@ class Base(object): else: sep = " | " - strings = [] for obj in args: if type(obj) == unicode: diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py index 6079ae8f6..15feea8e0 100644 --- a/module/plugins/Crypter.py +++ b/module/plugins/Crypter.py @@ -2,7 +2,6 @@ from traceback import print_exc -from module.Api import Destination from module.common.packagetools import parseNames from module.utils import to_list, has_method, uniqify from module.utils.fs import exists, remove, fs_encode @@ -11,22 +10,33 @@ from Base import Base, Retry class Package: """ Container that indicates new package should be created """ - def __init__(self, name, urls=None, dest=Destination.Queue): + def __init__(self, name, urls=None): self.name = name self.urls = urls if urls else [] - self.dest = dest + # nested packages + self.packs = [] - def addUrl(self, url): + def addURL(self, url): self.urls.append(url) + def addPackage(self, pack): + self.packs.append(pack) + + def getAllURLs(self): + urls = self.urls + for p in self.packs: + urls.extend(p.getAllURLs()) + return urls + + # same name and urls is enough to be equal for packages def __eq__(self, other): return self.name == other.name and self.urls == other.urls def __repr__(self): - return u". - - @author: RaNaN -""" - -from traceback import print_exc - -#from functools import wraps -from module.utils import has_method - -from Base import Base - -def class_name(p): - return p.rpartition(".")[2] - -class Expose(object): - """ used for decoration to declare rpc services """ - def __new__(cls, f, *args, **kwargs): - hookManager.addRPC(class_name(f.__module__), f.func_name, f.func_doc) - return f - -def AddEventListener(event): - """ used to register method for events """ - class _klass(object): - def __new__(cls, f, *args, **kwargs): - hookManager.addEventListener(class_name(f.__module__), f.func_name, event) - return f - return _klass - - -class ConfigHandler(object): - """ register method as config handler """ - def __new__(cls, f, *args, **kwargs): - hookManager.addConfigHandler(class_name(f.__module__), f.func_name) - return f - -def threaded(f): - #@wraps(f) - def run(*args,**kwargs): - hookManager.startThread(f, *args, **kwargs) - return run - -class Hook(Base): - """ - Base class for hook plugins. Please use @threaded decorator for all longer running task. - """ - - #: automatically register event listeners for functions, attribute will be deleted dont use it yourself - event_map = None - - # Alternative to event_map - #: List of events the plugin can handle, name the functions exactly like eventname. - event_list = None # dont make duplicate entries in event_map - - - #: periodic call interval in secondc - interval = 60 - - def __init__(self, core, manager): - Base.__init__(self, core) - - #: Provide information in dict here, usable by API `getInfo` - self.info = None - - #: Callback of periodical job task, used by hookmanager - self.cb = None - - #: `HookManager` - self.manager = manager - - #register events - if self.event_map: - for event, funcs in self.event_map.iteritems(): - if type(funcs) in (list, tuple): - for f in funcs: - self.evm.addEvent(event, getattr(self,f)) - else: - self.evm.addEvent(event, getattr(self,funcs)) - - #delete for various reasons - self.event_map = None - - if self.event_list: - for f in self.event_list: - self.evm.addEvent(f, getattr(self,f)) - - self.event_list = None - - self.initPeriodical() - self.init() - self.setup() - - def initPeriodical(self): - if self.interval >=1: - self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False) - - def _periodical(self): - try: - if self.isActivated(): self.periodical() - except Exception, e: - self.core.log.error(_("Error executing hooks: %s") % str(e)) - if self.core.debug: - print_exc() - - self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False) - - - def __repr__(self): - return "" % self.__name__ - - def isActivated(self): - """ checks if hook is activated""" - return True if self.__internal__ else self.getConfig("activated") - - def init(self): - pass - - def setup(self): - """ more init stuff if needed """ - pass - - def activate(self): - """ Used to activate the hook """ - if has_method(self.__class__, "coreReady"): - self.logDebug("Deprecated method .coreReady() use activated() instead") - self.coreReady() - - def deactivate(self): - """ Used to deactivate the hook. """ - pass - - def periodical(self): - pass - - def newCaptchaTask(self, task): - """ new captcha task for the plugin, it MUST set the handler and timeout or will be ignored """ - pass - - def captchaCorrect(self, task): - pass - - def captchaInvalid(self, task): - pass - - # public events starts from here - def downloadPreparing(self, pyfile): - pass - - def downloadFinished(self, pyfile): - pass - - def downloadFailed(self, pyfile): - pass - - def packageFinished(self, pypack): - pass - - def beforeReconnecting(self, ip): - pass - - def afterReconnecting(self, ip): - pass \ No newline at end of file diff --git a/module/plugins/Hoster.py b/module/plugins/Hoster.py index fc9e23132..32c587aa5 100644 --- a/module/plugins/Hoster.py +++ b/module/plugins/Hoster.py @@ -185,7 +185,7 @@ class Hoster(Base): 10 - not implemented 20 - unknown error """ - #@TODO checksum check hook + #@TODO checksum check addon return True, 10 @@ -365,7 +365,7 @@ class Hoster(Base): filename = join(location, name) - self.core.hookManager.dispatchEvent("downloadStarts", self.pyfile, url, filename) + self.core.addonManager.dispatchEvent("downloadStarts", self.pyfile, url, filename) try: newname = self.req.httpDownload(url, filename, get=get, post=post, ref=ref, cookies=cookies, diff --git a/module/plugins/MultiHoster.py b/module/plugins/MultiHoster.py index abbc14466..1936478b4 100644 --- a/module/plugins/MultiHoster.py +++ b/module/plugins/MultiHoster.py @@ -15,7 +15,7 @@ class MultiHoster(Account): """ Base class for MultiHoster services. This is also an Account instance so you should see :class:`Account` and overwrite necessary methods. - Multihoster becomes only active when an Account was entered and the MultiHoster hook was activated. + Multihoster becomes only active when an Account was entered and the MultiHoster addon was activated. You need to overwrite `loadHosterList` and a corresponding :class:`Hoster` plugin with the same name should be available to make your service working. """ diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 4e2fa21ed..733cd2c5d 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -30,9 +30,11 @@ from module.plugins.Base import Base from new_collections import namedtuple +#TODO: ignores not updatable + # ignore these plugin configs, mainly because plugins were wiped out IGNORE = ( - "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('hooks', 'UnRar'), + "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('addons', 'UnRar'), 'EasyShareCom', 'FlyshareCz' ) @@ -41,7 +43,7 @@ PluginTuple = namedtuple("PluginTuple", "version re deps user path") class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." - TYPES = ("crypter", "hoster", "captcha", "accounts", "hooks", "internal") + TYPES = ("crypter", "hoster", "accounts", "addons", "internal") BUILTIN = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s?(True|False|None|[0-9x.]+)', re.I) SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(?. + + @author: mkaay, RaNaN +""" + +try: + from json import loads +except ImportError: + from simplejson import loads + +from thread import start_new_thread +from pycurl import FORM_FILE, LOW_SPEED_TIME + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader + +from module.plugins.Addon import Addon + +PYLOAD_KEY = "9f65e7f381c3af2b076ea680ae96b0b7" + +class CaptchaTraderException(Exception): + def __init__(self, err): + self.err = err + + def getCode(self): + return self.err + + def __str__(self): + return "" % self.err + + def __repr__(self): + return "" % self.err + +class CaptchaTrader(Addon): + __name__ = "CaptchaTrader" + __version__ = "0.13" + __description__ = """send captchas to captchatrader.com""" + __config__ = [("activated", "bool", "Activated", True), + ("username", "str", "Username", ""), + ("force", "bool", "Force CT even if client is connected", False), + ("passkey", "password", "Password", ""),] + __author_name__ = ("RaNaN") + __author_mail__ = ("RaNaN@pyload.org") + + SUBMIT_URL = "http://captchatrader.com/api/submit" + RESPOND_URL = "http://captchatrader.com/api/respond" + GETCREDITS_URL = "http://captchatrader.com/api/get_credits/username:%(user)s/password:%(password)s/" + + def setup(self): + self.info = {} + + def getCredits(self): + json = getURL(CaptchaTrader.GETCREDITS_URL % {"user": self.getConfig("username"), + "password": self.getConfig("passkey")}) + response = loads(json) + if response[0] < 0: + raise CaptchaTraderException(response[1]) + else: + self.logInfo(_("%s credits left") % response[1]) + self.info["credits"] = response[1] + return response[1] + + def submit(self, captcha, captchaType="file", match=None): + if not PYLOAD_KEY: + raise CaptchaTraderException("No API Key Specified!") + + #if type(captcha) == str and captchaType == "file": + # raise CaptchaTraderException("Invalid Type") + assert captchaType in ("file", "url-jpg", "url-jpeg", "url-png", "url-bmp") + + req = getRequest() + + #raise timeout threshold + req.c.setopt(LOW_SPEED_TIME, 80) + + try: + json = req.load(CaptchaTrader.SUBMIT_URL, post={"api_key": PYLOAD_KEY, + "username": self.getConfig("username"), + "password": self.getConfig("passkey"), + "value": (FORM_FILE, captcha), + "type": captchaType}, multipart=True) + finally: + req.close() + + response = loads(json) + if response[0] < 0: + raise CaptchaTraderException(response[1]) + + ticket = response[0] + result = response[1] + self.logDebug("result %s : %s" % (ticket,result)) + + return ticket, result + + def respond(self, ticket, success): + try: + json = getURL(CaptchaTrader.RESPOND_URL, post={"is_correct": 1 if success else 0, + "username": self.getConfig("username"), + "password": self.getConfig("passkey"), + "ticket": ticket}) + + response = loads(json) + if response[0] < 0: + raise CaptchaTraderException(response[1]) + + except BadHeader, e: + self.logError(_("Could not send response."), str(e)) + + def newCaptchaTask(self, task): + if not task.isTextual(): + return False + + if not self.getConfig("username") or not self.getConfig("passkey"): + return False + + if self.core.isClientConnected() and not self.getConfig("force"): + return False + + if self.getCredits() > 10: + task.handler.append(self) + task.setWaiting(100) + start_new_thread(self.processCaptcha, (task,)) + + else: + self.logInfo(_("Your CaptchaTrader Account has not enough credits")) + + def captchaCorrect(self, task): + if "ticket" in task.data: + ticket = task.data["ticket"] + self.respond(ticket, True) + + def captchaInvalid(self, task): + if "ticket" in task.data: + ticket = task.data["ticket"] + self.respond(ticket, False) + + def processCaptcha(self, task): + c = task.captchaFile + try: + ticket, result = self.submit(c) + except CaptchaTraderException, e: + task.error = e.getCode() + return + + task.data["ticket"] = ticket + task.setResult(result) diff --git a/module/plugins/addons/ClickAndLoad.py b/module/plugins/addons/ClickAndLoad.py new file mode 100644 index 000000000..6d6928557 --- /dev/null +++ b/module/plugins/addons/ClickAndLoad.py @@ -0,0 +1,89 @@ +# -*- 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 . + + @author: RaNaN + @interface-version: 0.2 +""" + +import socket +import thread + +from module.plugins.Addon import Addon + +class ClickAndLoad(Addon): + __name__ = "ClickAndLoad" + __version__ = "0.2" + __description__ = """Gives abillity to use jd's click and load. depends on webinterface""" + __config__ = [("activated", "bool", "Activated", "True"), + ("extern", "bool", "Allow external link adding", "False")] + __author_name__ = ("RaNaN", "mkaay") + __author_mail__ = ("RaNaN@pyload.de", "mkaay@mkaay.de") + + def activate(self): + self.port = int(self.core.config['webinterface']['port']) + if self.core.config['webinterface']['activated']: + try: + if self.getConfig("extern"): + ip = "0.0.0.0" + else: + ip = "127.0.0.1" + + thread.start_new_thread(proxy, (self, ip, self.port, 9666)) + except: + self.log.error("ClickAndLoad port already in use.") + + +def proxy(self, *settings): + thread.start_new_thread(server, (self,) + settings) + lock = thread.allocate_lock() + lock.acquire() + lock.acquire() + + +def server(self, *settings): + try: + dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + dock_socket.bind((settings[0], settings[2])) + dock_socket.listen(5) + while True: + client_socket = dock_socket.accept()[0] + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.connect(("127.0.0.1", settings[1])) + thread.start_new_thread(forward, (client_socket, server_socket)) + thread.start_new_thread(forward, (server_socket, client_socket)) + except socket.error, e: + if hasattr(e, "errno"): + errno = e.errno + else: + errno = e.args[0] + + if errno == 98: + self.core.log.warning(_("Click'N'Load: Port 9666 already in use")) + return + thread.start_new_thread(server, (self,) + settings) + except: + thread.start_new_thread(server, (self,) + settings) + + +def forward(source, destination): + string = ' ' + while string: + string = source.recv(1024) + if string: + destination.sendall(string) + else: + #source.shutdown(socket.SHUT_RD) + destination.shutdown(socket.SHUT_WR) diff --git a/module/plugins/addons/EasybytezCom.py b/module/plugins/addons/EasybytezCom.py new file mode 100644 index 000000000..4dd39cca6 --- /dev/null +++ b/module/plugins/addons/EasybytezCom.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster +import re + +def getConfigSet(option): + s = set(option.lower().replace(',','|').split('|')) + s.discard(u'') + return s + +class EasybytezCom(MultiHoster): + __name__ = "EasybytezCom" + __version__ = "0.01" + __type__ = "hook" + __config__ = [("activated", "bool", "Activated", "False"), + ("includeHoster", "str", "Use only for downloads from (comma-separated hosters)", ""), + ("excludeHoster", "str", "Do not use for downloads from (comma-separated hosters)", "")] + __description__ = """EasyBytez.com hook plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def getHoster(self): + + hoster = set(['2shared.com', 'easy-share.com', 'filefactory.com', 'fileserve.com', 'filesonic.com', 'hotfile.com', 'mediafire.com', 'megaupload.com', 'netload.in', 'rapidshare.com', 'uploading.com', 'wupload.com', 'oron.com', 'uploadstation.com', 'ul.to', 'uploaded.to']) + + option = self.getConfig('includeHoster').strip() + if option: hoster &= getConfigSet(option) + option = self.getConfig('excludeHoster').strip() + if option: hoster -= getConfigSet(option) + + return list(hoster) \ No newline at end of file diff --git a/module/plugins/addons/Ev0InFetcher.py b/module/plugins/addons/Ev0InFetcher.py new file mode 100644 index 000000000..aeb46320a --- /dev/null +++ b/module/plugins/addons/Ev0InFetcher.py @@ -0,0 +1,87 @@ +# -*- 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 . + + @author: mkaay +""" +from module.lib import feedparser +from time import mktime, time + +from module.plugins.Addon import Addon + +class Ev0InFetcher(Addon): + __name__ = "Ev0InFetcher" + __version__ = "0.2" + __description__ = """checks rss feeds for ev0.in""" + __config__ = [("activated", "bool", "Activated", "False"), + ("interval", "int", "Check interval in minutes", "10"), + ("queue", "bool", "Move new shows directly to Queue", False), + ("shows", "str", "Shows to check for (comma seperated)", ""), + ("quality", "xvid;x264;rmvb", "Video Format", "xvid"), + ("hoster", "str", "Hoster to use (comma seperated)", "NetloadIn,RapidshareCom,MegauploadCom,HotfileCom")] + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + + def setup(self): + self.interval = self.getConfig("interval") * 60 + + def filterLinks(self, links): + results = self.core.pluginManager.parseUrls(links) + sortedLinks = {} + + for url, hoster in results[0]: + if hoster not in sortedLinks: + sortedLinks[hoster] = [] + sortedLinks[hoster].append(url) + + for h in self.getConfig("hoster").split(","): + try: + return sortedLinks[h.strip()] + except: + continue + return [] + + def periodical(self): + def normalizefiletitle(filename): + filename = filename.replace('.', ' ') + filename = filename.replace('_', ' ') + filename = filename.lower() + return filename + + shows = [s.strip() for s in self.getConfig("shows").split(",")] + + feed = feedparser.parse("http://feeds.feedburner.com/ev0in/%s?format=xml" % self.getConfig("quality")) + + showStorage = {} + for show in shows: + showStorage[show] = int(self.getStorage("show_%s_lastfound" % show, 0)) + + found = False + for item in feed['items']: + for show, lastfound in showStorage.iteritems(): + if show.lower() in normalizefiletitle(item['title']) and lastfound < int(mktime(item.date_parsed)): + links = self.filterLinks(item['description'].split("
")) + packagename = item['title'].encode("utf-8") + self.core.log.info("Ev0InFetcher: new episode '%s' (matched '%s')" % (packagename, show)) + self.core.api.addPackage(packagename, links, 1 if self.getConfig("queue") else 0) + self.setStorage("show_%s_lastfound" % show, int(mktime(item.date_parsed))) + found = True + if not found: + #self.core.log.debug("Ev0InFetcher: no new episodes found") + pass + + for show, lastfound in self.getStorage().iteritems(): + if int(lastfound) > 0 and int(lastfound) + (3600*24*30) < int(time()): + self.delStorage("show_%s_lastfound" % show) + self.core.log.debug("Ev0InFetcher: cleaned '%s' record" % show) diff --git a/module/plugins/addons/ExternalScripts.py b/module/plugins/addons/ExternalScripts.py new file mode 100644 index 000000000..00fc7c114 --- /dev/null +++ b/module/plugins/addons/ExternalScripts.py @@ -0,0 +1,118 @@ +# -*- 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 . + + @author: RaNaN +""" + +import subprocess +from os import access, X_OK, makedirs +from os.path import basename + +from module.plugins.Addon import Addon +from module.utils.fs import save_join, exists, join, listdir + +class ExternalScripts(Addon): + __name__ = "ExternalScripts" + __version__ = "0.21" + __description__ = """Run external scripts""" + __config__ = [("activated", "bool", "Activated", "True")] + __author_name__ = ("mkaay", "RaNaN", "spoob") + __author_mail__ = ("mkaay@mkaay.de", "ranan@pyload.org", "spoob@pyload.org") + + event_list = ["unrarFinished", "allDownloadsFinished", "allDownloadsProcessed"] + + def setup(self): + self.scripts = {} + + folders = ['download_preparing', 'download_finished', 'package_finished', + 'before_reconnect', 'after_reconnect', 'unrar_finished', + 'all_dls_finished', 'all_dls_processed'] + + for folder in folders: + + self.scripts[folder] = [] + + self.initPluginType(folder, join(pypath, 'scripts', folder)) + self.initPluginType(folder, join('scripts', folder)) + + for script_type, names in self.scripts.iteritems(): + if names: + self.logInfo((_("Installed scripts for %s: ") % script_type ) + ", ".join([basename(x) for x in names])) + + + def initPluginType(self, folder, path): + if not exists(path): + try: + makedirs(path) + except : + self.logDebug("Script folder %s not created" % folder) + return + + for f in listdir(path): + if f.startswith("#") or f.startswith(".") or f.startswith("_") or f.endswith("~") or f.endswith(".swp"): + continue + + if not access(join(path,f), X_OK): + self.logWarning(_("Script not executable:") + " %s/%s" % (folder, f)) + + self.scripts[folder].append(join(path, f)) + + def callScript(self, script, *args): + try: + cmd = [script] + [str(x) if not isinstance(x, basestring) else x for x in args] + #output goes to pyload + subprocess.Popen(cmd, bufsize=-1) + except Exception, e: + self.logError(_("Error in %(script)s: %(error)s") % { "script" :basename(script), "error": str(e)}) + + def downloadPreparing(self, pyfile): + for script in self.scripts['download_preparing']: + self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.id) + + def downloadFinished(self, pyfile): + for script in self.scripts['download_finished']: + self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.name, pyfile.id, + save_join(self.core.config['general']['download_folder'], pyfile.package().folder, pyfile.name), + pyfile.id) + + + def packageFinished(self, pypack): + for script in self.scripts['package_finished']: + folder = self.core.config['general']['download_folder'] + folder = save_join(folder, pypack.folder) + + self.callScript(script, pypack.name, folder, pypack.id) + + def beforeReconnecting(self, ip): + for script in self.scripts['before_reconnect']: + self.callScript(script, ip) + + def afterReconnecting(self, ip): + for script in self.scripts['after_reconnect']: + self.callScript(script, ip) + + def unrarFinished(self, folder, fname): + for script in self.scripts["unrar_finished"]: + self.callScript(script, folder, fname) + + def allDownloadsFinished(self): + for script in self.scripts["all_dls_finished"]: + self.callScript(script) + + def allDownloadsProcessed(self): + for script in self.scripts["all_dls_processed"]: + self.callScript(script) + diff --git a/module/plugins/addons/ExtractArchive.py b/module/plugins/addons/ExtractArchive.py new file mode 100644 index 000000000..5f749ed0d --- /dev/null +++ b/module/plugins/addons/ExtractArchive.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import os +from os.path import basename, isfile, isdir, join +from traceback import print_exc +from copy import copy + +# monkey patch bug in python 2.6 and lower +# see http://bugs.python.org/issue6122 +# http://bugs.python.org/issue1236 +# http://bugs.python.org/issue1731717 +if sys.version_info < (2, 7) and os.name != "nt": + from subprocess import Popen + import errno + + def _eintr_retry_call(func, *args): + while True: + try: + return func(*args) + except OSError, e: + if e.errno == errno.EINTR: + continue + raise + + # unsued timeout option for older python version + def wait(self, timeout=0): + """Wait for child process to terminate. Returns returncode + attribute.""" + if self.returncode is None: + try: + pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) + except OSError, e: + if e.errno != errno.ECHILD: + raise + # This happens if SIGCLD is set to be ignored or waiting + # for child processes has otherwise been disabled for our + # process. This child is dead, we can't get the status. + sts = 0 + self._handle_exitstatus(sts) + return self.returncode + + Popen.wait = wait + +if os.name != "nt": + from os import chown + from pwd import getpwnam + from grp import getgrnam + +from module.utils.fs import save_join, fs_encode, exists, remove, chmod, makedirs +from module.plugins.Addon import Addon, threaded, Expose +from module.plugins.internal.AbstractExtractor import ArchiveError, CRCError, WrongPassword + +class ExtractArchive(Addon): + """ + Provides: unrarFinished (folder, filename) + """ + __name__ = "ExtractArchive" + __version__ = "0.12" + __description__ = "Extract different kind of archives" + __config__ = [("activated", "bool", "Activated", True), + ("fullpath", "bool", "Extract full path", True), + ("overwrite", "bool", "Overwrite files", True), + ("passwordfile", "file", "password file", "unrar_passwords.txt"), + ("deletearchive", "bool", "Delete archives when done", False), + ("subfolder", "bool", "Create subfolder for each package", False), + ("destination", "folder", "Extract files to", ""), + ("recursive", "bool", "Extract archives in archvies", True), + ("queue", "bool", "Wait for all downloads to be finished", True), + ("renice", "int", "CPU Priority", 0), ] + __author_name__ = ("pyload Team") + __author_mail__ = ("adminpyload.org") + + event_list = ["allDownloadsProcessed"] + + def setup(self): + self.plugins = [] + self.passwords = [] + names = [] + + for p in ("UnRar", "UnZip"): + try: + module = self.core.pluginManager.loadModule("internal", p) + klass = getattr(module, p) + if klass.checkDeps(): + names.append(p) + self.plugins.append(klass) + + except OSError, e: + if e.errno == 2: + self.logInfo(_("No %s installed") % p) + else: + self.logWarning(_("Could not activate %s") % p, str(e)) + if self.core.debug: + print_exc() + + except Exception, e: + self.logWarning(_("Could not activate %s") % p, str(e)) + if self.core.debug: + print_exc() + + if names: + self.logInfo(_("Activated") + " " + " ".join(names)) + else: + self.logInfo(_("No Extract plugins activated")) + + # queue with package ids + self.queue = [] + + @Expose + def extractPackage(self, id): + """ Extract package with given id""" + self.manager.startThread(self.extract, [id]) + + def packageFinished(self, pypack): + if self.getConfig("queue"): + self.logInfo(_("Package %s queued for later extracting") % pypack.name) + self.queue.append(pypack.id) + else: + self.manager.startThread(self.extract, [pypack.id]) + + + @threaded + def allDownloadsProcessed(self, thread): + local = copy(self.queue) + del self.queue[:] + self.extract(local, thread) + + + def extract(self, ids, thread=None): + # reload from txt file + self.reloadPasswords() + + # dl folder + dl = self.config['general']['download_folder'] + + extracted = [] + + #iterate packages -> plugins -> targets + for pid in ids: + p = self.core.files.getPackage(pid) + self.logInfo(_("Check package %s") % p.name) + if not p: continue + + # determine output folder + out = save_join(dl, p.folder, "") + # force trailing slash + + if self.getConfig("destination") and self.getConfig("destination").lower() != "none": + + out = save_join(dl, p.folder, self.getConfig("destination"), "") + #relative to package folder if destination is relative, otherwise absolute path overwrites them + + if self.getConf("subfolder"): + out = join(out, fs_encode(p.folder)) + + if not exists(out): + makedirs(out) + + files_ids = [(save_join(dl, p.folder, x["name"]), x["id"]) for x in p.getChildren().itervalues()] + matched = False + + # check as long there are unseen files + while files_ids: + new_files_ids = [] + + for plugin in self.plugins: + targets = plugin.getTargets(files_ids) + if targets: + self.logDebug("Targets for %s: %s" % (plugin.__name__, targets)) + matched = True + for target, fid in targets: + if target in extracted: + self.logDebug(basename(target), "skipped") + continue + extracted.append(target) #prevent extracting same file twice + + klass = plugin(self, target, out, self.getConfig("fullpath"), self.getConfig("overwrite"), + self.getConfig("renice")) + klass.init() + + self.logInfo(basename(target), _("Extract to %s") % out) + new_files = self.startExtracting(klass, fid, p.password.strip().splitlines(), thread) + self.logDebug("Extracted: %s" % new_files) + self.setPermissions(new_files) + + for file in new_files: + if not exists(file): + self.logDebug("new file %s does not exists" % file) + continue + if self.getConfig("recursive") and isfile(file): + new_files_ids.append((file, fid)) #append as new target + + files_ids = new_files_ids # also check extracted files + + if not matched: self.logInfo(_("No files found to extract")) + + + + def startExtracting(self, plugin, fid, passwords, thread): + pyfile = self.core.files.getFile(fid) + if not pyfile: return [] + + pyfile.setCustomStatus(_("extracting")) + thread.addActive(pyfile) #keep this file until everything is done + + try: + progress = lambda x: pyfile.setProgress(x) + success = False + + if not plugin.checkArchive(): + plugin.extract(progress) + success = True + else: + self.logInfo(basename(plugin.file), _("Password protected")) + self.logDebug("Passwords: %s" % str(passwords)) + + pwlist = copy(self.getPasswords()) + #remove already supplied pws from list (only local) + for pw in passwords: + if pw in pwlist: pwlist.remove(pw) + + for pw in passwords + pwlist: + try: + self.logDebug("Try password: %s" % pw) + if plugin.checkPassword(pw): + plugin.extract(progress, pw) + self.addPassword(pw) + success = True + break + except WrongPassword: + self.logDebug("Password was wrong") + + if not success: + self.logError(basename(plugin.file), _("Wrong password")) + return [] + + if self.core.debug: + self.logDebug("Would delete: %s" % ", ".join(plugin.getDeleteFiles())) + + if self.getConfig("deletearchive"): + files = plugin.getDeleteFiles() + self.logInfo(_("Deleting %s files") % len(files)) + for f in files: + if exists(f): remove(f) + else: self.logDebug("%s does not exists" % f) + + self.logInfo(basename(plugin.file), _("Extracting finished")) + self.manager.dispatchEvent("unrarFinished", plugin.out, plugin.file) + + return plugin.getExtractedFiles() + + + except ArchiveError, e: + self.logError(basename(plugin.file), _("Archive Error"), str(e)) + except CRCError: + self.logError(basename(plugin.file), _("CRC Mismatch")) + except Exception, e: + if self.core.debug: + print_exc() + self.logError(basename(plugin.file), _("Unknown Error"), str(e)) + + return [] + + @Expose + def getPasswords(self): + """ List of saved passwords """ + return self.passwords + + + def reloadPasswords(self): + pwfile = self.getConfig("passwordfile") + if not exists(pwfile): + open(pwfile, "wb").close() + + passwords = [] + f = open(pwfile, "rb") + for pw in f.read().splitlines(): + passwords.append(pw) + f.close() + + self.passwords = passwords + + + @Expose + def addPassword(self, pw): + """ Adds a password to saved list""" + pwfile = self.getConfig("passwordfile") + + if pw in self.passwords: self.passwords.remove(pw) + self.passwords.insert(0, pw) + + f = open(pwfile, "wb") + for pw in self.passwords: + f.write(pw + "\n") + f.close() + + def setPermissions(self, files): + for f in files: + if not exists(f): continue + try: + if self.core.config["permission"]["change_file"]: + if isfile(f): + chmod(f, int(self.core.config["permission"]["file"], 8)) + elif isdir(f): + chmod(f, int(self.core.config["permission"]["folder"], 8)) + + if self.core.config["permission"]["change_dl"] and os.name != "nt": + uid = getpwnam(self.config["permission"]["user"])[2] + gid = getgrnam(self.config["permission"]["group"])[2] + chown(f, uid, gid) + except Exception, e: + self.log.warning(_("Setting User and Group failed"), e) diff --git a/module/plugins/addons/HotFolder.py b/module/plugins/addons/HotFolder.py new file mode 100644 index 000000000..d05026448 --- /dev/null +++ b/module/plugins/addons/HotFolder.py @@ -0,0 +1,85 @@ +# -*- 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 . + + @author: RaNaN + @interface-version: 0.2 +""" + +from os import makedirs +from os import listdir +from os.path import exists +from os.path import join +from os.path import isfile +from shutil import move +import time + +from module.plugins.Addon import Addon + +class HotFolder(Addon): + __name__ = "HotFolder" + __version__ = "0.1" + __description__ = """observe folder and file for changes and add container and links""" + __config__ = [ ("activated", "bool", "Activated" , "False"), + ("folder", "str", "Folder to observe", "container"), + ("watch_file", "bool", "Observe link file", "False"), + ("keep", "bool", "Keep added containers", "True"), + ("file", "str", "Link file", "links.txt")] + __threaded__ = [] + __author_name__ = ("RaNaN") + __author_mail__ = ("RaNaN@pyload.de") + + def setup(self): + self.interval = 10 + + def periodical(self): + + if not exists(join(self.getConfig("folder"), "finished")): + makedirs(join(self.getConfig("folder"), "finished")) + + if self.getConfig("watch_file"): + + if not exists(self.getConfig("file")): + f = open(self.getConfig("file"), "wb") + f.close() + + + f = open(self.getConfig("file"), "rb") + content = f.read().strip() + f.close() + f = open(self.getConfig("file"), "wb") + f.close() + if content: + name = "%s_%s.txt" % (self.getConfig("file"), time.strftime("%H-%M-%S_%d%b%Y") ) + + f = open(join(self.getConfig("folder"), "finished", name), "wb") + f.write(content) + f.close() + + self.core.api.addPackage(f.name, [f.name], 1) + + for f in listdir(self.getConfig("folder")): + path = join(self.getConfig("folder"), f) + + if not isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): + continue + + newpath = join(self.getConfig("folder"), "finished", f if self.getConfig("keep") else "tmp_"+f) + move(path, newpath) + + self.log.info(_("Added %s from HotFolder") % f) + self.core.api.addPackage(f, [newpath], 1) + + \ No newline at end of file diff --git a/module/plugins/addons/IRCInterface.py b/module/plugins/addons/IRCInterface.py new file mode 100644 index 000000000..ddaa40613 --- /dev/null +++ b/module/plugins/addons/IRCInterface.py @@ -0,0 +1,425 @@ +# -*- 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 . + + @author: RaNaN + @author: jeix + @interface-version: 0.2 +""" + +from select import select +import socket +from threading import Thread +import time +from time import sleep +from traceback import print_exc +import re + +from module.plugins.Addon import Addon +from module.network.RequestFactory import getURL +from module.utils import formatSize + +from pycurl import FORM_FILE + +class IRCInterface(Thread, Addon): + __name__ = "IRCInterface" + __version__ = "0.1" + __description__ = """connect to irc and let owner perform different tasks""" + __config__ = [("activated", "bool", "Activated", "False"), + ("host", "str", "IRC-Server Address", "Enter your server here!"), + ("port", "int", "IRC-Server Port", "6667"), + ("ident", "str", "Clients ident", "pyload-irc"), + ("realname", "str", "Realname", "pyload-irc"), + ("nick", "str", "Nickname the Client will take", "pyLoad-IRC"), + ("owner", "str", "Nickname the Client will accept commands from", "Enter your nick here!"), + ("info_file", "bool", "Inform about every file finished", "False"), + ("info_pack", "bool", "Inform about every package finished", "True"), + ("captcha", "bool", "Send captcha requests", "True")] + __author_name__ = ("Jeix") + __author_mail__ = ("Jeix@hasnomail.com") + + def __init__(self, core, manager): + Thread.__init__(self) + Addon.__init__(self, core, manager) + self.setDaemon(True) + # self.sm = core.server_methods + self.api = core.api #todo, only use api + + def coreReady(self): + self.new_package = {} + + self.abort = False + + self.links_added = 0 + self.more = [] + + self.start() + + + def packageFinished(self, pypack): + try: + if self.getConfig("info_pack"): + self.response(_("Package finished: %s") % pypack.name) + except: + pass + + def downloadFinished(self, pyfile): + try: + if self.getConfig("info_file"): + self.response(_("Download finished: %(name)s @ %(plugin)s ") % { "name" : pyfile.name, "plugin": pyfile.pluginname} ) + except: + pass + + def newCaptchaTask(self, task): + if self.getConfig("captcha") and task.isTextual(): + task.handler.append(self) + task.setWaiting(60) + + page = getURL("http://www.freeimagehosting.net/upload.php", post={"attached" : (FORM_FILE, task.captchaFile)}, multipart=True) + + url = re.search(r"\[img\]([^\[]+)\[/img\]\[/url\]", page).group(1) + self.response(_("New Captcha Request: %s") % url) + self.response(_("Answer with 'c %s text on the captcha'") % task.id) + + def run(self): + # connect to IRC etc. + self.sock = socket.socket() + host = self.getConfig("host") + self.sock.connect((host, self.getConfig("port"))) + nick = self.getConfig("nick") + self.sock.send("NICK %s\r\n" % nick) + self.sock.send("USER %s %s bla :%s\r\n" % (nick, host, nick)) + for t in self.getConfig("owner").split(): + if t.strip().startswith("#"): + self.sock.send("JOIN %s\r\n" % t.strip()) + self.log.info("pyLoad IRC: Connected to %s!" % host) + self.log.info("pyLoad IRC: Switching to listening mode!") + try: + self.main_loop() + + except IRCError, ex: + self.sock.send("QUIT :byebye\r\n") + print_exc() + self.sock.close() + + + def main_loop(self): + readbuffer = "" + while True: + sleep(1) + fdset = select([self.sock], [], [], 0) + if self.sock not in fdset[0]: + continue + + if self.abort: + raise IRCError("quit") + + readbuffer += self.sock.recv(1024) + temp = readbuffer.split("\n") + readbuffer = temp.pop() + + for line in temp: + line = line.rstrip() + first = line.split() + + if first[0] == "PING": + self.sock.send("PONG %s\r\n" % first[1]) + + if first[0] == "ERROR": + raise IRCError(line) + + msg = line.split(None, 3) + if len(msg) < 4: + continue + + msg = { + "origin":msg[0][1:], + "action":msg[1], + "target":msg[2], + "text":msg[3][1:] + } + + self.handle_events(msg) + + + def handle_events(self, msg): + if not msg["origin"].split("!", 1)[0] in self.getConfig("owner").split(): + return + + if msg["target"].split("!", 1)[0] != self.getConfig("nick"): + return + + if msg["action"] != "PRIVMSG": + return + + # HANDLE CTCP ANTI FLOOD/BOT PROTECTION + if msg["text"] == "\x01VERSION\x01": + self.log.debug("Sending CTCP VERSION.") + self.sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) + return + elif msg["text"] == "\x01TIME\x01": + self.log.debug("Sending CTCP TIME.") + self.sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) + return + elif msg["text"] == "\x01LAG\x01": + self.log.debug("Received CTCP LAG.") # don't know how to answer + return + + trigger = "pass" + args = None + + try: + temp = msg["text"].split() + trigger = temp[0] + if len(temp) > 1: + args = temp[1:] + except: + pass + + handler = getattr(self, "event_%s" % trigger, self.event_pass) + try: + res = handler(args) + for line in res: + self.response(line, msg["origin"]) + except Exception, e: + self.log.error("pyLoad IRC: "+ repr(e)) + + + def response(self, msg, origin=""): + if origin == "": + for t in self.getConfig("owner").split(): + self.sock.send("PRIVMSG %s :%s\r\n" % (t.strip(), msg)) + else: + self.sock.send("PRIVMSG %s :%s\r\n" % (origin.split("!", 1)[0], msg)) + + +#### Events + def event_pass(self, args): + return [] + + def event_status(self, args): + downloads = self.api.statusDownloads() + if not downloads: + return ["INFO: There are no active downloads currently."] + + temp_progress = "" + lines = ["ID - Name - Status - Speed - ETA - Progress"] + for data in downloads: + + if data.status == 5: + temp_progress = data.format_wait + else: + temp_progress = "%d%% (%s)" % (data.percent, data.format_size) + + lines.append("#%d - %s - %s - %s - %s - %s" % + ( + data.fid, + data.name, + data.statusmsg, + "%s/s" % formatSize(data.speed), + "%s" % data.format_eta, + temp_progress + ) + ) + return lines + + def event_queue(self, args): + ps = self.api.getQueue() + + if not ps: + return ["INFO: There are no packages in queue."] + + lines = [] + for pack in ps: + lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.fids) )) + + return lines + + def event_collector(self, args): + ps = self.api.getCollector() + if not ps: + return ["INFO: No packages in collector!"] + + lines = [] + for pack in ps: + lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.fids) )) + + return lines + + def event_info(self, args): + if not args: + return ['ERROR: Use info like this: info '] + + info = self.api.getFileData(int(args[0])) + + if not info: + return ["ERROR: Link doesn't exists."] + + return ['LINK #%s: %s (%s) [%s][%s]' % (info.fid, info.name, info.format_size, info.status_msg, + info.plugin)] + + def event_packinfo(self, args): + if not args: + return ['ERROR: Use packinfo like this: packinfo '] + + lines = [] + pack = self.api.getPackageData(int(args[0])) + + if not pack: + return ["ERROR: Package doesn't exists."] + + id = args[0] + + self.more = [] + + lines.append('PACKAGE #%s: "%s" with %d links' % (id, pack.name, len(pack.links)) ) + for pyfile in pack.links: + self.more.append('LINK #%s: %s (%s) [%s][%s]' % (pyfile.fid, pyfile.name, pyfile.format_size, + pyfile.statusmsg, pyfile.plugin)) + + if len(self.more) < 6: + lines.extend(self.more) + self.more = [] + else: + lines.extend(self.more[:6]) + self.more = self.more[6:] + lines.append("%d more links do display." % len(self.more)) + + + return lines + + def event_more(self, args): + if not self.more: + return ["No more information to display."] + + lines = self.more[:6] + self.more = self.more[6:] + lines.append("%d more links do display." % len(self.more)) + + return lines + + def event_start(self, args): + + self.api.unpauseServer() + return ["INFO: Starting downloads."] + + def event_stop(self, args): + + self.api.pauseServer() + return ["INFO: No new downloads will be started."] + + + def event_add(self, args): + if len(args) < 2: + return ['ERROR: Add links like this: "add links". ', + 'This will add the link to to the package / the package with id !'] + + + + pack = args[0].strip() + links = [x.strip() for x in args[1:]] + + count_added = 0 + count_failed = 0 + try: + id = int(pack) + pack = self.api.getPackageData(id) + if not pack: + return ["ERROR: Package doesn't exists."] + + #TODO add links + + return ["INFO: Added %d links to Package %s [#%d]" % (len(links), pack["name"], id)] + + except: + # create new package + id = self.api.addPackage(pack, links, 1) + return ["INFO: Created new Package %s [#%d] with %d links." % (pack, id, len(links))] + + + def event_del(self, args): + if len(args) < 2: + return ["ERROR: Use del command like this: del -p|-l [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] + + if args[0] == "-p": + ret = self.api.deletePackages(map(int, args[1:])) + return ["INFO: Deleted %d packages!" % len(args[1:])] + + elif args[0] == "-l": + ret = self.api.delLinks(map(int, args[1:])) + return ["INFO: Deleted %d links!" % len(args[1:])] + + else: + return ["ERROR: Use del command like this: del <-p|-l> [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] + + def event_push(self, args): + if not args: + return ["ERROR: Push package to queue like this: push "] + + id = int(args[0]) + if not self.api.getPackage_data(id): + return ["ERROR: Package #%d does not exist." % id] + + self.api.pushToQueue(id) + return ["INFO: Pushed package #%d to queue." % id] + + def event_pull(self, args): + if not args: + return ["ERROR: Pull package from queue like this: pull ."] + + id = int(args[0]) + if not self.api.getPackageData(id): + return ["ERROR: Package #%d does not exist." % id] + + self.api.pullFromQueue(id) + return ["INFO: Pulled package #%d from queue to collector." % id] + + def event_c(self, args): + """ captcha answer """ + if not args: + return ["ERROR: Captcha ID missing."] + + task = self.core.captchaManager.getTaskByID(args[0]) + if not task: + return ["ERROR: Captcha Task with ID %s does not exists." % args[0]] + + task.setResult(" ".join(args[1:])) + return ["INFO: Result %s saved." % " ".join(args[1:])] + + + def event_help(self, args): + lines = ["The following commands are available:", + "add [...] Adds link to package. (creates new package if it does not exist)", + "queue Shows all packages in the queue", + "collector Shows all packages in collector", + "del -p|-l [...] Deletes all packages|links with the ids specified", + "info Shows info of the link with id ", + "packinfo Shows info of the package with id ", + "more Shows more info when the result was truncated", + "start Starts all downloads", + "stop Stops the download (but not abort active downloads)", + "push Push package to queue", + "pull Pull package from queue", + "status Show general download status", + "help Shows this help message"] + return lines + + +class IRCError(Exception): + def __init__(self, value): + Exception.__init__(value) + self.value = value + def __str__(self): + return repr(self.value) diff --git a/module/plugins/addons/MergeFiles.py b/module/plugins/addons/MergeFiles.py new file mode 100644 index 000000000..48f997681 --- /dev/null +++ b/module/plugins/addons/MergeFiles.py @@ -0,0 +1,94 @@ +# -*- 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 . + + @author: and9000 +""" + +import os +import re +import sys +import traceback + +from os.path import join +from module.utils import save_join, fs_encode +from module.plugins.Addon import Addon + +BUFFER_SIZE = 4096 + +class MergeFiles(Addon): + __name__ = "MergeFiles" + __version__ = "0.1" + __description__ = "Merges parts splitted with hjsplit" + __config__ = [ + ("activated" , "bool" , "Activated" , "False"), + ] + __threaded__ = ["packageFinished"] + __author_name__ = ("and9000") + __author_mail__ = ("me@has-no-mail.com") + + def setup(self): + # nothing to do + pass + + def packageFinished(self, pack): + files = {} + fid_dict = {} + for fid, data in pack.getChildren().iteritems(): + if re.search("\.[0-9]{3}$", data["name"]): + if data["name"][:-4] not in files: + files[data["name"][:-4]] = [] + files[data["name"][:-4]].append(data["name"]) + files[data["name"][:-4]].sort() + fid_dict[data["name"]] = fid + + download_folder = self.core.config['general']['download_folder'] + + if self.core.config['general']['folder_per_package']: + download_folder = save_join(download_folder, pack.folder) + + for name, file_list in files.iteritems(): + self.core.log.info("Starting merging of %s" % name) + final_file = open(join(download_folder, fs_encode(name)), "wb") + + for splitted_file in file_list: + self.core.log.debug("Merging part %s" % splitted_file) + pyfile = self.core.files.getFile(fid_dict[splitted_file]) + pyfile.setStatus("processing") + try: + s_file = open(os.path.join(download_folder, splitted_file), "rb") + size_written = 0 + s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file))) + while True: + f_buffer = s_file.read(BUFFER_SIZE) + if f_buffer: + final_file.write(f_buffer) + size_written += BUFFER_SIZE + pyfile.setProgress((size_written*100)/s_file_size) + else: + break + s_file.close() + self.core.log.debug("Finished merging part %s" % splitted_file) + except Exception, e: + print traceback.print_exc() + finally: + pyfile.setProgress(100) + pyfile.setStatus("finished") + pyfile.release() + + final_file.close() + self.core.log.info("Finished merging of %s" % name) + + diff --git a/module/plugins/addons/MultiHome.py b/module/plugins/addons/MultiHome.py new file mode 100644 index 000000000..af3f55416 --- /dev/null +++ b/module/plugins/addons/MultiHome.py @@ -0,0 +1,82 @@ +# -*- 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 . + + @author: mkaay +""" + +from module.plugins.Addon import Addon +from time import time + +class MultiHome(Addon): + __name__ = "MultiHome" + __version__ = "0.1" + __description__ = """ip address changer""" + __config__ = [ ("activated", "bool", "Activated" , "False"), + ("interfaces", "str", "Interfaces" , "None") ] + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + + def setup(self): + self.register = {} + self.interfaces = [] + self.parseInterfaces(self.getConfig("interfaces").split(";")) + if not self.interfaces: + self.parseInterfaces([self.config["download"]["interface"]]) + self.setConfig("interfaces", self.toConfig()) + + def toConfig(self): + return ";".join([i.adress for i in self.interfaces]) + + def parseInterfaces(self, interfaces): + for interface in interfaces: + if not interface or str(interface).lower() == "none": + continue + self.interfaces.append(Interface(interface)) + + def coreReady(self): + requestFactory = self.core.requestFactory + oldGetRequest = requestFactory.getRequest + def getRequest(pluginName, account=None): + iface = self.bestInterface(pluginName, account) + if iface: + iface.useFor(pluginName, account) + requestFactory.iface = lambda: iface.adress + self.log.debug("Multihome: using address: "+iface.adress) + return oldGetRequest(pluginName, account) + requestFactory.getRequest = getRequest + + def bestInterface(self, pluginName, account): + best = None + for interface in self.interfaces: + if not best or interface.lastPluginAccess(pluginName, account) < best.lastPluginAccess(pluginName, account): + best = interface + return best + +class Interface(object): + def __init__(self, adress): + self.adress = adress + self.history = {} + + def lastPluginAccess(self, pluginName, account): + if (pluginName, account) in self.history: + return self.history[(pluginName, account)] + return 0 + + def useFor(self, pluginName, account): + self.history[(pluginName, account)] = time() + + def __repr__(self): + return "" % self.adress diff --git a/module/plugins/addons/MultiHoster.py b/module/plugins/addons/MultiHoster.py new file mode 100644 index 000000000..05d25b958 --- /dev/null +++ b/module/plugins/addons/MultiHoster.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from types import MethodType + +from module.plugins.MultiHoster import MultiHoster as MultiHosterAccount, normalize +from module.plugins.Addon import Addon, AddEventListener +from module.plugins.PluginManager import PluginTuple + +class MultiHoster(Addon): + __version__ = "0.1" + __internal__ = True + __description__ = "Gives ability to use MultiHoster services. You need to add your account first." + __config__ = [] + __author_mail__ = ("pyLoad Team",) + __author_mail__ = ("support@pyload.org",) + + #TODO: multiple accounts - multihoster / config options + + def init(self): + + # overwritten plugins + self.plugins = {} + + def addHoster(self, account): + + self.logDebug("New MultiHoster %s" % account.__name__) + + pluginMap = {} + for name in self.core.pluginManager.getPlugins("hoster").keys(): + pluginMap[name.lower()] = name + + supported = [] + new_supported = [] + + for hoster in account.getHosterList(): + name = normalize(hoster) + + if name in pluginMap: + supported.append(pluginMap[name]) + else: + new_supported.append(hoster) + + if not supported and not new_supported: + account.logError(_("No Hoster loaded")) + return + + klass = self.core.pluginManager.getPluginClass(account.__name__) + + # inject plugin plugin + account.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(supported))) + for hoster in supported: + self.plugins[hoster] = klass + + account.logDebug("New Hosters: %s" % ", ".join(sorted(new_supported))) + + # create new regexp + regexp = r".*(%s).*" % "|".join([klass.__pattern__] + [x.replace(".", "\\.") for x in new_supported]) + + # recreate plugin tuple for new regexp + hoster = self.core.pluginManager.getPlugins("hoster") + p = hoster[account.__name__] + new = PluginTuple(p.version, re.compile(regexp), p.deps, p.user, p.path) + hoster[account.__name__] = new + + + + @AddEventListener("accountDeleted") + def refreshAccounts(self, plugin=None, user=None): + + self.plugins = {} + + for name, account in self.core.accountManager.iterAccounts(): + if isinstance(account, MultiHosterAccount) and account.isUsable(): + self.addHoster(account) + + @AddEventListener("accountUpdated") + def refreshAccount(self, plugin, user): + + account = self.core.accountManager.getAccount(plugin, user) + if isinstance(account, MultiHosterAccount) and account.isUsable(): + self.addHoster(account) + + def activate(self): + self.refreshAccounts() + + # new method for plugin manager + def getPlugin(self2, name): + if name in self.plugins: + return self.plugins[name] + return self2.getPluginClass(name) + + pm = self.core.pluginManager + pm.getPlugin = MethodType(getPlugin, pm, object) + + + def deactivate(self): + #restore state + pm = self.core.pluginManager + pm.getPlugin = pm.getPluginClass + diff --git a/module/plugins/addons/MultishareCz.py b/module/plugins/addons/MultishareCz.py new file mode 100644 index 000000000..a934f43ef --- /dev/null +++ b/module/plugins/addons/MultishareCz.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster +import re + +def getConfigSet(option): + s = set(option.lower().split('|')) + s.discard(u'') + return s + +class MultishareCz(MultiHoster): + __name__ = "MultishareCz" + __version__ = "0.01" + __type__ = "hook" + __config__ = [("activated", "bool", "Activated", "False"), + ("includeHoster", "str", "Use only for downloads from (bar-separated hosters)", ""), + ("excludeHoster", "str", "Do not use for downloads from (bar-separated hosters)", "rapidshare.com|uloz.to")] + __description__ = """MultiShare.cz hook plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + #replacements = [("freakshare.net", "freakshare.com")] + HOSTER_PATTERN = r']*alt="([^"]+)">\s*OK' + + def getHoster(self): + + page = getURL("http://www.multishare.cz/monitoring/") + hoster = set(m.group(1).lower() for m in re.finditer(self.HOSTER_PATTERN, page)) + + option = self.getConfig('includeHoster').strip() + if option: hoster &= getConfigSet(option) + option = self.getConfig('excludeHoster').strip() + if option: hoster -= getConfigSet(option) + + return list(hoster) \ No newline at end of file diff --git a/module/plugins/addons/Premium4Me.py b/module/plugins/addons/Premium4Me.py new file mode 100644 index 000000000..fc3ce2343 --- /dev/null +++ b/module/plugins/addons/Premium4Me.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class Premium4Me(MultiHoster): + __name__ = "Premium4Me" + __version__ = "0.02" + __type__ = "hook" + + __config__ = [("activated", "bool", "Activated", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for downloads from supported hosters:", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] + __description__ = """premium4.me hook plugin""" + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") + + replacements = [("freakshare.net", "freakshare.com")] + + def getHoster(self): + + page = getURL("http://premium4.me/api/hosters.php?authcode=%s" % self.account.authcode) + hosters = set([x.strip() for x in page.replace("\"", "").split(";")]) + + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace(',','|').split('|')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + elif configMode == "unlisted": + hosters -= configList + + return list(hosters) + + def coreReady(self): + + self.account = self.core.accountManager.getAccountPlugin("Premium4Me") + + user = self.account.selectAccount()[0] + + if not user: + self.logError(_("Please add your premium4.me account first and restart pyLoad")) + return + + return MultiHoster.coreReady(self) \ No newline at end of file diff --git a/module/plugins/addons/RehostTo.py b/module/plugins/addons/RehostTo.py new file mode 100644 index 000000000..b16987f5c --- /dev/null +++ b/module/plugins/addons/RehostTo.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class RehostTo(MultiHoster): + __name__ = "RehostTo" + __version__ = "0.41" + __type__ = "hook" + + __config__ = [("activated", "bool", "Activated", "False")] + + __description__ = """rehost.to hook plugin""" + __author_name__ = ("RaNaN") + __author_mail__ = ("RaNaN@pyload.org") + + replacements = [("freakshare.net", "freakshare.com")] + + def getHoster(self): + + page = getURL("http://rehost.to/api.php?cmd=get_supported_och_dl&long_ses=%s" % self.long_ses) + return [x.strip() for x in page.replace("\"", "").split(",")] + + + def coreReady(self): + + self.account = self.core.accountManager.getAccountPlugin("RehostTo") + + user = self.account.selectAccount()[0] + + if not user: + self.log.error("Rehost.to: "+ _("Please add your rehost.to account first and restart pyLoad")) + return + + data = self.account.getAccountInfo(user) + self.ses = data["ses"] + self.long_ses = data["long_ses"] + + return MultiHoster.coreReady(self) diff --git a/module/plugins/addons/UpdateManager.py b/module/plugins/addons/UpdateManager.py new file mode 100644 index 000000000..5bc6ac447 --- /dev/null +++ b/module/plugins/addons/UpdateManager.py @@ -0,0 +1,199 @@ +# -*- 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 . + + @author: RaNaN +""" + +import sys +import re +from os import stat +from os.path import join, exists +from time import time + +from module.plugins.PluginManager import IGNORE +from module.network.RequestFactory import getURL +from module.plugins.Addon import threaded, Expose, Addon + +class UpdateManager(Addon): + __name__ = "UpdateManager" + __version__ = "0.12" + __description__ = """checks for updates""" + __config__ = [("activated", "bool", "Activated", "True"), + ("interval", "int", "Check interval in minutes", "360"), + ("debug", "bool", "Check for plugin changes when in debug mode", False)] + __author_name__ = ("RaNaN") + __author_mail__ = ("ranan@pyload.org") + + @property + def debug(self): + return self.core.debug and self.getConfig("debug") + + + def setup(self): + if self.debug: + self.logDebug("Monitoring file changes") + self.interval = 4 + self.last_check = 0 #timestamp of updatecheck + self.old_periodical = self.periodical + self.periodical = self.checkChanges + self.mtimes = {} #recordes times + else: + self.interval = self.getConfig("interval") * 60 + + self.updated = False + self.reloaded = True + + self.info = {"pyload": False, "plugins": False} + + @threaded + def periodical(self): + + if self.core.version.endswith("-dev"): + self.logDebug("No update check performed on dev version.") + return + + update = self.checkForUpdate() + if update: + self.info["pyload"] = True + else: + self.log.info(_("No Updates for pyLoad")) + self.checkPlugins() + + if self.updated and not self.reloaded: + self.info["plugins"] = True + self.log.info(_("*** Plugins have been updated, please restart pyLoad ***")) + elif self.updated and self.reloaded: + self.log.info(_("Plugins updated and reloaded")) + self.updated = False + else: + self.log.info(_("No plugin updates available")) + + @Expose + def recheckForUpdates(self): + """recheck if updates are available""" + self.periodical() + + def checkForUpdate(self): + """checks if an update is available""" + + try: + version_check = getURL("http://get.pyload.org/check/%s/" % self.core.api.getServerVersion()) + if version_check == "": + return False + else: + self.log.info(_("*** New pyLoad Version %s available ***") % version_check) + self.log.info(_("*** Get it here: http://pyload.org/download ***")) + return True + except: + self.log.warning(_("Not able to connect server for updates")) + return False + + + def checkPlugins(self): + """ checks for plugins updates""" + + # plugins were already updated + if self.info["plugins"]: return + + try: + updates = getURL("http://get.pyload.org/plugins/check/") + except: + self.log.warning(_("Not able to connect server for updates")) + return False + + updates = updates.splitlines() + reloads = [] + + vre = re.compile(r'__version__.*=.*("|\')([0-9.]+)') + + for plugin in updates: + path, version = plugin.split(":") + prefix, filename = path.split("/") + + if filename.endswith(".pyc"): + name = filename[:filename.find("_")] + else: + name = filename.replace(".py", "") + + #TODO: obsolete + if prefix.endswith("s"): + type = prefix[:-1] + else: + type = prefix + + plugins = self.core.pluginManager.getPlugins(type) + + if name in plugins: + if float(plugins[name].version) >= float(version): + continue + + if name in IGNORE or (type, name) in IGNORE: + continue + + self.log.info(_("New version of %(type)s|%(name)s : %(version).2f") % { + "type": type, + "name": name, + "version": float(version) + }) + + try: + content = getURL("http://get.pyload.org/plugins/get/" + path) + except Exception, e: + self.logWarning(_("Error when updating %s") % filename, str(e)) + continue + + m = vre.search(content) + if not m or m.group(2) != version: + self.logWarning(_("Error when updating %s") % name, _("Version mismatch")) + continue + + f = open(join("userplugins", prefix, filename), "wb") + f.write(content) + f.close() + self.updated = True + + reloads.append((prefix, name)) + + self.reloaded = self.core.pluginManager.reloadPlugins(reloads) + + def checkChanges(self): + + if self.last_check + self.getConfig("interval") * 60 < time(): + self.old_periodical() + self.last_check = time() + + modules = filter( + lambda m: m and (m.__name__.startswith("module.plugins.") or m.__name__.startswith("userplugins.")) and m.__name__.count(".") >= 2, + sys.modules.itervalues()) + + reloads = [] + + for m in modules: + root, type, name = m.__name__.rsplit(".", 2) + id = (type, name) + if type in self.core.pluginManager.plugins: + f = m.__file__.replace(".pyc", ".py") + if not exists(f): continue + + mtime = stat(f).st_mtime + + if id not in self.mtimes: + self.mtimes[id] = mtime + elif self.mtimes[id] < mtime: + reloads.append(id) + self.mtimes[id] = mtime + + self.core.pluginManager.reloadPlugins(reloads) diff --git a/module/plugins/addons/XMPPInterface.py b/module/plugins/addons/XMPPInterface.py new file mode 100644 index 000000000..e8ef1d2ca --- /dev/null +++ b/module/plugins/addons/XMPPInterface.py @@ -0,0 +1,276 @@ +# -*- 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 . + + @author: RaNaN + @interface-version: 0.2 +""" + +from pyxmpp import streamtls +from pyxmpp.all import JID, Message, Presence +from pyxmpp.jabber.client import JabberClient +from pyxmpp.interface import implements +from pyxmpp.interfaces import * + +from module.plugins.addons.IRCInterface import IRCInterface + +class XMPPInterface(IRCInterface, JabberClient): + __name__ = "XMPPInterface" + __version__ = "0.1" + __description__ = """connect to jabber and let owner perform different tasks""" + __config__ = [("activated", "bool", "Activated", "False"), + ("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), + ("pw", "str", "Password", ""), + ("tls", "bool", "Use TLS", False), + ("owners", "str", "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), + ("info_file", "bool", "Inform about every file finished", "False"), + ("info_pack", "bool", "Inform about every package finished", "True"), + ("captcha", "bool", "Send captcha requests", "True")] + __author_name__ = ("RaNaN") + __author_mail__ = ("RaNaN@pyload.org") + + implements(IMessageHandlersProvider) + + def __init__(self, core, manager): + IRCInterface.__init__(self, core, manager) + + self.jid = JID(self.getConfig("jid")) + password = self.getConfig("pw") + + # if bare JID is provided add a resource -- it is required + if not self.jid.resource: + self.jid = JID(self.jid.node, self.jid.domain, "pyLoad") + + if self.getConfig("tls"): + tls_settings = streamtls.TLSSettings(require=True, verify_peer=False) + auth = ("sasl:PLAIN", "sasl:DIGEST-MD5") + else: + tls_settings = None + auth = ("sasl:DIGEST-MD5", "digest") + + # setup client with provided connection information + # and identity data + JabberClient.__init__(self, self.jid, password, + disco_name="pyLoad XMPP Client", disco_type="bot", + tls_settings=tls_settings, auth_methods=auth) + + self.interface_providers = [ + VersionHandler(self), + self, + ] + + def coreReady(self): + self.new_package = {} + + self.start() + + def packageFinished(self, pypack): + try: + if self.getConfig("info_pack"): + self.announce(_("Package finished: %s") % pypack.name) + except: + pass + + def downloadFinished(self, pyfile): + try: + if self.getConfig("info_file"): + self.announce( + _("Download finished: %(name)s @ %(plugin)s") % {"name": pyfile.name, "plugin": pyfile.pluginname}) + except: + pass + + def run(self): + # connect to IRC etc. + self.connect() + try: + self.loop() + except Exception, ex: + self.core.log.error("pyLoad XMPP: %s" % str(ex)) + + def stream_state_changed(self, state, arg): + """This one is called when the state of stream connecting the component + to a server changes. This will usually be used to let the user + know what is going on.""" + self.log.debug("pyLoad XMPP: *** State changed: %s %r ***" % (state, arg)) + + def disconnected(self): + self.log.debug("pyLoad XMPP: Client was disconnected") + + def stream_closed(self, stream): + self.log.debug("pyLoad XMPP: Stream was closed | %s" % stream) + + def stream_error(self, err): + self.log.debug("pyLoad XMPP: Stream Error: %s" % err) + + def get_message_handlers(self): + """Return list of (message_type, message_handler) tuples. + + The handlers returned will be called when matching message is received + in a client session.""" + return [ + ("normal", self.message), + ] + + def presence_control(self, stanza): + from_jid = unicode(stanza.get_from_jid()) + stanza_type = stanza.get_type() + self.log.debug("pyLoad XMPP: %s stanza from %s" % (stanza_type, + from_jid)) + + if from_jid in self.getConfig("owners"): + return stanza.make_accept_response() + + return stanza.make_deny_response() + + def session_started(self): + self.stream.send(Presence()) + + self.stream.set_presence_handler("subscribe", self.presence_control) + self.stream.set_presence_handler("subscribed", self.presence_control) + self.stream.set_presence_handler("unsubscribe", self.presence_control) + self.stream.set_presence_handler("unsubscribed", self.presence_control) + + def message(self, stanza): + """Message handler for the component.""" + subject = stanza.get_subject() + body = stanza.get_body() + t = stanza.get_type() + self.log.debug(u'pyLoad XMPP: Message from %s received.' % (unicode(stanza.get_from(), ))) + self.log.debug(u'pyLoad XMPP: Body: %s Subject: %s Type: %s' % (body, subject, t)) + + if t == "headline": + # 'headline' messages should never be replied to + return True + if subject: + subject = u"Re: " + subject + + to_jid = stanza.get_from() + from_jid = stanza.get_to() + + #j = JID() + to_name = to_jid.as_utf8() + from_name = from_jid.as_utf8() + + names = self.getConfig("owners").split(";") + + if to_name in names or to_jid.node + "@" + to_jid.domain in names: + messages = [] + + trigger = "pass" + args = None + + try: + temp = body.split() + trigger = temp[0] + if len(temp) > 1: + args = temp[1:] + except: + pass + + handler = getattr(self, "event_%s" % trigger, self.event_pass) + try: + res = handler(args) + for line in res: + m = Message( + to_jid=to_jid, + from_jid=from_jid, + stanza_type=stanza.get_type(), + subject=subject, + body=line) + + messages.append(m) + except Exception, e: + self.log.error("pyLoad XMPP: " + repr(e)) + + return messages + + else: + return True + + def response(self, msg, origin=""): + return self.announce(msg) + + def announce(self, message): + """ send message to all owners""" + for user in self.getConfig("owners").split(";"): + self.log.debug("pyLoad XMPP: Send message to %s" % user) + + to_jid = JID(user) + + m = Message(from_jid=self.jid, + to_jid=to_jid, + stanza_type="chat", + body=message) + + stream = self.get_stream() + if not stream: + self.connect() + stream = self.get_stream() + + stream.send(m) + + def beforeReconnecting(self, ip): + self.disconnect() + + def afterReconnecting(self, ip): + self.connect() + + +class VersionHandler(object): + """Provides handler for a version query. + + This class will answer version query and announce 'jabber:iq:version' namespace + in the client's disco#info results.""" + + implements(IIqHandlersProvider, IFeaturesProvider) + + def __init__(self, client): + """Just remember who created this.""" + self.client = client + + def get_features(self): + """Return namespace which should the client include in its reply to a + disco#info query.""" + return ["jabber:iq:version"] + + def get_iq_get_handlers(self): + """Return list of tuples (element_name, namespace, handler) describing + handlers of stanzas""" + return [ + ("query", "jabber:iq:version", self.get_version), + ] + + def get_iq_set_handlers(self): + """Return empty list, as this class provides no stanza handler.""" + return [] + + def get_version(self, iq): + """Handler for jabber:iq:version queries. + + jabber:iq:version queries are not supported directly by PyXMPP, so the + XML node is accessed directly through the libxml2 API. This should be + used very carefully!""" + iq = iq.make_result_response() + q = iq.new_query("jabber:iq:version") + q.newTextChild(q.ns(), "name", "Echo component") + q.newTextChild(q.ns(), "version", "1.0") + return iq + + def unload(self): + self.log.debug("pyLoad XMPP: unloading") + self.disconnect() + + def deactivate(self): + self.unload() diff --git a/module/plugins/addons/__init__.py b/module/plugins/addons/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/module/plugins/hooks/CaptchaTrader.py b/module/plugins/hooks/CaptchaTrader.py deleted file mode 100644 index 889eb83c0..000000000 --- a/module/plugins/hooks/CaptchaTrader.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- 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 . - - @author: mkaay, RaNaN -""" - -try: - from json import loads -except ImportError: - from simplejson import loads - -from thread import start_new_thread -from pycurl import FORM_FILE, LOW_SPEED_TIME - -from module.network.RequestFactory import getURL, getRequest -from module.network.HTTPRequest import BadHeader - -from module.plugins.Hook import Hook - -PYLOAD_KEY = "9f65e7f381c3af2b076ea680ae96b0b7" - -class CaptchaTraderException(Exception): - def __init__(self, err): - self.err = err - - def getCode(self): - return self.err - - def __str__(self): - return "" % self.err - - def __repr__(self): - return "" % self.err - -class CaptchaTrader(Hook): - __name__ = "CaptchaTrader" - __version__ = "0.13" - __description__ = """send captchas to captchatrader.com""" - __config__ = [("activated", "bool", "Activated", True), - ("username", "str", "Username", ""), - ("force", "bool", "Force CT even if client is connected", False), - ("passkey", "password", "Password", ""),] - __author_name__ = ("RaNaN") - __author_mail__ = ("RaNaN@pyload.org") - - SUBMIT_URL = "http://captchatrader.com/api/submit" - RESPOND_URL = "http://captchatrader.com/api/respond" - GETCREDITS_URL = "http://captchatrader.com/api/get_credits/username:%(user)s/password:%(password)s/" - - def setup(self): - self.info = {} - - def getCredits(self): - json = getURL(CaptchaTrader.GETCREDITS_URL % {"user": self.getConfig("username"), - "password": self.getConfig("passkey")}) - response = loads(json) - if response[0] < 0: - raise CaptchaTraderException(response[1]) - else: - self.logInfo(_("%s credits left") % response[1]) - self.info["credits"] = response[1] - return response[1] - - def submit(self, captcha, captchaType="file", match=None): - if not PYLOAD_KEY: - raise CaptchaTraderException("No API Key Specified!") - - #if type(captcha) == str and captchaType == "file": - # raise CaptchaTraderException("Invalid Type") - assert captchaType in ("file", "url-jpg", "url-jpeg", "url-png", "url-bmp") - - req = getRequest() - - #raise timeout threshold - req.c.setopt(LOW_SPEED_TIME, 80) - - try: - json = req.load(CaptchaTrader.SUBMIT_URL, post={"api_key": PYLOAD_KEY, - "username": self.getConfig("username"), - "password": self.getConfig("passkey"), - "value": (FORM_FILE, captcha), - "type": captchaType}, multipart=True) - finally: - req.close() - - response = loads(json) - if response[0] < 0: - raise CaptchaTraderException(response[1]) - - ticket = response[0] - result = response[1] - self.logDebug("result %s : %s" % (ticket,result)) - - return ticket, result - - def respond(self, ticket, success): - try: - json = getURL(CaptchaTrader.RESPOND_URL, post={"is_correct": 1 if success else 0, - "username": self.getConfig("username"), - "password": self.getConfig("passkey"), - "ticket": ticket}) - - response = loads(json) - if response[0] < 0: - raise CaptchaTraderException(response[1]) - - except BadHeader, e: - self.logError(_("Could not send response."), str(e)) - - def newCaptchaTask(self, task): - if not task.isTextual(): - return False - - if not self.getConfig("username") or not self.getConfig("passkey"): - return False - - if self.core.isClientConnected() and not self.getConfig("force"): - return False - - if self.getCredits() > 10: - task.handler.append(self) - task.setWaiting(100) - start_new_thread(self.processCaptcha, (task,)) - - else: - self.logInfo(_("Your CaptchaTrader Account has not enough credits")) - - def captchaCorrect(self, task): - if "ticket" in task.data: - ticket = task.data["ticket"] - self.respond(ticket, True) - - def captchaInvalid(self, task): - if "ticket" in task.data: - ticket = task.data["ticket"] - self.respond(ticket, False) - - def processCaptcha(self, task): - c = task.captchaFile - try: - ticket, result = self.submit(c) - except CaptchaTraderException, e: - task.error = e.getCode() - return - - task.data["ticket"] = ticket - task.setResult(result) diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py deleted file mode 100644 index fc32d0da8..000000000 --- a/module/plugins/hooks/ClickAndLoad.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- 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 . - - @author: RaNaN - @interface-version: 0.2 -""" - -import socket -import thread - -from module.plugins.Hook import Hook - -class ClickAndLoad(Hook): - __name__ = "ClickAndLoad" - __version__ = "0.2" - __description__ = """Gives abillity to use jd's click and load. depends on webinterface""" - __config__ = [("activated", "bool", "Activated", "True"), - ("extern", "bool", "Allow external link adding", "False")] - __author_name__ = ("RaNaN", "mkaay") - __author_mail__ = ("RaNaN@pyload.de", "mkaay@mkaay.de") - - def activate(self): - self.port = int(self.core.config['webinterface']['port']) - if self.core.config['webinterface']['activated']: - try: - if self.getConfig("extern"): - ip = "0.0.0.0" - else: - ip = "127.0.0.1" - - thread.start_new_thread(proxy, (self, ip, self.port, 9666)) - except: - self.log.error("ClickAndLoad port already in use.") - - -def proxy(self, *settings): - thread.start_new_thread(server, (self,) + settings) - lock = thread.allocate_lock() - lock.acquire() - lock.acquire() - - -def server(self, *settings): - try: - dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - dock_socket.bind((settings[0], settings[2])) - dock_socket.listen(5) - while True: - client_socket = dock_socket.accept()[0] - server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_socket.connect(("127.0.0.1", settings[1])) - thread.start_new_thread(forward, (client_socket, server_socket)) - thread.start_new_thread(forward, (server_socket, client_socket)) - except socket.error, e: - if hasattr(e, "errno"): - errno = e.errno - else: - errno = e.args[0] - - if errno == 98: - self.core.log.warning(_("Click'N'Load: Port 9666 already in use")) - return - thread.start_new_thread(server, (self,) + settings) - except: - thread.start_new_thread(server, (self,) + settings) - - -def forward(source, destination): - string = ' ' - while string: - string = source.recv(1024) - if string: - destination.sendall(string) - else: - #source.shutdown(socket.SHUT_RD) - destination.shutdown(socket.SHUT_WR) diff --git a/module/plugins/hooks/EasybytezCom.py b/module/plugins/hooks/EasybytezCom.py deleted file mode 100644 index 4dd39cca6..000000000 --- a/module/plugins/hooks/EasybytezCom.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.network.RequestFactory import getURL -from module.plugins.internal.MultiHoster import MultiHoster -import re - -def getConfigSet(option): - s = set(option.lower().replace(',','|').split('|')) - s.discard(u'') - return s - -class EasybytezCom(MultiHoster): - __name__ = "EasybytezCom" - __version__ = "0.01" - __type__ = "hook" - __config__ = [("activated", "bool", "Activated", "False"), - ("includeHoster", "str", "Use only for downloads from (comma-separated hosters)", ""), - ("excludeHoster", "str", "Do not use for downloads from (comma-separated hosters)", "")] - __description__ = """EasyBytez.com hook plugin""" - __author_name__ = ("zoidberg") - __author_mail__ = ("zoidberg@mujmail.cz") - - def getHoster(self): - - hoster = set(['2shared.com', 'easy-share.com', 'filefactory.com', 'fileserve.com', 'filesonic.com', 'hotfile.com', 'mediafire.com', 'megaupload.com', 'netload.in', 'rapidshare.com', 'uploading.com', 'wupload.com', 'oron.com', 'uploadstation.com', 'ul.to', 'uploaded.to']) - - option = self.getConfig('includeHoster').strip() - if option: hoster &= getConfigSet(option) - option = self.getConfig('excludeHoster').strip() - if option: hoster -= getConfigSet(option) - - return list(hoster) \ No newline at end of file diff --git a/module/plugins/hooks/Ev0InFetcher.py b/module/plugins/hooks/Ev0InFetcher.py deleted file mode 100644 index 0cd3f3226..000000000 --- a/module/plugins/hooks/Ev0InFetcher.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- 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 . - - @author: mkaay -""" -from module.lib import feedparser -from time import mktime, time - -from module.plugins.Hook import Hook - -class Ev0InFetcher(Hook): - __name__ = "Ev0InFetcher" - __version__ = "0.2" - __description__ = """checks rss feeds for ev0.in""" - __config__ = [("activated", "bool", "Activated", "False"), - ("interval", "int", "Check interval in minutes", "10"), - ("queue", "bool", "Move new shows directly to Queue", False), - ("shows", "str", "Shows to check for (comma seperated)", ""), - ("quality", "xvid;x264;rmvb", "Video Format", "xvid"), - ("hoster", "str", "Hoster to use (comma seperated)", "NetloadIn,RapidshareCom,MegauploadCom,HotfileCom")] - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") - - def setup(self): - self.interval = self.getConfig("interval") * 60 - - def filterLinks(self, links): - results = self.core.pluginManager.parseUrls(links) - sortedLinks = {} - - for url, hoster in results[0]: - if hoster not in sortedLinks: - sortedLinks[hoster] = [] - sortedLinks[hoster].append(url) - - for h in self.getConfig("hoster").split(","): - try: - return sortedLinks[h.strip()] - except: - continue - return [] - - def periodical(self): - def normalizefiletitle(filename): - filename = filename.replace('.', ' ') - filename = filename.replace('_', ' ') - filename = filename.lower() - return filename - - shows = [s.strip() for s in self.getConfig("shows").split(",")] - - feed = feedparser.parse("http://feeds.feedburner.com/ev0in/%s?format=xml" % self.getConfig("quality")) - - showStorage = {} - for show in shows: - showStorage[show] = int(self.getStorage("show_%s_lastfound" % show, 0)) - - found = False - for item in feed['items']: - for show, lastfound in showStorage.iteritems(): - if show.lower() in normalizefiletitle(item['title']) and lastfound < int(mktime(item.date_parsed)): - links = self.filterLinks(item['description'].split("
")) - packagename = item['title'].encode("utf-8") - self.core.log.info("Ev0InFetcher: new episode '%s' (matched '%s')" % (packagename, show)) - self.core.api.addPackage(packagename, links, 1 if self.getConfig("queue") else 0) - self.setStorage("show_%s_lastfound" % show, int(mktime(item.date_parsed))) - found = True - if not found: - #self.core.log.debug("Ev0InFetcher: no new episodes found") - pass - - for show, lastfound in self.getStorage().iteritems(): - if int(lastfound) > 0 and int(lastfound) + (3600*24*30) < int(time()): - self.delStorage("show_%s_lastfound" % show) - self.core.log.debug("Ev0InFetcher: cleaned '%s' record" % show) diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py deleted file mode 100644 index 39fe2b9f0..000000000 --- a/module/plugins/hooks/ExternalScripts.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- 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 . - - @author: RaNaN -""" - -import subprocess -from os import access, X_OK, makedirs -from os.path import basename - -from module.plugins.Hook import Hook -from module.utils.fs import save_join, exists, join, listdir - -class ExternalScripts(Hook): - __name__ = "ExternalScripts" - __version__ = "0.21" - __description__ = """Run external scripts""" - __config__ = [("activated", "bool", "Activated", "True")] - __author_name__ = ("mkaay", "RaNaN", "spoob") - __author_mail__ = ("mkaay@mkaay.de", "ranan@pyload.org", "spoob@pyload.org") - - event_list = ["unrarFinished", "allDownloadsFinished", "allDownloadsProcessed"] - - def setup(self): - self.scripts = {} - - folders = ['download_preparing', 'download_finished', 'package_finished', - 'before_reconnect', 'after_reconnect', 'unrar_finished', - 'all_dls_finished', 'all_dls_processed'] - - for folder in folders: - - self.scripts[folder] = [] - - self.initPluginType(folder, join(pypath, 'scripts', folder)) - self.initPluginType(folder, join('scripts', folder)) - - for script_type, names in self.scripts.iteritems(): - if names: - self.logInfo((_("Installed scripts for %s: ") % script_type ) + ", ".join([basename(x) for x in names])) - - - def initPluginType(self, folder, path): - if not exists(path): - try: - makedirs(path) - except : - self.logDebug("Script folder %s not created" % folder) - return - - for f in listdir(path): - if f.startswith("#") or f.startswith(".") or f.startswith("_") or f.endswith("~") or f.endswith(".swp"): - continue - - if not access(join(path,f), X_OK): - self.logWarning(_("Script not executable:") + " %s/%s" % (folder, f)) - - self.scripts[folder].append(join(path, f)) - - def callScript(self, script, *args): - try: - cmd = [script] + [str(x) if not isinstance(x, basestring) else x for x in args] - #output goes to pyload - subprocess.Popen(cmd, bufsize=-1) - except Exception, e: - self.logError(_("Error in %(script)s: %(error)s") % { "script" :basename(script), "error": str(e)}) - - def downloadPreparing(self, pyfile): - for script in self.scripts['download_preparing']: - self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.id) - - def downloadFinished(self, pyfile): - for script in self.scripts['download_finished']: - self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.name, pyfile.id, - save_join(self.core.config['general']['download_folder'], pyfile.package().folder, pyfile.name), - pyfile.id) - - - def packageFinished(self, pypack): - for script in self.scripts['package_finished']: - folder = self.core.config['general']['download_folder'] - folder = save_join(folder, pypack.folder) - - self.callScript(script, pypack.name, folder, pypack.id) - - def beforeReconnecting(self, ip): - for script in self.scripts['before_reconnect']: - self.callScript(script, ip) - - def afterReconnecting(self, ip): - for script in self.scripts['after_reconnect']: - self.callScript(script, ip) - - def unrarFinished(self, folder, fname): - for script in self.scripts["unrar_finished"]: - self.callScript(script, folder, fname) - - def allDownloadsFinished(self): - for script in self.scripts["all_dls_finished"]: - self.callScript(script) - - def allDownloadsProcessed(self): - for script in self.scripts["all_dls_processed"]: - self.callScript(script) - diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py deleted file mode 100644 index 12bd40d1b..000000000 --- a/module/plugins/hooks/ExtractArchive.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import sys -import os -from os.path import basename, isfile, isdir, join -from traceback import print_exc -from copy import copy - -# monkey patch bug in python 2.6 and lower -# see http://bugs.python.org/issue6122 -# http://bugs.python.org/issue1236 -# http://bugs.python.org/issue1731717 -if sys.version_info < (2, 7) and os.name != "nt": - from subprocess import Popen - import errno - - def _eintr_retry_call(func, *args): - while True: - try: - return func(*args) - except OSError, e: - if e.errno == errno.EINTR: - continue - raise - - # unsued timeout option for older python version - def wait(self, timeout=0): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - try: - pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) - except OSError, e: - if e.errno != errno.ECHILD: - raise - # This happens if SIGCLD is set to be ignored or waiting - # for child processes has otherwise been disabled for our - # process. This child is dead, we can't get the status. - sts = 0 - self._handle_exitstatus(sts) - return self.returncode - - Popen.wait = wait - -if os.name != "nt": - from os import chown - from pwd import getpwnam - from grp import getgrnam - -from module.utils.fs import save_join, fs_encode, exists, remove, chmod, makedirs -from module.plugins.Hook import Hook, threaded, Expose -from module.plugins.internal.AbstractExtractor import ArchiveError, CRCError, WrongPassword - -class ExtractArchive(Hook): - """ - Provides: unrarFinished (folder, filename) - """ - __name__ = "ExtractArchive" - __version__ = "0.12" - __description__ = "Extract different kind of archives" - __config__ = [("activated", "bool", "Activated", True), - ("fullpath", "bool", "Extract full path", True), - ("overwrite", "bool", "Overwrite files", True), - ("passwordfile", "file", "password file", "unrar_passwords.txt"), - ("deletearchive", "bool", "Delete archives when done", False), - ("subfolder", "bool", "Create subfolder for each package", False), - ("destination", "folder", "Extract files to", ""), - ("recursive", "bool", "Extract archives in archvies", True), - ("queue", "bool", "Wait for all downloads to be finished", True), - ("renice", "int", "CPU Priority", 0), ] - __author_name__ = ("pyload Team") - __author_mail__ = ("adminpyload.org") - - event_list = ["allDownloadsProcessed"] - - def setup(self): - self.plugins = [] - self.passwords = [] - names = [] - - for p in ("UnRar", "UnZip"): - try: - module = self.core.pluginManager.loadModule("internal", p) - klass = getattr(module, p) - if klass.checkDeps(): - names.append(p) - self.plugins.append(klass) - - except OSError, e: - if e.errno == 2: - self.logInfo(_("No %s installed") % p) - else: - self.logWarning(_("Could not activate %s") % p, str(e)) - if self.core.debug: - print_exc() - - except Exception, e: - self.logWarning(_("Could not activate %s") % p, str(e)) - if self.core.debug: - print_exc() - - if names: - self.logInfo(_("Activated") + " " + " ".join(names)) - else: - self.logInfo(_("No Extract plugins activated")) - - # queue with package ids - self.queue = [] - - @Expose - def extractPackage(self, id): - """ Extract package with given id""" - self.manager.startThread(self.extract, [id]) - - def packageFinished(self, pypack): - if self.getConfig("queue"): - self.logInfo(_("Package %s queued for later extracting") % pypack.name) - self.queue.append(pypack.id) - else: - self.manager.startThread(self.extract, [pypack.id]) - - - @threaded - def allDownloadsProcessed(self, thread): - local = copy(self.queue) - del self.queue[:] - self.extract(local, thread) - - - def extract(self, ids, thread=None): - # reload from txt file - self.reloadPasswords() - - # dl folder - dl = self.config['general']['download_folder'] - - extracted = [] - - #iterate packages -> plugins -> targets - for pid in ids: - p = self.core.files.getPackage(pid) - self.logInfo(_("Check package %s") % p.name) - if not p: continue - - # determine output folder - out = save_join(dl, p.folder, "") - # force trailing slash - - if self.getConfig("destination") and self.getConfig("destination").lower() != "none": - - out = save_join(dl, p.folder, self.getConfig("destination"), "") - #relative to package folder if destination is relative, otherwise absolute path overwrites them - - if self.getConf("subfolder"): - out = join(out, fs_encode(p.folder)) - - if not exists(out): - makedirs(out) - - files_ids = [(save_join(dl, p.folder, x["name"]), x["id"]) for x in p.getChildren().itervalues()] - matched = False - - # check as long there are unseen files - while files_ids: - new_files_ids = [] - - for plugin in self.plugins: - targets = plugin.getTargets(files_ids) - if targets: - self.logDebug("Targets for %s: %s" % (plugin.__name__, targets)) - matched = True - for target, fid in targets: - if target in extracted: - self.logDebug(basename(target), "skipped") - continue - extracted.append(target) #prevent extracting same file twice - - klass = plugin(self, target, out, self.getConfig("fullpath"), self.getConfig("overwrite"), - self.getConfig("renice")) - klass.init() - - self.logInfo(basename(target), _("Extract to %s") % out) - new_files = self.startExtracting(klass, fid, p.password.strip().splitlines(), thread) - self.logDebug("Extracted: %s" % new_files) - self.setPermissions(new_files) - - for file in new_files: - if not exists(file): - self.logDebug("new file %s does not exists" % file) - continue - if self.getConfig("recursive") and isfile(file): - new_files_ids.append((file, fid)) #append as new target - - files_ids = new_files_ids # also check extracted files - - if not matched: self.logInfo(_("No files found to extract")) - - - - def startExtracting(self, plugin, fid, passwords, thread): - pyfile = self.core.files.getFile(fid) - if not pyfile: return [] - - pyfile.setCustomStatus(_("extracting")) - thread.addActive(pyfile) #keep this file until everything is done - - try: - progress = lambda x: pyfile.setProgress(x) - success = False - - if not plugin.checkArchive(): - plugin.extract(progress) - success = True - else: - self.logInfo(basename(plugin.file), _("Password protected")) - self.logDebug("Passwords: %s" % str(passwords)) - - pwlist = copy(self.getPasswords()) - #remove already supplied pws from list (only local) - for pw in passwords: - if pw in pwlist: pwlist.remove(pw) - - for pw in passwords + pwlist: - try: - self.logDebug("Try password: %s" % pw) - if plugin.checkPassword(pw): - plugin.extract(progress, pw) - self.addPassword(pw) - success = True - break - except WrongPassword: - self.logDebug("Password was wrong") - - if not success: - self.logError(basename(plugin.file), _("Wrong password")) - return [] - - if self.core.debug: - self.logDebug("Would delete: %s" % ", ".join(plugin.getDeleteFiles())) - - if self.getConfig("deletearchive"): - files = plugin.getDeleteFiles() - self.logInfo(_("Deleting %s files") % len(files)) - for f in files: - if exists(f): remove(f) - else: self.logDebug("%s does not exists" % f) - - self.logInfo(basename(plugin.file), _("Extracting finished")) - self.manager.dispatchEvent("unrarFinished", plugin.out, plugin.file) - - return plugin.getExtractedFiles() - - - except ArchiveError, e: - self.logError(basename(plugin.file), _("Archive Error"), str(e)) - except CRCError: - self.logError(basename(plugin.file), _("CRC Mismatch")) - except Exception, e: - if self.core.debug: - print_exc() - self.logError(basename(plugin.file), _("Unknown Error"), str(e)) - - return [] - - @Expose - def getPasswords(self): - """ List of saved passwords """ - return self.passwords - - - def reloadPasswords(self): - pwfile = self.getConfig("passwordfile") - if not exists(pwfile): - open(pwfile, "wb").close() - - passwords = [] - f = open(pwfile, "rb") - for pw in f.read().splitlines(): - passwords.append(pw) - f.close() - - self.passwords = passwords - - - @Expose - def addPassword(self, pw): - """ Adds a password to saved list""" - pwfile = self.getConfig("passwordfile") - - if pw in self.passwords: self.passwords.remove(pw) - self.passwords.insert(0, pw) - - f = open(pwfile, "wb") - for pw in self.passwords: - f.write(pw + "\n") - f.close() - - def setPermissions(self, files): - for f in files: - if not exists(f): continue - try: - if self.core.config["permission"]["change_file"]: - if isfile(f): - chmod(f, int(self.core.config["permission"]["file"], 8)) - elif isdir(f): - chmod(f, int(self.core.config["permission"]["folder"], 8)) - - if self.core.config["permission"]["change_dl"] and os.name != "nt": - uid = getpwnam(self.config["permission"]["user"])[2] - gid = getgrnam(self.config["permission"]["group"])[2] - chown(f, uid, gid) - except Exception, e: - self.log.warning(_("Setting User and Group failed"), e) diff --git a/module/plugins/hooks/HotFolder.py b/module/plugins/hooks/HotFolder.py deleted file mode 100644 index ee1031ad5..000000000 --- a/module/plugins/hooks/HotFolder.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- 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 . - - @author: RaNaN - @interface-version: 0.2 -""" - -from os import makedirs -from os import listdir -from os.path import exists -from os.path import join -from os.path import isfile -from shutil import move -import time - -from module.plugins.Hook import Hook - -class HotFolder(Hook): - __name__ = "HotFolder" - __version__ = "0.1" - __description__ = """observe folder and file for changes and add container and links""" - __config__ = [ ("activated", "bool", "Activated" , "False"), - ("folder", "str", "Folder to observe", "container"), - ("watch_file", "bool", "Observe link file", "False"), - ("keep", "bool", "Keep added containers", "True"), - ("file", "str", "Link file", "links.txt")] - __threaded__ = [] - __author_name__ = ("RaNaN") - __author_mail__ = ("RaNaN@pyload.de") - - def setup(self): - self.interval = 10 - - def periodical(self): - - if not exists(join(self.getConfig("folder"), "finished")): - makedirs(join(self.getConfig("folder"), "finished")) - - if self.getConfig("watch_file"): - - if not exists(self.getConfig("file")): - f = open(self.getConfig("file"), "wb") - f.close() - - - f = open(self.getConfig("file"), "rb") - content = f.read().strip() - f.close() - f = open(self.getConfig("file"), "wb") - f.close() - if content: - name = "%s_%s.txt" % (self.getConfig("file"), time.strftime("%H-%M-%S_%d%b%Y") ) - - f = open(join(self.getConfig("folder"), "finished", name), "wb") - f.write(content) - f.close() - - self.core.api.addPackage(f.name, [f.name], 1) - - for f in listdir(self.getConfig("folder")): - path = join(self.getConfig("folder"), f) - - if not isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): - continue - - newpath = join(self.getConfig("folder"), "finished", f if self.getConfig("keep") else "tmp_"+f) - move(path, newpath) - - self.log.info(_("Added %s from HotFolder") % f) - self.core.api.addPackage(f, [newpath], 1) - - \ No newline at end of file diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py deleted file mode 100644 index e2737dc3a..000000000 --- a/module/plugins/hooks/IRCInterface.py +++ /dev/null @@ -1,425 +0,0 @@ -# -*- 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 . - - @author: RaNaN - @author: jeix - @interface-version: 0.2 -""" - -from select import select -import socket -from threading import Thread -import time -from time import sleep -from traceback import print_exc -import re - -from module.plugins.Hook import Hook -from module.network.RequestFactory import getURL -from module.utils import formatSize - -from pycurl import FORM_FILE - -class IRCInterface(Thread, Hook): - __name__ = "IRCInterface" - __version__ = "0.1" - __description__ = """connect to irc and let owner perform different tasks""" - __config__ = [("activated", "bool", "Activated", "False"), - ("host", "str", "IRC-Server Address", "Enter your server here!"), - ("port", "int", "IRC-Server Port", "6667"), - ("ident", "str", "Clients ident", "pyload-irc"), - ("realname", "str", "Realname", "pyload-irc"), - ("nick", "str", "Nickname the Client will take", "pyLoad-IRC"), - ("owner", "str", "Nickname the Client will accept commands from", "Enter your nick here!"), - ("info_file", "bool", "Inform about every file finished", "False"), - ("info_pack", "bool", "Inform about every package finished", "True"), - ("captcha", "bool", "Send captcha requests", "True")] - __author_name__ = ("Jeix") - __author_mail__ = ("Jeix@hasnomail.com") - - def __init__(self, core, manager): - Thread.__init__(self) - Hook.__init__(self, core, manager) - self.setDaemon(True) - # self.sm = core.server_methods - self.api = core.api #todo, only use api - - def coreReady(self): - self.new_package = {} - - self.abort = False - - self.links_added = 0 - self.more = [] - - self.start() - - - def packageFinished(self, pypack): - try: - if self.getConfig("info_pack"): - self.response(_("Package finished: %s") % pypack.name) - except: - pass - - def downloadFinished(self, pyfile): - try: - if self.getConfig("info_file"): - self.response(_("Download finished: %(name)s @ %(plugin)s ") % { "name" : pyfile.name, "plugin": pyfile.pluginname} ) - except: - pass - - def newCaptchaTask(self, task): - if self.getConfig("captcha") and task.isTextual(): - task.handler.append(self) - task.setWaiting(60) - - page = getURL("http://www.freeimagehosting.net/upload.php", post={"attached" : (FORM_FILE, task.captchaFile)}, multipart=True) - - url = re.search(r"\[img\]([^\[]+)\[/img\]\[/url\]", page).group(1) - self.response(_("New Captcha Request: %s") % url) - self.response(_("Answer with 'c %s text on the captcha'") % task.id) - - def run(self): - # connect to IRC etc. - self.sock = socket.socket() - host = self.getConfig("host") - self.sock.connect((host, self.getConfig("port"))) - nick = self.getConfig("nick") - self.sock.send("NICK %s\r\n" % nick) - self.sock.send("USER %s %s bla :%s\r\n" % (nick, host, nick)) - for t in self.getConfig("owner").split(): - if t.strip().startswith("#"): - self.sock.send("JOIN %s\r\n" % t.strip()) - self.log.info("pyLoad IRC: Connected to %s!" % host) - self.log.info("pyLoad IRC: Switching to listening mode!") - try: - self.main_loop() - - except IRCError, ex: - self.sock.send("QUIT :byebye\r\n") - print_exc() - self.sock.close() - - - def main_loop(self): - readbuffer = "" - while True: - sleep(1) - fdset = select([self.sock], [], [], 0) - if self.sock not in fdset[0]: - continue - - if self.abort: - raise IRCError("quit") - - readbuffer += self.sock.recv(1024) - temp = readbuffer.split("\n") - readbuffer = temp.pop() - - for line in temp: - line = line.rstrip() - first = line.split() - - if first[0] == "PING": - self.sock.send("PONG %s\r\n" % first[1]) - - if first[0] == "ERROR": - raise IRCError(line) - - msg = line.split(None, 3) - if len(msg) < 4: - continue - - msg = { - "origin":msg[0][1:], - "action":msg[1], - "target":msg[2], - "text":msg[3][1:] - } - - self.handle_events(msg) - - - def handle_events(self, msg): - if not msg["origin"].split("!", 1)[0] in self.getConfig("owner").split(): - return - - if msg["target"].split("!", 1)[0] != self.getConfig("nick"): - return - - if msg["action"] != "PRIVMSG": - return - - # HANDLE CTCP ANTI FLOOD/BOT PROTECTION - if msg["text"] == "\x01VERSION\x01": - self.log.debug("Sending CTCP VERSION.") - self.sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) - return - elif msg["text"] == "\x01TIME\x01": - self.log.debug("Sending CTCP TIME.") - self.sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) - return - elif msg["text"] == "\x01LAG\x01": - self.log.debug("Received CTCP LAG.") # don't know how to answer - return - - trigger = "pass" - args = None - - try: - temp = msg["text"].split() - trigger = temp[0] - if len(temp) > 1: - args = temp[1:] - except: - pass - - handler = getattr(self, "event_%s" % trigger, self.event_pass) - try: - res = handler(args) - for line in res: - self.response(line, msg["origin"]) - except Exception, e: - self.log.error("pyLoad IRC: "+ repr(e)) - - - def response(self, msg, origin=""): - if origin == "": - for t in self.getConfig("owner").split(): - self.sock.send("PRIVMSG %s :%s\r\n" % (t.strip(), msg)) - else: - self.sock.send("PRIVMSG %s :%s\r\n" % (origin.split("!", 1)[0], msg)) - - -#### Events - def event_pass(self, args): - return [] - - def event_status(self, args): - downloads = self.api.statusDownloads() - if not downloads: - return ["INFO: There are no active downloads currently."] - - temp_progress = "" - lines = ["ID - Name - Status - Speed - ETA - Progress"] - for data in downloads: - - if data.status == 5: - temp_progress = data.format_wait - else: - temp_progress = "%d%% (%s)" % (data.percent, data.format_size) - - lines.append("#%d - %s - %s - %s - %s - %s" % - ( - data.fid, - data.name, - data.statusmsg, - "%s/s" % formatSize(data.speed), - "%s" % data.format_eta, - temp_progress - ) - ) - return lines - - def event_queue(self, args): - ps = self.api.getQueue() - - if not ps: - return ["INFO: There are no packages in queue."] - - lines = [] - for pack in ps: - lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.fids) )) - - return lines - - def event_collector(self, args): - ps = self.api.getCollector() - if not ps: - return ["INFO: No packages in collector!"] - - lines = [] - for pack in ps: - lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.fids) )) - - return lines - - def event_info(self, args): - if not args: - return ['ERROR: Use info like this: info '] - - info = self.api.getFileData(int(args[0])) - - if not info: - return ["ERROR: Link doesn't exists."] - - return ['LINK #%s: %s (%s) [%s][%s]' % (info.fid, info.name, info.format_size, info.status_msg, - info.plugin)] - - def event_packinfo(self, args): - if not args: - return ['ERROR: Use packinfo like this: packinfo '] - - lines = [] - pack = self.api.getPackageData(int(args[0])) - - if not pack: - return ["ERROR: Package doesn't exists."] - - id = args[0] - - self.more = [] - - lines.append('PACKAGE #%s: "%s" with %d links' % (id, pack.name, len(pack.links)) ) - for pyfile in pack.links: - self.more.append('LINK #%s: %s (%s) [%s][%s]' % (pyfile.fid, pyfile.name, pyfile.format_size, - pyfile.statusmsg, pyfile.plugin)) - - if len(self.more) < 6: - lines.extend(self.more) - self.more = [] - else: - lines.extend(self.more[:6]) - self.more = self.more[6:] - lines.append("%d more links do display." % len(self.more)) - - - return lines - - def event_more(self, args): - if not self.more: - return ["No more information to display."] - - lines = self.more[:6] - self.more = self.more[6:] - lines.append("%d more links do display." % len(self.more)) - - return lines - - def event_start(self, args): - - self.api.unpauseServer() - return ["INFO: Starting downloads."] - - def event_stop(self, args): - - self.api.pauseServer() - return ["INFO: No new downloads will be started."] - - - def event_add(self, args): - if len(args) < 2: - return ['ERROR: Add links like this: "add links". ', - 'This will add the link to to the package / the package with id !'] - - - - pack = args[0].strip() - links = [x.strip() for x in args[1:]] - - count_added = 0 - count_failed = 0 - try: - id = int(pack) - pack = self.api.getPackageData(id) - if not pack: - return ["ERROR: Package doesn't exists."] - - #TODO add links - - return ["INFO: Added %d links to Package %s [#%d]" % (len(links), pack["name"], id)] - - except: - # create new package - id = self.api.addPackage(pack, links, 1) - return ["INFO: Created new Package %s [#%d] with %d links." % (pack, id, len(links))] - - - def event_del(self, args): - if len(args) < 2: - return ["ERROR: Use del command like this: del -p|-l [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] - - if args[0] == "-p": - ret = self.api.deletePackages(map(int, args[1:])) - return ["INFO: Deleted %d packages!" % len(args[1:])] - - elif args[0] == "-l": - ret = self.api.delLinks(map(int, args[1:])) - return ["INFO: Deleted %d links!" % len(args[1:])] - - else: - return ["ERROR: Use del command like this: del <-p|-l> [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] - - def event_push(self, args): - if not args: - return ["ERROR: Push package to queue like this: push "] - - id = int(args[0]) - if not self.api.getPackage_data(id): - return ["ERROR: Package #%d does not exist." % id] - - self.api.pushToQueue(id) - return ["INFO: Pushed package #%d to queue." % id] - - def event_pull(self, args): - if not args: - return ["ERROR: Pull package from queue like this: pull ."] - - id = int(args[0]) - if not self.api.getPackageData(id): - return ["ERROR: Package #%d does not exist." % id] - - self.api.pullFromQueue(id) - return ["INFO: Pulled package #%d from queue to collector." % id] - - def event_c(self, args): - """ captcha answer """ - if not args: - return ["ERROR: Captcha ID missing."] - - task = self.core.captchaManager.getTaskByID(args[0]) - if not task: - return ["ERROR: Captcha Task with ID %s does not exists." % args[0]] - - task.setResult(" ".join(args[1:])) - return ["INFO: Result %s saved." % " ".join(args[1:])] - - - def event_help(self, args): - lines = ["The following commands are available:", - "add [...] Adds link to package. (creates new package if it does not exist)", - "queue Shows all packages in the queue", - "collector Shows all packages in collector", - "del -p|-l [...] Deletes all packages|links with the ids specified", - "info Shows info of the link with id ", - "packinfo Shows info of the package with id ", - "more Shows more info when the result was truncated", - "start Starts all downloads", - "stop Stops the download (but not abort active downloads)", - "push Push package to queue", - "pull Pull package from queue", - "status Show general download status", - "help Shows this help message"] - return lines - - -class IRCError(Exception): - def __init__(self, value): - Exception.__init__(value) - self.value = value - def __str__(self): - return repr(self.value) diff --git a/module/plugins/hooks/MergeFiles.py b/module/plugins/hooks/MergeFiles.py deleted file mode 100644 index 02d343096..000000000 --- a/module/plugins/hooks/MergeFiles.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- 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 . - - @author: and9000 -""" - -import os -import re -import sys -import traceback - -from os.path import join -from module.utils import save_join, fs_encode -from module.plugins.Hook import Hook - -BUFFER_SIZE = 4096 - -class MergeFiles(Hook): - __name__ = "MergeFiles" - __version__ = "0.1" - __description__ = "Merges parts splitted with hjsplit" - __config__ = [ - ("activated" , "bool" , "Activated" , "False"), - ] - __threaded__ = ["packageFinished"] - __author_name__ = ("and9000") - __author_mail__ = ("me@has-no-mail.com") - - def setup(self): - # nothing to do - pass - - def packageFinished(self, pack): - files = {} - fid_dict = {} - for fid, data in pack.getChildren().iteritems(): - if re.search("\.[0-9]{3}$", data["name"]): - if data["name"][:-4] not in files: - files[data["name"][:-4]] = [] - files[data["name"][:-4]].append(data["name"]) - files[data["name"][:-4]].sort() - fid_dict[data["name"]] = fid - - download_folder = self.core.config['general']['download_folder'] - - if self.core.config['general']['folder_per_package']: - download_folder = save_join(download_folder, pack.folder) - - for name, file_list in files.iteritems(): - self.core.log.info("Starting merging of %s" % name) - final_file = open(join(download_folder, fs_encode(name)), "wb") - - for splitted_file in file_list: - self.core.log.debug("Merging part %s" % splitted_file) - pyfile = self.core.files.getFile(fid_dict[splitted_file]) - pyfile.setStatus("processing") - try: - s_file = open(os.path.join(download_folder, splitted_file), "rb") - size_written = 0 - s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file))) - while True: - f_buffer = s_file.read(BUFFER_SIZE) - if f_buffer: - final_file.write(f_buffer) - size_written += BUFFER_SIZE - pyfile.setProgress((size_written*100)/s_file_size) - else: - break - s_file.close() - self.core.log.debug("Finished merging part %s" % splitted_file) - except Exception, e: - print traceback.print_exc() - finally: - pyfile.setProgress(100) - pyfile.setStatus("finished") - pyfile.release() - - final_file.close() - self.core.log.info("Finished merging of %s" % name) - - diff --git a/module/plugins/hooks/MultiHome.py b/module/plugins/hooks/MultiHome.py deleted file mode 100644 index f15148538..000000000 --- a/module/plugins/hooks/MultiHome.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- 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 . - - @author: mkaay -""" - -from module.plugins.Hook import Hook -from time import time - -class MultiHome(Hook): - __name__ = "MultiHome" - __version__ = "0.1" - __description__ = """ip address changer""" - __config__ = [ ("activated", "bool", "Activated" , "False"), - ("interfaces", "str", "Interfaces" , "None") ] - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") - - def setup(self): - self.register = {} - self.interfaces = [] - self.parseInterfaces(self.getConfig("interfaces").split(";")) - if not self.interfaces: - self.parseInterfaces([self.config["download"]["interface"]]) - self.setConfig("interfaces", self.toConfig()) - - def toConfig(self): - return ";".join([i.adress for i in self.interfaces]) - - def parseInterfaces(self, interfaces): - for interface in interfaces: - if not interface or str(interface).lower() == "none": - continue - self.interfaces.append(Interface(interface)) - - def coreReady(self): - requestFactory = self.core.requestFactory - oldGetRequest = requestFactory.getRequest - def getRequest(pluginName, account=None): - iface = self.bestInterface(pluginName, account) - if iface: - iface.useFor(pluginName, account) - requestFactory.iface = lambda: iface.adress - self.log.debug("Multihome: using address: "+iface.adress) - return oldGetRequest(pluginName, account) - requestFactory.getRequest = getRequest - - def bestInterface(self, pluginName, account): - best = None - for interface in self.interfaces: - if not best or interface.lastPluginAccess(pluginName, account) < best.lastPluginAccess(pluginName, account): - best = interface - return best - -class Interface(object): - def __init__(self, adress): - self.adress = adress - self.history = {} - - def lastPluginAccess(self, pluginName, account): - if (pluginName, account) in self.history: - return self.history[(pluginName, account)] - return 0 - - def useFor(self, pluginName, account): - self.history[(pluginName, account)] = time() - - def __repr__(self): - return "" % self.adress diff --git a/module/plugins/hooks/MultiHoster.py b/module/plugins/hooks/MultiHoster.py deleted file mode 100644 index 2a567cce4..000000000 --- a/module/plugins/hooks/MultiHoster.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import re -from types import MethodType - -from module.plugins.MultiHoster import MultiHoster as MultiHosterAccount, normalize -from module.plugins.Hook import Hook, AddEventListener -from module.plugins.PluginManager import PluginTuple - -class MultiHoster(Hook): - __version__ = "0.1" - __internal__ = True - __description__ = "Gives ability to use MultiHoster services. You need to add your account first." - __config__ = [] - __author_mail__ = ("pyLoad Team",) - __author_mail__ = ("support@pyload.org",) - - #TODO: multiple accounts - multihoster / config options - - def init(self): - - # overwritten plugins - self.plugins = {} - - def addHoster(self, account): - - self.logDebug("New MultiHoster %s" % account.__name__) - - pluginMap = {} - for name in self.core.pluginManager.getPlugins("hoster").keys(): - pluginMap[name.lower()] = name - - supported = [] - new_supported = [] - - for hoster in account.getHosterList(): - name = normalize(hoster) - - if name in pluginMap: - supported.append(pluginMap[name]) - else: - new_supported.append(hoster) - - if not supported and not new_supported: - account.logError(_("No Hoster loaded")) - return - - klass = self.core.pluginManager.getPluginClass(account.__name__) - - # inject plugin plugin - account.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(supported))) - for hoster in supported: - self.plugins[hoster] = klass - - account.logDebug("New Hosters: %s" % ", ".join(sorted(new_supported))) - - # create new regexp - regexp = r".*(%s).*" % "|".join([klass.__pattern__] + [x.replace(".", "\\.") for x in new_supported]) - - # recreate plugin tuple for new regexp - hoster = self.core.pluginManager.getPlugins("hoster") - p = hoster[account.__name__] - new = PluginTuple(p.version, re.compile(regexp), p.deps, p.user, p.path) - hoster[account.__name__] = new - - - - @AddEventListener("accountDeleted") - def refreshAccounts(self, plugin=None, user=None): - - self.plugins = {} - - for name, account in self.core.accountManager.iterAccounts(): - if isinstance(account, MultiHosterAccount) and account.isUsable(): - self.addHoster(account) - - @AddEventListener("accountUpdated") - def refreshAccount(self, plugin, user): - - account = self.core.accountManager.getAccount(plugin, user) - if isinstance(account, MultiHosterAccount) and account.isUsable(): - self.addHoster(account) - - def activate(self): - self.refreshAccounts() - - # new method for plugin manager - def getPlugin(self2, name): - if name in self.plugins: - return self.plugins[name] - return self2.getPluginClass(name) - - pm = self.core.pluginManager - pm.getPlugin = MethodType(getPlugin, pm, object) - - - def deactivate(self): - #restore state - pm = self.core.pluginManager - pm.getPlugin = pm.getPluginClass - diff --git a/module/plugins/hooks/MultishareCz.py b/module/plugins/hooks/MultishareCz.py deleted file mode 100644 index a934f43ef..000000000 --- a/module/plugins/hooks/MultishareCz.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.network.RequestFactory import getURL -from module.plugins.internal.MultiHoster import MultiHoster -import re - -def getConfigSet(option): - s = set(option.lower().split('|')) - s.discard(u'') - return s - -class MultishareCz(MultiHoster): - __name__ = "MultishareCz" - __version__ = "0.01" - __type__ = "hook" - __config__ = [("activated", "bool", "Activated", "False"), - ("includeHoster", "str", "Use only for downloads from (bar-separated hosters)", ""), - ("excludeHoster", "str", "Do not use for downloads from (bar-separated hosters)", "rapidshare.com|uloz.to")] - __description__ = """MultiShare.cz hook plugin""" - __author_name__ = ("zoidberg") - __author_mail__ = ("zoidberg@mujmail.cz") - - #replacements = [("freakshare.net", "freakshare.com")] - HOSTER_PATTERN = r']*alt="([^"]+)">\s*OK' - - def getHoster(self): - - page = getURL("http://www.multishare.cz/monitoring/") - hoster = set(m.group(1).lower() for m in re.finditer(self.HOSTER_PATTERN, page)) - - option = self.getConfig('includeHoster').strip() - if option: hoster &= getConfigSet(option) - option = self.getConfig('excludeHoster').strip() - if option: hoster -= getConfigSet(option) - - return list(hoster) \ No newline at end of file diff --git a/module/plugins/hooks/Premium4Me.py b/module/plugins/hooks/Premium4Me.py deleted file mode 100644 index fc3ce2343..000000000 --- a/module/plugins/hooks/Premium4Me.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.network.RequestFactory import getURL -from module.plugins.internal.MultiHoster import MultiHoster - -class Premium4Me(MultiHoster): - __name__ = "Premium4Me" - __version__ = "0.02" - __type__ = "hook" - - __config__ = [("activated", "bool", "Activated", "False"), - ("hosterListMode", "all;listed;unlisted", "Use for downloads from supported hosters:", "all"), - ("hosterList", "str", "Hoster list (comma separated)", "")] - __description__ = """premium4.me hook plugin""" - __author_name__ = ("RaNaN", "zoidberg") - __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") - - replacements = [("freakshare.net", "freakshare.com")] - - def getHoster(self): - - page = getURL("http://premium4.me/api/hosters.php?authcode=%s" % self.account.authcode) - hosters = set([x.strip() for x in page.replace("\"", "").split(";")]) - - configMode = self.getConfig('hosterListMode') - if configMode in ("listed", "unlisted"): - configList = set(self.getConfig('hosterList').strip().lower().replace(',','|').split('|')) - configList.discard(u'') - if configMode == "listed": - hosters &= configList - elif configMode == "unlisted": - hosters -= configList - - return list(hosters) - - def coreReady(self): - - self.account = self.core.accountManager.getAccountPlugin("Premium4Me") - - user = self.account.selectAccount()[0] - - if not user: - self.logError(_("Please add your premium4.me account first and restart pyLoad")) - return - - return MultiHoster.coreReady(self) \ No newline at end of file diff --git a/module/plugins/hooks/RehostTo.py b/module/plugins/hooks/RehostTo.py deleted file mode 100644 index b16987f5c..000000000 --- a/module/plugins/hooks/RehostTo.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.network.RequestFactory import getURL -from module.plugins.internal.MultiHoster import MultiHoster - -class RehostTo(MultiHoster): - __name__ = "RehostTo" - __version__ = "0.41" - __type__ = "hook" - - __config__ = [("activated", "bool", "Activated", "False")] - - __description__ = """rehost.to hook plugin""" - __author_name__ = ("RaNaN") - __author_mail__ = ("RaNaN@pyload.org") - - replacements = [("freakshare.net", "freakshare.com")] - - def getHoster(self): - - page = getURL("http://rehost.to/api.php?cmd=get_supported_och_dl&long_ses=%s" % self.long_ses) - return [x.strip() for x in page.replace("\"", "").split(",")] - - - def coreReady(self): - - self.account = self.core.accountManager.getAccountPlugin("RehostTo") - - user = self.account.selectAccount()[0] - - if not user: - self.log.error("Rehost.to: "+ _("Please add your rehost.to account first and restart pyLoad")) - return - - data = self.account.getAccountInfo(user) - self.ses = data["ses"] - self.long_ses = data["long_ses"] - - return MultiHoster.coreReady(self) diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py deleted file mode 100644 index 230a6e858..000000000 --- a/module/plugins/hooks/UpdateManager.py +++ /dev/null @@ -1,199 +0,0 @@ -# -*- 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 . - - @author: RaNaN -""" - -import sys -import re -from os import stat -from os.path import join, exists -from time import time - -from module.plugins.PluginManager import IGNORE -from module.network.RequestFactory import getURL -from module.plugins.Hook import threaded, Expose, Hook - -class UpdateManager(Hook): - __name__ = "UpdateManager" - __version__ = "0.12" - __description__ = """checks for updates""" - __config__ = [("activated", "bool", "Activated", "True"), - ("interval", "int", "Check interval in minutes", "360"), - ("debug", "bool", "Check for plugin changes when in debug mode", False)] - __author_name__ = ("RaNaN") - __author_mail__ = ("ranan@pyload.org") - - @property - def debug(self): - return self.core.debug and self.getConfig("debug") - - - def setup(self): - if self.debug: - self.logDebug("Monitoring file changes") - self.interval = 4 - self.last_check = 0 #timestamp of updatecheck - self.old_periodical = self.periodical - self.periodical = self.checkChanges - self.mtimes = {} #recordes times - else: - self.interval = self.getConfig("interval") * 60 - - self.updated = False - self.reloaded = True - - self.info = {"pyload": False, "plugins": False} - - @threaded - def periodical(self): - - if self.core.version.endswith("-dev"): - self.logDebug("No update check performed on dev version.") - return - - update = self.checkForUpdate() - if update: - self.info["pyload"] = True - else: - self.log.info(_("No Updates for pyLoad")) - self.checkPlugins() - - if self.updated and not self.reloaded: - self.info["plugins"] = True - self.log.info(_("*** Plugins have been updated, please restart pyLoad ***")) - elif self.updated and self.reloaded: - self.log.info(_("Plugins updated and reloaded")) - self.updated = False - else: - self.log.info(_("No plugin updates available")) - - @Expose - def recheckForUpdates(self): - """recheck if updates are available""" - self.periodical() - - def checkForUpdate(self): - """checks if an update is available""" - - try: - version_check = getURL("http://get.pyload.org/check/%s/" % self.core.api.getServerVersion()) - if version_check == "": - return False - else: - self.log.info(_("*** New pyLoad Version %s available ***") % version_check) - self.log.info(_("*** Get it here: http://pyload.org/download ***")) - return True - except: - self.log.warning(_("Not able to connect server for updates")) - return False - - - def checkPlugins(self): - """ checks for plugins updates""" - - # plugins were already updated - if self.info["plugins"]: return - - try: - updates = getURL("http://get.pyload.org/plugins/check/") - except: - self.log.warning(_("Not able to connect server for updates")) - return False - - updates = updates.splitlines() - reloads = [] - - vre = re.compile(r'__version__.*=.*("|\')([0-9.]+)') - - for plugin in updates: - path, version = plugin.split(":") - prefix, filename = path.split("/") - - if filename.endswith(".pyc"): - name = filename[:filename.find("_")] - else: - name = filename.replace(".py", "") - - #TODO: obsolete - if prefix.endswith("s"): - type = prefix[:-1] - else: - type = prefix - - plugins = self.core.pluginManager.getPlugins(type) - - if name in plugins: - if float(plugins[name].version) >= float(version): - continue - - if name in IGNORE or (type, name) in IGNORE: - continue - - self.log.info(_("New version of %(type)s|%(name)s : %(version).2f") % { - "type": type, - "name": name, - "version": float(version) - }) - - try: - content = getURL("http://get.pyload.org/plugins/get/" + path) - except Exception, e: - self.logWarning(_("Error when updating %s") % filename, str(e)) - continue - - m = vre.search(content) - if not m or m.group(2) != version: - self.logWarning(_("Error when updating %s") % name, _("Version mismatch")) - continue - - f = open(join("userplugins", prefix, filename), "wb") - f.write(content) - f.close() - self.updated = True - - reloads.append((prefix, name)) - - self.reloaded = self.core.pluginManager.reloadPlugins(reloads) - - def checkChanges(self): - - if self.last_check + self.getConfig("interval") * 60 < time(): - self.old_periodical() - self.last_check = time() - - modules = filter( - lambda m: m and (m.__name__.startswith("module.plugins.") or m.__name__.startswith("userplugins.")) and m.__name__.count(".") >= 2, - sys.modules.itervalues()) - - reloads = [] - - for m in modules: - root, type, name = m.__name__.rsplit(".", 2) - id = (type, name) - if type in self.core.pluginManager.plugins: - f = m.__file__.replace(".pyc", ".py") - if not exists(f): continue - - mtime = stat(f).st_mtime - - if id not in self.mtimes: - self.mtimes[id] = mtime - elif self.mtimes[id] < mtime: - reloads.append(id) - self.mtimes[id] = mtime - - self.core.pluginManager.reloadPlugins(reloads) diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPPInterface.py deleted file mode 100644 index de87433cf..000000000 --- a/module/plugins/hooks/XMPPInterface.py +++ /dev/null @@ -1,276 +0,0 @@ -# -*- 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 . - - @author: RaNaN - @interface-version: 0.2 -""" - -from pyxmpp import streamtls -from pyxmpp.all import JID, Message, Presence -from pyxmpp.jabber.client import JabberClient -from pyxmpp.interface import implements -from pyxmpp.interfaces import * - -from module.plugins.hooks.IRCInterface import IRCInterface - -class XMPPInterface(IRCInterface, JabberClient): - __name__ = "XMPPInterface" - __version__ = "0.1" - __description__ = """connect to jabber and let owner perform different tasks""" - __config__ = [("activated", "bool", "Activated", "False"), - ("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), - ("pw", "str", "Password", ""), - ("tls", "bool", "Use TLS", False), - ("owners", "str", "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), - ("info_file", "bool", "Inform about every file finished", "False"), - ("info_pack", "bool", "Inform about every package finished", "True"), - ("captcha", "bool", "Send captcha requests", "True")] - __author_name__ = ("RaNaN") - __author_mail__ = ("RaNaN@pyload.org") - - implements(IMessageHandlersProvider) - - def __init__(self, core, manager): - IRCInterface.__init__(self, core, manager) - - self.jid = JID(self.getConfig("jid")) - password = self.getConfig("pw") - - # if bare JID is provided add a resource -- it is required - if not self.jid.resource: - self.jid = JID(self.jid.node, self.jid.domain, "pyLoad") - - if self.getConfig("tls"): - tls_settings = streamtls.TLSSettings(require=True, verify_peer=False) - auth = ("sasl:PLAIN", "sasl:DIGEST-MD5") - else: - tls_settings = None - auth = ("sasl:DIGEST-MD5", "digest") - - # setup client with provided connection information - # and identity data - JabberClient.__init__(self, self.jid, password, - disco_name="pyLoad XMPP Client", disco_type="bot", - tls_settings=tls_settings, auth_methods=auth) - - self.interface_providers = [ - VersionHandler(self), - self, - ] - - def coreReady(self): - self.new_package = {} - - self.start() - - def packageFinished(self, pypack): - try: - if self.getConfig("info_pack"): - self.announce(_("Package finished: %s") % pypack.name) - except: - pass - - def downloadFinished(self, pyfile): - try: - if self.getConfig("info_file"): - self.announce( - _("Download finished: %(name)s @ %(plugin)s") % {"name": pyfile.name, "plugin": pyfile.pluginname}) - except: - pass - - def run(self): - # connect to IRC etc. - self.connect() - try: - self.loop() - except Exception, ex: - self.core.log.error("pyLoad XMPP: %s" % str(ex)) - - def stream_state_changed(self, state, arg): - """This one is called when the state of stream connecting the component - to a server changes. This will usually be used to let the user - know what is going on.""" - self.log.debug("pyLoad XMPP: *** State changed: %s %r ***" % (state, arg)) - - def disconnected(self): - self.log.debug("pyLoad XMPP: Client was disconnected") - - def stream_closed(self, stream): - self.log.debug("pyLoad XMPP: Stream was closed | %s" % stream) - - def stream_error(self, err): - self.log.debug("pyLoad XMPP: Stream Error: %s" % err) - - def get_message_handlers(self): - """Return list of (message_type, message_handler) tuples. - - The handlers returned will be called when matching message is received - in a client session.""" - return [ - ("normal", self.message), - ] - - def presence_control(self, stanza): - from_jid = unicode(stanza.get_from_jid()) - stanza_type = stanza.get_type() - self.log.debug("pyLoad XMPP: %s stanza from %s" % (stanza_type, - from_jid)) - - if from_jid in self.getConfig("owners"): - return stanza.make_accept_response() - - return stanza.make_deny_response() - - def session_started(self): - self.stream.send(Presence()) - - self.stream.set_presence_handler("subscribe", self.presence_control) - self.stream.set_presence_handler("subscribed", self.presence_control) - self.stream.set_presence_handler("unsubscribe", self.presence_control) - self.stream.set_presence_handler("unsubscribed", self.presence_control) - - def message(self, stanza): - """Message handler for the component.""" - subject = stanza.get_subject() - body = stanza.get_body() - t = stanza.get_type() - self.log.debug(u'pyLoad XMPP: Message from %s received.' % (unicode(stanza.get_from(), ))) - self.log.debug(u'pyLoad XMPP: Body: %s Subject: %s Type: %s' % (body, subject, t)) - - if t == "headline": - # 'headline' messages should never be replied to - return True - if subject: - subject = u"Re: " + subject - - to_jid = stanza.get_from() - from_jid = stanza.get_to() - - #j = JID() - to_name = to_jid.as_utf8() - from_name = from_jid.as_utf8() - - names = self.getConfig("owners").split(";") - - if to_name in names or to_jid.node + "@" + to_jid.domain in names: - messages = [] - - trigger = "pass" - args = None - - try: - temp = body.split() - trigger = temp[0] - if len(temp) > 1: - args = temp[1:] - except: - pass - - handler = getattr(self, "event_%s" % trigger, self.event_pass) - try: - res = handler(args) - for line in res: - m = Message( - to_jid=to_jid, - from_jid=from_jid, - stanza_type=stanza.get_type(), - subject=subject, - body=line) - - messages.append(m) - except Exception, e: - self.log.error("pyLoad XMPP: " + repr(e)) - - return messages - - else: - return True - - def response(self, msg, origin=""): - return self.announce(msg) - - def announce(self, message): - """ send message to all owners""" - for user in self.getConfig("owners").split(";"): - self.log.debug("pyLoad XMPP: Send message to %s" % user) - - to_jid = JID(user) - - m = Message(from_jid=self.jid, - to_jid=to_jid, - stanza_type="chat", - body=message) - - stream = self.get_stream() - if not stream: - self.connect() - stream = self.get_stream() - - stream.send(m) - - def beforeReconnecting(self, ip): - self.disconnect() - - def afterReconnecting(self, ip): - self.connect() - - -class VersionHandler(object): - """Provides handler for a version query. - - This class will answer version query and announce 'jabber:iq:version' namespace - in the client's disco#info results.""" - - implements(IIqHandlersProvider, IFeaturesProvider) - - def __init__(self, client): - """Just remember who created this.""" - self.client = client - - def get_features(self): - """Return namespace which should the client include in its reply to a - disco#info query.""" - return ["jabber:iq:version"] - - def get_iq_get_handlers(self): - """Return list of tuples (element_name, namespace, handler) describing - handlers of stanzas""" - return [ - ("query", "jabber:iq:version", self.get_version), - ] - - def get_iq_set_handlers(self): - """Return empty list, as this class provides no stanza handler.""" - return [] - - def get_version(self, iq): - """Handler for jabber:iq:version queries. - - jabber:iq:version queries are not supported directly by PyXMPP, so the - XML node is accessed directly through the libxml2 API. This should be - used very carefully!""" - iq = iq.make_result_response() - q = iq.new_query("jabber:iq:version") - q.newTextChild(q.ns(), "name", "Echo component") - q.newTextChild(q.ns(), "version", "1.0") - return iq - - def unload(self): - self.log.debug("pyLoad XMPP: unloading") - self.disconnect() - - def deactivate(self): - self.unload() diff --git a/module/plugins/hooks/__init__.py b/module/plugins/hooks/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py index 2130f910e..ceb188193 100644 --- a/module/plugins/internal/AbstractExtractor.py +++ b/module/plugins/internal/AbstractExtractor.py @@ -30,7 +30,7 @@ class AbtractExtractor: def __init__(self, m, file, out, fullpath, overwrite, renice): """Initialize extractor for specific file - :param m: ExtractArchive Hook plugin + :param m: ExtractArchive Addon plugin :param file: Absolute filepath :param out: Absolute path to destination directory :param fullpath: extract to fullpath diff --git a/module/remote/socketbackend/ttypes.py b/module/remote/socketbackend/ttypes.py index 682b2b52a..91430d720 100644 --- a/module/remote/socketbackend/ttypes.py +++ b/module/remote/socketbackend/ttypes.py @@ -6,43 +6,61 @@ class BaseObject(object): __slots__ = [] -class Destination: - Collector = 0 - Queue = 1 - class DownloadStatus: - Aborted = 9 - Custom = 11 - Decrypting = 10 - Downloading = 12 - Failed = 8 - Finished = 0 + Aborted = 12 + Custom = 15 + Decrypting = 13 + Downloading = 10 + Failed = 7 + Finished = 5 + NA = 0 Offline = 1 Online = 2 - Processing = 13 + Paused = 4 + Processing = 14 Queued = 3 - Skipped = 4 - Starting = 7 - TempOffline = 6 - Unknown = 14 - Waiting = 5 + Skipped = 6 + Starting = 8 + TempOffline = 11 + Unknown = 16 + Waiting = 9 + +class FileStatus: + Missing = 1 + Ok = 0 + Remote = 2 class Input: - BOOL = 4 - CHOICE = 6 - CLICK = 5 - LIST = 8 - MULTIPLE = 7 - NONE = 0 - PASSWORD = 3 - TABLE = 9 - TEXT = 1 - TEXTBOX = 2 + Bool = 4 + Choice = 6 + Click = 5 + List = 8 + Multiple = 7 + NA = 0 + Password = 3 + Table = 9 + Text = 1 + TextBox = 2 + +class MediaType: + All = 0 + Archive = 32 + Audio = 2 + Document = 16 + Image = 4 + Other = 1 + Video = 8 class Output: - CAPTCHA = 1 - NOTIFICATION = 4 - QUESTION = 2 + All = 0 + Captcha = 2 + Notification = 1 + Query = 4 + +class PackageStatus: + Ok = 0 + Paused = 1 + Remote = 2 class AccountInfo(BaseObject): __slots__ = ['plugin', 'loginname', 'valid', 'validuntil', 'trafficleft', 'maxtraffic', 'premium', 'activated', 'options'] @@ -58,57 +76,56 @@ class AccountInfo(BaseObject): self.activated = activated self.options = options -class CaptchaTask(BaseObject): - __slots__ = ['tid', 'data', 'type', 'resultType'] +class AddonInfo(BaseObject): + __slots__ = ['func_name', 'description', 'value'] - def __init__(self, tid=None, data=None, type=None, resultType=None): - self.tid = tid - self.data = data - self.type = type - self.resultType = resultType + def __init__(self, func_name=None, description=None, value=None): + self.func_name = func_name + self.description = description + self.value = value + +class AddonService(BaseObject): + __slots__ = ['func_name', 'description', 'media', 'package'] + + def __init__(self, func_name=None, description=None, media=None, package=None): + self.func_name = func_name + self.description = description + self.media = media + self.package = package class ConfigItem(BaseObject): - __slots__ = ['name', 'long_name', 'description', 'type', 'default_value', 'value'] + __slots__ = ['name', 'display_name', 'description', 'type', 'default_value', 'value'] - def __init__(self, name=None, long_name=None, description=None, type=None, default_value=None, value=None): + def __init__(self, name=None, display_name=None, description=None, type=None, default_value=None, value=None): self.name = name - self.long_name = long_name + self.display_name = display_name self.description = description self.type = type self.default_value = default_value self.value = value class ConfigSection(BaseObject): - __slots__ = ['name', 'long_name', 'description', 'long_description', 'items', 'handler'] + __slots__ = ['name', 'display_name', 'description', 'long_description', 'items', 'info', 'handler'] - def __init__(self, name=None, long_name=None, description=None, long_description=None, items=None, handler=None): + def __init__(self, name=None, display_name=None, description=None, long_description=None, items=None, info=None, handler=None): self.name = name - self.long_name = long_name + self.display_name = display_name self.description = description self.long_description = long_description self.items = items + self.info = info self.handler = handler class DownloadInfo(BaseObject): - __slots__ = ['fid', 'name', 'speed', 'eta', 'format_eta', 'bleft', 'size', 'format_size', 'percent', 'status', 'statusmsg', 'format_wait', 'wait_until', 'packageID', 'packageName', 'plugin'] + __slots__ = ['url', 'plugin', 'hash', 'status', 'statusmsg', 'error'] - def __init__(self, fid=None, name=None, speed=None, eta=None, format_eta=None, bleft=None, size=None, format_size=None, percent=None, status=None, statusmsg=None, format_wait=None, wait_until=None, packageID=None, packageName=None, plugin=None): - self.fid = fid - self.name = name - self.speed = speed - self.eta = eta - self.format_eta = format_eta - self.bleft = bleft - self.size = size - self.format_size = format_size - self.percent = percent + def __init__(self, url=None, plugin=None, hash=None, status=None, statusmsg=None, error=None): + self.url = url + self.plugin = plugin + self.hash = hash self.status = status self.statusmsg = statusmsg - self.format_wait = format_wait - self.wait_until = wait_until - self.packageID = packageID - self.packageName = packageName - self.plugin = plugin + self.error = error class EventInfo(BaseObject): __slots__ = ['eventname', 'event_args'] @@ -117,42 +134,50 @@ class EventInfo(BaseObject): self.eventname = eventname self.event_args = event_args -class FileData(BaseObject): - __slots__ = ['fid', 'url', 'name', 'plugin', 'size', 'format_size', 'status', 'statusmsg', 'packageID', 'error', 'order'] - - def __init__(self, fid=None, url=None, name=None, plugin=None, size=None, format_size=None, status=None, statusmsg=None, packageID=None, error=None, order=None): - self.fid = fid - self.url = url - self.name = name - self.plugin = plugin - self.size = size - self.format_size = format_size - self.status = status - self.statusmsg = statusmsg - self.packageID = packageID - self.error = error - self.order = order - class FileDoesNotExists(Exception): __slots__ = ['fid'] def __init__(self, fid=None): self.fid = fid +class FileInfo(BaseObject): + __slots__ = ['fid', 'name', 'package', 'size', 'status', 'media', 'added', 'fileorder', 'download'] + + def __init__(self, fid=None, name=None, package=None, size=None, status=None, media=None, added=None, fileorder=None, download=None): + self.fid = fid + self.name = name + self.package = package + self.size = size + self.status = status + self.media = media + self.added = added + self.fileorder = fileorder + self.download = download + class InteractionTask(BaseObject): - __slots__ = ['iid', 'input', 'structure', 'preset', 'output', 'data', 'title', 'description', 'plugin'] + __slots__ = ['iid', 'input', 'data', 'output', 'default_value', 'title', 'description', 'plugin'] - def __init__(self, iid=None, input=None, structure=None, preset=None, output=None, data=None, title=None, description=None, plugin=None): + def __init__(self, iid=None, input=None, data=None, output=None, default_value=None, title=None, description=None, plugin=None): self.iid = iid self.input = input - self.structure = structure - self.preset = preset - self.output = output self.data = data + self.output = output + self.default_value = default_value self.title = title self.description = description self.plugin = plugin +class LinkStatus(BaseObject): + __slots__ = ['url', 'name', 'plugin', 'size', 'status', 'packagename'] + + def __init__(self, url=None, name=None, plugin=None, size=None, status=None, packagename=None): + self.url = url + self.name = name + self.plugin = plugin + self.size = size + self.status = status + self.packagename = packagename + class OnlineCheck(BaseObject): __slots__ = ['rid', 'data'] @@ -160,39 +185,67 @@ class OnlineCheck(BaseObject): self.rid = rid self.data = data -class OnlineStatus(BaseObject): - __slots__ = ['name', 'plugin', 'packagename', 'status', 'size'] +class PackageDoesNotExists(Exception): + __slots__ = ['pid'] - def __init__(self, name=None, plugin=None, packagename=None, status=None, size=None): - self.name = name - self.plugin = plugin - self.packagename = packagename - self.status = status - self.size = size + def __init__(self, pid=None): + self.pid = pid -class PackageData(BaseObject): - __slots__ = ['pid', 'name', 'folder', 'site', 'password', 'dest', 'order', 'linksdone', 'sizedone', 'sizetotal', 'linkstotal', 'links', 'fids'] +class PackageInfo(BaseObject): + __slots__ = ['pid', 'name', 'folder', 'root', 'site', 'comment', 'password', 'added', 'status', 'packageorder', 'stats', 'fids', 'pids'] - def __init__(self, pid=None, name=None, folder=None, site=None, password=None, dest=None, order=None, linksdone=None, sizedone=None, sizetotal=None, linkstotal=None, links=None, fids=None): + def __init__(self, pid=None, name=None, folder=None, root=None, site=None, comment=None, password=None, added=None, status=None, packageorder=None, stats=None, fids=None, pids=None): self.pid = pid self.name = name self.folder = folder + self.root = root self.site = site + self.comment = comment self.password = password - self.dest = dest - self.order = order + self.added = added + self.status = status + self.packageorder = packageorder + self.stats = stats + self.fids = fids + self.pids = pids + +class PackageStats(BaseObject): + __slots__ = ['linkstotal', 'linksdone', 'sizetotal', 'sizedone'] + + def __init__(self, linkstotal=None, linksdone=None, sizetotal=None, sizedone=None): + self.linkstotal = linkstotal self.linksdone = linksdone - self.sizedone = sizedone self.sizetotal = sizetotal - self.linkstotal = linkstotal - self.links = links - self.fids = fids + self.sizedone = sizedone -class PackageDoesNotExists(Exception): - __slots__ = ['pid'] +class PackageView(BaseObject): + __slots__ = ['root', 'files', 'packages'] - def __init__(self, pid=None): - self.pid = pid + def __init__(self, root=None, files=None, packages=None): + self.root = root + self.files = files + self.packages = packages + +class ProgressInfo(BaseObject): + __slots__ = ['fid', 'name', 'speed', 'eta', 'format_eta', 'bleft', 'size', 'format_size', 'percent', 'status', 'statusmsg', 'format_wait', 'wait_until', 'packageID', 'packageName', 'plugin'] + + def __init__(self, fid=None, name=None, speed=None, eta=None, format_eta=None, bleft=None, size=None, format_size=None, percent=None, status=None, statusmsg=None, format_wait=None, wait_until=None, packageID=None, packageName=None, plugin=None): + self.fid = fid + self.name = name + self.speed = speed + self.eta = eta + self.format_eta = format_eta + self.bleft = bleft + self.size = size + self.format_size = format_size + self.percent = percent + self.status = status + self.statusmsg = statusmsg + self.format_wait = format_wait + self.wait_until = wait_until + self.packageID = packageID + self.packageName = packageName + self.plugin = plugin class ServerStatus(BaseObject): __slots__ = ['pause', 'active', 'queue', 'total', 'speed', 'download', 'reconnect'] @@ -206,14 +259,6 @@ class ServerStatus(BaseObject): self.download = download self.reconnect = reconnect -class ServiceCall(BaseObject): - __slots__ = ['plugin', 'func', 'arguments'] - - def __init__(self, plugin=None, func=None, arguments=None): - self.plugin = plugin - self.func = func - self.arguments = arguments - class ServiceDoesNotExists(Exception): __slots__ = ['plugin', 'func'] @@ -244,11 +289,23 @@ class UserDoesNotExists(Exception): self.user = user class Iface: - def addFiles(self, pid, links): + def addFromCollector(self, name, paused): + pass + def addLinks(self, pid, links): + pass + def addPackage(self, name, links, password): + pass + def addPackageChild(self, name, links, password, root, paused): + pass + def addPackageP(self, name, links, password, paused): pass - def addPackage(self, name, links, dest, password): + def addToCollector(self, links): pass - def call(self, info): + def autoAddLinks(self, links): + pass + def call(self, plugin, func, arguments): + pass + def callAddonHandler(self, plugin, func, pid_or_fid): pass def checkOnlineStatus(self, urls): pass @@ -258,15 +315,23 @@ class Iface: pass def configureSection(self, section): pass - def deleteFiles(self, fids): + def createPackage(self, name, folder, root, password, site, comment, paused): + pass + def deleteCollLink(self, url): pass - def deleteFinished(self): + def deleteCollPack(self, name): + pass + def deleteFiles(self, fids): pass def deletePackages(self, pids): pass + def findFiles(self, pattern): + pass def freeSpace(self): pass - def generateAndAddPackages(self, links, dest): + def generateAndAddPackages(self, links, paused): + pass + def generateDownloadLink(self, fid, timeout): pass def generatePackages(self, links): pass @@ -274,17 +339,17 @@ class Iface: pass def getAccounts(self, refresh): pass - def getAllInfo(self): + def getAddonHandler(self): pass - def getAllUserData(self): + def getAllFiles(self): pass - def getCaptchaTask(self, exclusive): + def getAllInfo(self): pass - def getCaptchaTaskStatus(self, tid): + def getAllUnfinishedFiles(self): pass - def getCollector(self): + def getAllUserData(self): pass - def getCollectorData(self): + def getCollector(self): pass def getConfig(self): pass @@ -292,35 +357,35 @@ class Iface: pass def getEvents(self, uuid): pass - def getFileData(self, fid): + def getFileInfo(self, fid): pass - def getFileOrder(self, pid): + def getFileTree(self, pid, full): pass def getInfoByPlugin(self, plugin): pass + def getInteractionTask(self, mode): + pass def getLog(self, offset): pass - def getPackageData(self, pid): + def getPackageContent(self, pid): pass def getPackageInfo(self, pid): pass - def getPackageOrder(self, destination): - pass def getPluginConfig(self): pass - def getQueue(self): - pass - def getQueueData(self): + def getProgressInfo(self): pass def getServerVersion(self): pass def getServices(self): pass + def getUnfinishedFileTree(self, pid, full): + pass def getUserData(self, username, password): pass def hasService(self, plugin, func): pass - def isCaptchaWaiting(self): + def isInteractionWaiting(self, mode): pass def isTimeDownload(self): pass @@ -332,11 +397,11 @@ class Iface: pass def moveFiles(self, fids, pid): pass - def movePackage(self, destination, pid): + def movePackage(self, pid, root): pass - def orderFile(self, fid, position): + def orderFiles(self, fids, pid, position): pass - def orderPackage(self, pid, position): + def orderPackage(self, pids, position): pass def parseURLs(self, html, url): pass @@ -344,14 +409,12 @@ class Iface: pass def pollResults(self, rid): pass - def pullFromQueue(self, pid): - pass - def pushToQueue(self, pid): - pass def recheckPackage(self, pid): pass def removeAccount(self, plugin, account): pass + def renameCollPack(self, name, new_name): + pass def restart(self): pass def restartFailed(self): @@ -360,15 +423,21 @@ class Iface: pass def restartPackage(self, pid): pass - def setCaptchaResult(self, tid, result): + def scanDownloadFolder(self): + pass + def setConfigHandler(self, plugin, iid, value): pass def setConfigValue(self, section, option, value): pass + def setFilePaused(self, fid, paused): + pass + def setInteractionResult(self, iid, result): + pass def setPackageData(self, pid, data): pass - def setPackageName(self, pid, name): + def setPackageFolder(self, pid, path): pass - def statusDownloads(self): + def setPackagePaused(self, pid, paused): pass def statusServer(self): pass diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index a1b328958..bcf96324c 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -4,74 +4,96 @@ typedef i32 FileID typedef i32 PackageID typedef i32 ResultID typedef i32 InteractionID +typedef i64 UTCDate +typedef i64 ByteCount typedef list LinkList +// a string that can represent multiple types int, bool, time, etc.. +typedef string ValueString typedef string PluginName -typedef byte Progress -typedef byte Priority - +// NA - Not Available enum DownloadStatus { - Finished + NA, Offline, Online, Queued, + Paused, + Finished, Skipped, + Failed, + Starting, Waiting, + Downloading, TempOffline, - Starting, - Failed, Aborted, Decrypting, - Custom, - Downloading, Processing, + Custom, Unknown } -enum Destination { - Collector, - Queue +enum MediaType { + All = 0 + Other = 1, + Audio = 2, + Image = 4, + Video = 8, + Document = 16, + Archive = 32, +} + +enum FileStatus { + Ok, + Missing, + Remote, // file is available at remote location +} + +enum PackageStatus { + Ok, + Paused, + Remote, } // types for user interaction // some may only be place holder currently not supported // also all input - output combination are not reasonable, see InteractionManager for further info enum Input { - NONE, - TEXT, - TEXTBOX, - PASSWORD, - BOOL, // confirm like, yes or no dialog - CLICK, // for positional captchas - CHOICE, // choice from list - MULTIPLE, // multiple choice from list of elements - LIST, // arbitary list of elements - TABLE // table like data structure + NA, + Text, + TextBox, + Password, + Bool, // confirm like, yes or no dialog + Click, // for positional captchas + Choice, // choice from list + Multiple, // multiple choice from list of elements + List, // arbitary list of elements + Table // table like data structure } // more can be implemented by need // this describes the type of the outgoing interaction // ensure they can be logcial or'ed enum Output { - CAPTCHA = 1, - QUESTION = 2, - NOTIFICATION = 4, + All = 0, + Notification = 1, + Captcha = 2, + Query = 4, } -struct DownloadInfo { +struct ProgressInfo { 1: FileID fid, 2: string name, - 3: i64 speed, + 3: ByteCount speed, 4: i32 eta, 5: string format_eta, - 6: i64 bleft, - 7: i64 size, + 6: ByteCount bleft, + 7: ByteCount size, 8: string format_size, - 9: Progress percent, + 9: i16 percent, 10: DownloadStatus status, 11: string statusmsg, 12: string format_wait, - 13: i64 wait_until, + 13: UTCDate wait_until, 14: PackageID packageID, 15: string packageName, 16: PluginName plugin, @@ -82,76 +104,107 @@ struct ServerStatus { 2: i16 active, 3: i16 queue, 4: i16 total, - 5: i64 speed, + 5: ByteCount speed, 6: bool download, 7: bool reconnect } -struct FileData { +// download info for specific file +struct DownloadInfo { + 1: string url, + 2: PluginName plugin, + 3: string hash, + 4: DownloadStatus status, + 5: string statusmsg, + 6: string error, +} + +struct FileInfo { 1: FileID fid, - 2: string url, - 3: string name, - 4: PluginName plugin, - 5: i64 size, - 6: string format_size, - 7: DownloadStatus status, - 8: string statusmsg, - 9: PackageID packageID, - 10: string error, - 11: i16 order + 2: string name, + 3: PackageID package, + 4: ByteCount size, + 5: FileStatus status, + 6: MediaType media, + 7: UTCDate added, + 8: i16 fileorder, + 9: optional DownloadInfo download, } -struct PackageData { +struct PackageStats { + 1: i16 linkstotal, + 2: i16 linksdone, + 3: ByteCount sizetotal, + 4: ByteCount sizedone, +} + +struct PackageInfo { 1: PackageID pid, 2: string name, 3: string folder, - 4: string site, - 5: string password, - 6: Destination dest, - 7: i16 order, - 8: optional i16 linksdone, - 9: optional i64 sizedone, - 10: optional i64 sizetotal, - 11: optional i16 linkstotal, - 12: optional list links, - 13: optional list fids + 4: PackageID root, + 5: string site, + 6: string comment, + 7: string password, + 8: UTCDate added, + 9: PackageStatus status, + 10: i16 packageorder, + 11: PackageStats stats, + 12: list fids, + 13: list pids, +} + +// thrift does not allow recursive datatypes, so all data is accumulated and mapped with id +struct PackageView { + 1: PackageInfo root, + 2: map files, + 3: map packages +} + +// general info about link, used for collector and online results +struct LinkStatus { + 1: string url, + 2: string name, + 3: PluginName plugin, + 4: ByteCount size, // size <= 0 : unknown + 5: DownloadStatus status, + 6: string packagename, } struct InteractionTask { 1: InteractionID iid, 2: Input input, - 3: list structure, - 4: list preset, - 5: Output output, - 6: list data, - 7: string title, - 8: string description, - 9: string plugin, + 3: list data, + 4: Output output, + 5: optional ValueString default_value, + 6: string title, + 7: string description, + 8: PluginName plugin, +} + +struct AddonInfo { + 1: string func_name, + 2: string description, + 3: ValueString value, } struct ConfigItem { 1: string name, - 2: string long_name, + 2: string display_name, 3: string description, 4: string type, - 5: string default_value, - 6: string value, + 5: ValueString default_value, + 6: ValueString value, } struct ConfigSection { 1: string name, - 2: string long_name, + 2: string display_name, 3: string description, 4: string long_description, 5: optional list items, - 6: optional map handler, -} - -struct CaptchaTask { - 1: i16 tid, - 2: binary data, - 3: string type, - 4: string resultType + 6: optional list info, + 7: optional list handler, // if null plugin is not loaded } struct EventInfo { @@ -171,168 +224,239 @@ struct AccountInfo { 1: PluginName plugin, 2: string loginname, 3: bool valid, - 4: i64 validuntil, - 5: i64 trafficleft, - 6: i64 maxtraffic, + 4: UTCDate validuntil, + 5: ByteCount trafficleft, + 6: ByteCount maxtraffic, 7: bool premium, 8: bool activated, 9: map options, } -struct ServiceCall { - 1: PluginName plugin, - 2: string func, - 3: string arguments, // empty string or json encoded list -} - -struct OnlineStatus { - 1: string name, - 2: PluginName plugin, - 3: string packagename, - 4: DownloadStatus status, - 5: i64 size, // size <= 0 : unknown +struct AddonService { + 1: string func_name, + 2: string description, + 3: optional i16 media, + 4: optional bool package, } struct OnlineCheck { - 1: ResultID rid, // -1 -> nothing more to get - 2: map data, //url to result + 1: ResultID rid, // -1 -> nothing more to get + 2: map data, //url to result } // exceptions -exception PackageDoesNotExists{ +exception PackageDoesNotExists { 1: PackageID pid } -exception FileDoesNotExists{ +exception FileDoesNotExists { 1: FileID fid } -exception UserDoesNotExists{ +exception UserDoesNotExists { 1: string user } -exception ServiceDoesNotExists{ +exception ServiceDoesNotExists { 1: string plugin 2: string func } -exception ServiceException{ +exception ServiceException { 1: string msg } service Pyload { - //config - string getConfigValue(1: string section, 2: string option), - void setConfigValue(1: string section, 2: string option, 3: string value), - map getConfig(), - map getPluginConfig(), - ConfigSection configureSection(1: string section), + /////////////////////// + // Server Status + /////////////////////// - // server status + string getServerVersion(), + ServerStatus statusServer(), void pauseServer(), void unpauseServer(), bool togglePause(), - ServerStatus statusServer(), - i64 freeSpace(), - string getServerVersion(), + ByteCount freeSpace(), void kill(), void restart(), list getLog(1: i32 offset), bool isTimeDownload(), bool isTimeReconnect(), bool toggleReconnect(), + void scanDownloadFolder(), - // download preparing + // downloads - information + list getProgressInfo(), + + /////////////////////// + // Configuration + /////////////////////// + + string getConfigValue(1: string section, 2: string option), + void setConfigValue(1: string section, 2: string option, 3: string value), + map getConfig(), + map getPluginConfig(), + ConfigSection configureSection(1: string section), + void setConfigHandler(1: PluginName plugin, 2: InteractionID iid, 3: ValueString value), + + /////////////////////// + // Download Preparing + /////////////////////// - // packagename - urls - map generatePackages(1: LinkList links), map checkURLs(1: LinkList urls), map parseURLs(1: string html, 2: string url), + // packagename - urls // parses results and generates packages OnlineCheck checkOnlineStatus(1: LinkList urls), OnlineCheck checkOnlineStatusContainer(1: LinkList urls, 2: string filename, 3: binary data) - // poll results from previosly started online check + // poll results from previously started online check OnlineCheck pollResults(1: ResultID rid), - // downloads - information - list statusDownloads(), - PackageData getPackageData(1: PackageID pid) throws (1: PackageDoesNotExists e), - PackageData getPackageInfo(1: PackageID pid) throws (1: PackageDoesNotExists e), - FileData getFileData(1: FileID fid) throws (1: FileDoesNotExists e), - list getQueue(), - list getCollector(), - list getQueueData(), - list getCollectorData(), - map getPackageOrder(1: Destination destination), - map getFileOrder(1: PackageID pid) - - // downloads - adding/deleting - list generateAndAddPackages(1: LinkList links, 2: Destination dest), - PackageID addPackage(1: string name, 2: LinkList links, 3: Destination dest, 4: string password), + map generatePackages(1: LinkList links), + + /////////////////////// + // Adding/Deleting + /////////////////////// + + list generateAndAddPackages(1: LinkList links, 2: bool paused), + list autoAddLinks(1: LinkList links), + + PackageID createPackage(1: string name, 2: string folder, 3: PackageID root, 4: string password, + 5: string site, 6: string comment, 7: bool paused), + + PackageID addPackage(1: string name, 2: LinkList links, 3: string password), + // same as above with paused attribute + PackageID addPackageP(1: string name, 2: LinkList links, 3: string password, 4: bool paused), + + // pid -1 is toplevel + PackageID addPackageChild(1: string name, 2: LinkList links, 3: string password, 4: PackageID root, 5: bool paused), + PackageID uploadContainer(1: string filename, 2: binary data), - void addFiles(1: PackageID pid, 2: LinkList links), + + void addLinks(1: PackageID pid, 2: LinkList links) throws (1: PackageDoesNotExists e), + + // these are real file operations and WILL delete files on disk void deleteFiles(1: list fids), void deletePackages(1: list pids), - // downloads - modifying - void pushToQueue(1: PackageID pid), - void pullFromQueue(1: PackageID pid), + /////////////////////// + // Collector + /////////////////////// + + list getCollector(), + + void addToCollector(1: LinkList links), + PackageID addFromCollector(1: string name, 2: bool paused), + void renameCollPack(1: string name, 2: string new_name), + void deleteCollPack(1: string name), + void deleteCollLink(1: string url), + + //////////////////////////// + // File Information retrival + //////////////////////////// + + PackageView getAllFiles(), + PackageView getAllUnfinishedFiles(), + + // pid -1 for root, full=False only delivers first level in tree + PackageView getFileTree(1: PackageID pid, 2: bool full), + PackageView getUnfinishedFileTree(1: PackageID pid, 2: bool full), + + // same as above with full=False + PackageView getPackageContent(1: PackageID pid), + + PackageInfo getPackageInfo(1: PackageID pid) throws (1: PackageDoesNotExists e), + FileInfo getFileInfo(1: FileID fid) throws (1: FileDoesNotExists e), + map findFiles(1: string pattern), + + /////////////////////// + // Modify Downloads + /////////////////////// + void restartPackage(1: PackageID pid), void restartFile(1: FileID fid), void recheckPackage(1: PackageID pid), - void stopAllDownloads(), void stopDownloads(1: list fids), - void setPackageName(1: PackageID pid, 2: string name), - void movePackage(1: Destination destination, 2: PackageID pid), - void moveFiles(1: list fids, 2: PackageID pid), - void orderPackage(1: PackageID pid, 2: i16 position), - void orderFile(1: FileID fid, 2: i16 position), - void setPackageData(1: PackageID pid, 2: map data) throws (1: PackageDoesNotExists e), - list deleteFinished(), + void stopAllDownloads(), void restartFailed(), - //events - list getEvents(1: string uuid) + ///////////////////////// + // Modify Files/Packages + ///////////////////////// + + void setFilePaused(1: FileID fid, 2: bool paused) throws (1: FileDoesNotExists e), + + // moving package while downloading is not possible, so they will return bool to indicate success + void setPackagePaused(1: PackageID pid, 2: bool paused) throws (1: PackageDoesNotExists e), + bool setPackageFolder(1: PackageID pid, 2: string path) throws (1: PackageDoesNotExists e), + void setPackageData(1: PackageID pid, 2: map data) throws (1: PackageDoesNotExists e), + + // as above, this will move files on disk + bool movePackage(1: PackageID pid, 2: PackageID root) throws (1: PackageDoesNotExists e), + bool moveFiles(1: list fids, 2: PackageID pid) throws (1: PackageDoesNotExists e), + + void orderPackage(1: list pids, 2: i16 position), + void orderFiles(1: list fids, 2: PackageID pid, 3: i16 position), + + /////////////////////// + // User Interaction + /////////////////////// + + // mode = Output types binary ORed + bool isInteractionWaiting(1: i16 mode), + InteractionTask getInteractionTask(1: i16 mode), + void setInteractionResult(1: InteractionID iid, 2: ValueString result), + + // generate a download link, everybody can download the file until timeout reached + string generateDownloadLink(1: FileID fid, 2: i16 timeout), + + map> getAddonHandler(), + + void callAddonHandler(1: PluginName plugin, 2: string func, 3: PackageID pid_or_fid), + + /////////////////////// + // Event Handling + /////////////////////// + + list getEvents(1: string uuid), - //accounts + /////////////////////// + // Account Methods + /////////////////////// + list getAccounts(1: bool refresh), list getAccountTypes() void updateAccount(1: PluginName plugin, 2: string account, 3: string password, 4: map options), void removeAccount(1: PluginName plugin, 2: string account), - //auth + ///////////////////////// + // Auth+User Information + ///////////////////////// + bool login(1: string username, 2: string password), - UserData getUserData(1: string username, 2:string password) throws (1: UserDoesNotExists ex), + UserData getUserData(1: string username, 2: string password) throws (1: UserDoesNotExists ex), map getAllUserData(), - //services + /////////////////////// + // Addon Methods + /////////////////////// - // servicename : description - map> getServices(), + map> getServices(), bool hasService(1: PluginName plugin, 2: string func), - string call(1: ServiceCall info) throws (1: ServiceDoesNotExists ex, 2: ServiceException e), + // empty string or json encoded list as args + string call(1: PluginName plugin, 2: string func, 3: string arguments) throws (1: ServiceDoesNotExists ex, 2: ServiceException e), - //info - // {plugin: {name: value}} - map> getAllInfo(), - map getInfoByPlugin(1: PluginName plugin), + map> getAllInfo(), + list getInfoByPlugin(1: PluginName plugin), //scheduler // TODO - - // User interaction - - //captcha - bool isCaptchaWaiting(), - CaptchaTask getCaptchaTask(1: bool exclusive), - string getCaptchaTaskStatus(1: InteractionID tid), - void setCaptchaResult(1: InteractionID tid, 2: string result), } diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote index 6ee40092d..6f0c09182 100755 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote @@ -23,60 +23,76 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' print '' print 'Functions:' - print ' string getConfigValue(string section, string option)' - print ' void setConfigValue(string section, string option, string value)' - print ' getConfig()' - print ' getPluginConfig()' - print ' ConfigSection configureSection(string section)' + print ' string getServerVersion()' + print ' ServerStatus statusServer()' print ' void pauseServer()' print ' void unpauseServer()' print ' bool togglePause()' - print ' ServerStatus statusServer()' - print ' i64 freeSpace()' - print ' string getServerVersion()' + print ' ByteCount freeSpace()' print ' void kill()' print ' void restart()' print ' getLog(i32 offset)' print ' bool isTimeDownload()' print ' bool isTimeReconnect()' print ' bool toggleReconnect()' - print ' generatePackages(LinkList links)' + print ' void scanDownloadFolder()' + print ' getProgressInfo()' + print ' string getConfigValue(string section, string option)' + print ' void setConfigValue(string section, string option, string value)' + print ' getConfig()' + print ' getPluginConfig()' + print ' ConfigSection configureSection(string section)' + print ' void setConfigHandler(PluginName plugin, InteractionID iid, ValueString value)' print ' checkURLs(LinkList urls)' print ' parseURLs(string html, string url)' print ' OnlineCheck checkOnlineStatus(LinkList urls)' print ' OnlineCheck checkOnlineStatusContainer(LinkList urls, string filename, string data)' print ' OnlineCheck pollResults(ResultID rid)' - print ' statusDownloads()' - print ' PackageData getPackageData(PackageID pid)' - print ' PackageData getPackageInfo(PackageID pid)' - print ' FileData getFileData(FileID fid)' - print ' getQueue()' - print ' getCollector()' - print ' getQueueData()' - print ' getCollectorData()' - print ' getPackageOrder(Destination destination)' - print ' getFileOrder(PackageID pid)' - print ' generateAndAddPackages(LinkList links, Destination dest)' - print ' PackageID addPackage(string name, LinkList links, Destination dest, string password)' - print ' void addFiles(PackageID pid, LinkList links)' - print ' void uploadContainer(string filename, string data)' + print ' generatePackages(LinkList links)' + print ' generateAndAddPackages(LinkList links, bool paused)' + print ' autoAddLinks(LinkList links)' + print ' PackageID createPackage(string name, string folder, PackageID root, string password, string site, string comment, bool paused)' + print ' PackageID addPackage(string name, LinkList links, string password)' + print ' PackageID addPackageP(string name, LinkList links, string password, bool paused)' + print ' PackageID addPackageChild(string name, LinkList links, string password, PackageID root, bool paused)' + print ' PackageID uploadContainer(string filename, string data)' + print ' void addLinks(PackageID pid, LinkList links)' print ' void deleteFiles( fids)' print ' void deletePackages( pids)' - print ' void pushToQueue(PackageID pid)' - print ' void pullFromQueue(PackageID pid)' + print ' getCollector()' + print ' void addToCollector(LinkList links)' + print ' PackageID addFromCollector(string name, bool paused)' + print ' void renameCollPack(string name, string new_name)' + print ' void deleteCollPack(string name)' + print ' void deleteCollLink(string url)' + print ' PackageView getAllFiles()' + print ' PackageView getAllUnfinishedFiles()' + print ' PackageView getFileTree(PackageID pid, bool full)' + print ' PackageView getUnfinishedFileTree(PackageID pid, bool full)' + print ' PackageView getPackageContent(PackageID pid)' + print ' PackageInfo getPackageInfo(PackageID pid)' + print ' FileInfo getFileInfo(FileID fid)' + print ' findFiles(string pattern)' print ' void restartPackage(PackageID pid)' print ' void restartFile(FileID fid)' print ' void recheckPackage(PackageID pid)' - print ' void stopAllDownloads()' print ' void stopDownloads( fids)' - print ' void setPackageName(PackageID pid, string name)' - print ' void movePackage(Destination destination, PackageID pid)' - print ' void moveFiles( fids, PackageID pid)' - print ' void orderPackage(PackageID pid, i16 position)' - print ' void orderFile(FileID fid, i16 position)' - print ' void setPackageData(PackageID pid, data)' - print ' deleteFinished()' + print ' void stopAllDownloads()' print ' void restartFailed()' + print ' void setFilePaused(FileID fid, bool paused)' + print ' void setPackagePaused(PackageID pid, bool paused)' + print ' bool setPackageFolder(PackageID pid, string path)' + print ' void setPackageData(PackageID pid, data)' + print ' bool movePackage(PackageID pid, PackageID root)' + print ' bool moveFiles( fids, PackageID pid)' + print ' void orderPackage( pids, i16 position)' + print ' void orderFiles( fids, PackageID pid, i16 position)' + print ' bool isInteractionWaiting(i16 mode)' + print ' InteractionTask getInteractionTask(i16 mode)' + print ' void setInteractionResult(InteractionID iid, ValueString result)' + print ' string generateDownloadLink(FileID fid, i16 timeout)' + print ' getAddonHandler()' + print ' void callAddonHandler(PluginName plugin, string func, PackageID pid_or_fid)' print ' getEvents(string uuid)' print ' getAccounts(bool refresh)' print ' getAccountTypes()' @@ -87,13 +103,9 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help': print ' getAllUserData()' print ' getServices()' print ' bool hasService(PluginName plugin, string func)' - print ' string call(ServiceCall info)' + print ' string call(PluginName plugin, string func, string arguments)' print ' getAllInfo()' print ' getInfoByPlugin(PluginName plugin)' - print ' bool isCaptchaWaiting()' - print ' CaptchaTask getCaptchaTask(bool exclusive)' - print ' string getCaptchaTaskStatus(TaskID tid)' - print ' void setCaptchaResult(TaskID tid, string result)' print '' sys.exit(0) @@ -145,35 +157,17 @@ protocol = TBinaryProtocol.TBinaryProtocol(transport) client = Pyload.Client(protocol) transport.open() -if cmd == 'getConfigValue': - if len(args) != 2: - print 'getConfigValue requires 2 args' - sys.exit(1) - pp.pprint(client.getConfigValue(args[0],args[1],)) - -elif cmd == 'setConfigValue': - if len(args) != 3: - print 'setConfigValue requires 3 args' - sys.exit(1) - pp.pprint(client.setConfigValue(args[0],args[1],args[2],)) - -elif cmd == 'getConfig': +if cmd == 'getServerVersion': if len(args) != 0: - print 'getConfig requires 0 args' + print 'getServerVersion requires 0 args' sys.exit(1) - pp.pprint(client.getConfig()) + pp.pprint(client.getServerVersion()) -elif cmd == 'getPluginConfig': +elif cmd == 'statusServer': if len(args) != 0: - print 'getPluginConfig requires 0 args' - sys.exit(1) - pp.pprint(client.getPluginConfig()) - -elif cmd == 'configureSection': - if len(args) != 1: - print 'configureSection requires 1 args' + print 'statusServer requires 0 args' sys.exit(1) - pp.pprint(client.configureSection(args[0],)) + pp.pprint(client.statusServer()) elif cmd == 'pauseServer': if len(args) != 0: @@ -193,24 +187,12 @@ elif cmd == 'togglePause': sys.exit(1) pp.pprint(client.togglePause()) -elif cmd == 'statusServer': - if len(args) != 0: - print 'statusServer requires 0 args' - sys.exit(1) - pp.pprint(client.statusServer()) - elif cmd == 'freeSpace': if len(args) != 0: print 'freeSpace requires 0 args' sys.exit(1) pp.pprint(client.freeSpace()) -elif cmd == 'getServerVersion': - if len(args) != 0: - print 'getServerVersion requires 0 args' - sys.exit(1) - pp.pprint(client.getServerVersion()) - elif cmd == 'kill': if len(args) != 0: print 'kill requires 0 args' @@ -247,11 +229,53 @@ elif cmd == 'toggleReconnect': sys.exit(1) pp.pprint(client.toggleReconnect()) -elif cmd == 'generatePackages': +elif cmd == 'scanDownloadFolder': + if len(args) != 0: + print 'scanDownloadFolder requires 0 args' + sys.exit(1) + pp.pprint(client.scanDownloadFolder()) + +elif cmd == 'getProgressInfo': + if len(args) != 0: + print 'getProgressInfo requires 0 args' + sys.exit(1) + pp.pprint(client.getProgressInfo()) + +elif cmd == 'getConfigValue': + if len(args) != 2: + print 'getConfigValue requires 2 args' + sys.exit(1) + pp.pprint(client.getConfigValue(args[0],args[1],)) + +elif cmd == 'setConfigValue': + if len(args) != 3: + print 'setConfigValue requires 3 args' + sys.exit(1) + pp.pprint(client.setConfigValue(args[0],args[1],args[2],)) + +elif cmd == 'getConfig': + if len(args) != 0: + print 'getConfig requires 0 args' + sys.exit(1) + pp.pprint(client.getConfig()) + +elif cmd == 'getPluginConfig': + if len(args) != 0: + print 'getPluginConfig requires 0 args' + sys.exit(1) + pp.pprint(client.getPluginConfig()) + +elif cmd == 'configureSection': if len(args) != 1: - print 'generatePackages requires 1 args' + print 'configureSection requires 1 args' sys.exit(1) - pp.pprint(client.generatePackages(eval(args[0]),)) + pp.pprint(client.configureSection(args[0],)) + +elif cmd == 'setConfigHandler': + if len(args) != 3: + print 'setConfigHandler requires 3 args' + sys.exit(1) + pp.pprint(client.setConfigHandler(eval(args[0]),eval(args[1]),eval(args[2]),)) elif cmd == 'checkURLs': if len(args) != 1: @@ -283,35 +307,71 @@ elif cmd == 'pollResults': sys.exit(1) pp.pprint(client.pollResults(eval(args[0]),)) -elif cmd == 'statusDownloads': - if len(args) != 0: - print 'statusDownloads requires 0 args' +elif cmd == 'generatePackages': + if len(args) != 1: + print 'generatePackages requires 1 args' sys.exit(1) - pp.pprint(client.statusDownloads()) + pp.pprint(client.generatePackages(eval(args[0]),)) -elif cmd == 'getPackageData': - if len(args) != 1: - print 'getPackageData requires 1 args' +elif cmd == 'generateAndAddPackages': + if len(args) != 2: + print 'generateAndAddPackages requires 2 args' sys.exit(1) - pp.pprint(client.getPackageData(eval(args[0]),)) + pp.pprint(client.generateAndAddPackages(eval(args[0]),eval(args[1]),)) -elif cmd == 'getPackageInfo': +elif cmd == 'autoAddLinks': if len(args) != 1: - print 'getPackageInfo requires 1 args' + print 'autoAddLinks requires 1 args' sys.exit(1) - pp.pprint(client.getPackageInfo(eval(args[0]),)) + pp.pprint(client.autoAddLinks(eval(args[0]),)) -elif cmd == 'getFileData': +elif cmd == 'createPackage': + if len(args) != 7: + print 'createPackage requires 7 args' + sys.exit(1) + pp.pprint(client.createPackage(args[0],args[1],eval(args[2]),args[3],args[4],args[5],eval(args[6]),)) + +elif cmd == 'addPackage': + if len(args) != 3: + print 'addPackage requires 3 args' + sys.exit(1) + pp.pprint(client.addPackage(args[0],eval(args[1]),args[2],)) + +elif cmd == 'addPackageP': + if len(args) != 4: + print 'addPackageP requires 4 args' + sys.exit(1) + pp.pprint(client.addPackageP(args[0],eval(args[1]),args[2],eval(args[3]),)) + +elif cmd == 'addPackageChild': + if len(args) != 5: + print 'addPackageChild requires 5 args' + sys.exit(1) + pp.pprint(client.addPackageChild(args[0],eval(args[1]),args[2],eval(args[3]),eval(args[4]),)) + +elif cmd == 'uploadContainer': + if len(args) != 2: + print 'uploadContainer requires 2 args' + sys.exit(1) + pp.pprint(client.uploadContainer(args[0],args[1],)) + +elif cmd == 'addLinks': + if len(args) != 2: + print 'addLinks requires 2 args' + sys.exit(1) + pp.pprint(client.addLinks(eval(args[0]),eval(args[1]),)) + +elif cmd == 'deleteFiles': if len(args) != 1: - print 'getFileData requires 1 args' + print 'deleteFiles requires 1 args' sys.exit(1) - pp.pprint(client.getFileData(eval(args[0]),)) + pp.pprint(client.deleteFiles(eval(args[0]),)) -elif cmd == 'getQueue': - if len(args) != 0: - print 'getQueue requires 0 args' +elif cmd == 'deletePackages': + if len(args) != 1: + print 'deletePackages requires 1 args' sys.exit(1) - pp.pprint(client.getQueue()) + pp.pprint(client.deletePackages(eval(args[0]),)) elif cmd == 'getCollector': if len(args) != 0: @@ -319,77 +379,83 @@ elif cmd == 'getCollector': sys.exit(1) pp.pprint(client.getCollector()) -elif cmd == 'getQueueData': - if len(args) != 0: - print 'getQueueData requires 0 args' +elif cmd == 'addToCollector': + if len(args) != 1: + print 'addToCollector requires 1 args' sys.exit(1) - pp.pprint(client.getQueueData()) + pp.pprint(client.addToCollector(eval(args[0]),)) -elif cmd == 'getCollectorData': - if len(args) != 0: - print 'getCollectorData requires 0 args' +elif cmd == 'addFromCollector': + if len(args) != 2: + print 'addFromCollector requires 2 args' + sys.exit(1) + pp.pprint(client.addFromCollector(args[0],eval(args[1]),)) + +elif cmd == 'renameCollPack': + if len(args) != 2: + print 'renameCollPack requires 2 args' sys.exit(1) - pp.pprint(client.getCollectorData()) + pp.pprint(client.renameCollPack(args[0],args[1],)) -elif cmd == 'getPackageOrder': +elif cmd == 'deleteCollPack': if len(args) != 1: - print 'getPackageOrder requires 1 args' + print 'deleteCollPack requires 1 args' sys.exit(1) - pp.pprint(client.getPackageOrder(eval(args[0]),)) + pp.pprint(client.deleteCollPack(args[0],)) -elif cmd == 'getFileOrder': +elif cmd == 'deleteCollLink': if len(args) != 1: - print 'getFileOrder requires 1 args' + print 'deleteCollLink requires 1 args' sys.exit(1) - pp.pprint(client.getFileOrder(eval(args[0]),)) + pp.pprint(client.deleteCollLink(args[0],)) -elif cmd == 'generateAndAddPackages': - if len(args) != 2: - print 'generateAndAddPackages requires 2 args' +elif cmd == 'getAllFiles': + if len(args) != 0: + print 'getAllFiles requires 0 args' sys.exit(1) - pp.pprint(client.generateAndAddPackages(eval(args[0]),eval(args[1]),)) + pp.pprint(client.getAllFiles()) -elif cmd == 'addPackage': - if len(args) != 4: - print 'addPackage requires 4 args' +elif cmd == 'getAllUnfinishedFiles': + if len(args) != 0: + print 'getAllUnfinishedFiles requires 0 args' sys.exit(1) - pp.pprint(client.addPackage(args[0],eval(args[1]),eval(args[2]),args[3],)) + pp.pprint(client.getAllUnfinishedFiles()) -elif cmd == 'addFiles': +elif cmd == 'getFileTree': if len(args) != 2: - print 'addFiles requires 2 args' + print 'getFileTree requires 2 args' sys.exit(1) - pp.pprint(client.addFiles(eval(args[0]),eval(args[1]),)) + pp.pprint(client.getFileTree(eval(args[0]),eval(args[1]),)) -elif cmd == 'uploadContainer': +elif cmd == 'getUnfinishedFileTree': if len(args) != 2: - print 'uploadContainer requires 2 args' + print 'getUnfinishedFileTree requires 2 args' sys.exit(1) - pp.pprint(client.uploadContainer(args[0],args[1],)) + pp.pprint(client.getUnfinishedFileTree(eval(args[0]),eval(args[1]),)) -elif cmd == 'deleteFiles': +elif cmd == 'getPackageContent': if len(args) != 1: - print 'deleteFiles requires 1 args' + print 'getPackageContent requires 1 args' sys.exit(1) - pp.pprint(client.deleteFiles(eval(args[0]),)) + pp.pprint(client.getPackageContent(eval(args[0]),)) -elif cmd == 'deletePackages': +elif cmd == 'getPackageInfo': if len(args) != 1: - print 'deletePackages requires 1 args' + print 'getPackageInfo requires 1 args' sys.exit(1) - pp.pprint(client.deletePackages(eval(args[0]),)) + pp.pprint(client.getPackageInfo(eval(args[0]),)) -elif cmd == 'pushToQueue': +elif cmd == 'getFileInfo': if len(args) != 1: - print 'pushToQueue requires 1 args' + print 'getFileInfo requires 1 args' sys.exit(1) - pp.pprint(client.pushToQueue(eval(args[0]),)) + pp.pprint(client.getFileInfo(eval(args[0]),)) -elif cmd == 'pullFromQueue': +elif cmd == 'findFiles': if len(args) != 1: - print 'pullFromQueue requires 1 args' + print 'findFiles requires 1 args' sys.exit(1) - pp.pprint(client.pullFromQueue(eval(args[0]),)) + pp.pprint(client.findFiles(args[0],)) elif cmd == 'restartPackage': if len(args) != 1: @@ -409,23 +475,47 @@ elif cmd == 'recheckPackage': sys.exit(1) pp.pprint(client.recheckPackage(eval(args[0]),)) +elif cmd == 'stopDownloads': + if len(args) != 1: + print 'stopDownloads requires 1 args' + sys.exit(1) + pp.pprint(client.stopDownloads(eval(args[0]),)) + elif cmd == 'stopAllDownloads': if len(args) != 0: print 'stopAllDownloads requires 0 args' sys.exit(1) pp.pprint(client.stopAllDownloads()) -elif cmd == 'stopDownloads': - if len(args) != 1: - print 'stopDownloads requires 1 args' +elif cmd == 'restartFailed': + if len(args) != 0: + print 'restartFailed requires 0 args' sys.exit(1) - pp.pprint(client.stopDownloads(eval(args[0]),)) + pp.pprint(client.restartFailed()) + +elif cmd == 'setFilePaused': + if len(args) != 2: + print 'setFilePaused requires 2 args' + sys.exit(1) + pp.pprint(client.setFilePaused(eval(args[0]),eval(args[1]),)) + +elif cmd == 'setPackagePaused': + if len(args) != 2: + print 'setPackagePaused requires 2 args' + sys.exit(1) + pp.pprint(client.setPackagePaused(eval(args[0]),eval(args[1]),)) + +elif cmd == 'setPackageFolder': + if len(args) != 2: + print 'setPackageFolder requires 2 args' + sys.exit(1) + pp.pprint(client.setPackageFolder(eval(args[0]),args[1],)) -elif cmd == 'setPackageName': +elif cmd == 'setPackageData': if len(args) != 2: - print 'setPackageName requires 2 args' + print 'setPackageData requires 2 args' sys.exit(1) - pp.pprint(client.setPackageName(eval(args[0]),args[1],)) + pp.pprint(client.setPackageData(eval(args[0]),eval(args[1]),)) elif cmd == 'movePackage': if len(args) != 2: @@ -445,29 +535,47 @@ elif cmd == 'orderPackage': sys.exit(1) pp.pprint(client.orderPackage(eval(args[0]),eval(args[1]),)) -elif cmd == 'orderFile': +elif cmd == 'orderFiles': + if len(args) != 3: + print 'orderFiles requires 3 args' + sys.exit(1) + pp.pprint(client.orderFiles(eval(args[0]),eval(args[1]),eval(args[2]),)) + +elif cmd == 'isInteractionWaiting': + if len(args) != 1: + print 'isInteractionWaiting requires 1 args' + sys.exit(1) + pp.pprint(client.isInteractionWaiting(eval(args[0]),)) + +elif cmd == 'getInteractionTask': + if len(args) != 1: + print 'getInteractionTask requires 1 args' + sys.exit(1) + pp.pprint(client.getInteractionTask(eval(args[0]),)) + +elif cmd == 'setInteractionResult': if len(args) != 2: - print 'orderFile requires 2 args' + print 'setInteractionResult requires 2 args' sys.exit(1) - pp.pprint(client.orderFile(eval(args[0]),eval(args[1]),)) + pp.pprint(client.setInteractionResult(eval(args[0]),eval(args[1]),)) -elif cmd == 'setPackageData': +elif cmd == 'generateDownloadLink': if len(args) != 2: - print 'setPackageData requires 2 args' + print 'generateDownloadLink requires 2 args' sys.exit(1) - pp.pprint(client.setPackageData(eval(args[0]),eval(args[1]),)) + pp.pprint(client.generateDownloadLink(eval(args[0]),eval(args[1]),)) -elif cmd == 'deleteFinished': +elif cmd == 'getAddonHandler': if len(args) != 0: - print 'deleteFinished requires 0 args' + print 'getAddonHandler requires 0 args' sys.exit(1) - pp.pprint(client.deleteFinished()) + pp.pprint(client.getAddonHandler()) -elif cmd == 'restartFailed': - if len(args) != 0: - print 'restartFailed requires 0 args' +elif cmd == 'callAddonHandler': + if len(args) != 3: + print 'callAddonHandler requires 3 args' sys.exit(1) - pp.pprint(client.restartFailed()) + pp.pprint(client.callAddonHandler(eval(args[0]),args[1],eval(args[2]),)) elif cmd == 'getEvents': if len(args) != 1: @@ -530,10 +638,10 @@ elif cmd == 'hasService': pp.pprint(client.hasService(eval(args[0]),args[1],)) elif cmd == 'call': - if len(args) != 1: - print 'call requires 1 args' + if len(args) != 3: + print 'call requires 3 args' sys.exit(1) - pp.pprint(client.call(eval(args[0]),)) + pp.pprint(client.call(eval(args[0]),args[1],args[2],)) elif cmd == 'getAllInfo': if len(args) != 0: @@ -547,30 +655,6 @@ elif cmd == 'getInfoByPlugin': sys.exit(1) pp.pprint(client.getInfoByPlugin(eval(args[0]),)) -elif cmd == 'isCaptchaWaiting': - if len(args) != 0: - print 'isCaptchaWaiting requires 0 args' - sys.exit(1) - pp.pprint(client.isCaptchaWaiting()) - -elif cmd == 'getCaptchaTask': - if len(args) != 1: - print 'getCaptchaTask requires 1 args' - sys.exit(1) - pp.pprint(client.getCaptchaTask(eval(args[0]),)) - -elif cmd == 'getCaptchaTaskStatus': - if len(args) != 1: - print 'getCaptchaTaskStatus requires 1 args' - sys.exit(1) - pp.pprint(client.getCaptchaTaskStatus(eval(args[0]),)) - -elif cmd == 'setCaptchaResult': - if len(args) != 2: - print 'setCaptchaResult requires 2 args' - sys.exit(1) - pp.pprint(client.setCaptchaResult(eval(args[0]),args[1],)) - else: print 'Unrecognized method %s' % cmd sys.exit(1) diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py index 3e0fe3bbc..e58070a59 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py @@ -9,38 +9,14 @@ from thrift.Thrift import TType, TMessageType, TException from ttypes import * from thrift.Thrift import TProcessor -from thrift.protocol.TBase import TBase, TExceptionBase, TApplicationException +from thrift.protocol.TBase import TBase, TExceptionBase class Iface(object): - def getConfigValue(self, section, option): - """ - Parameters: - - section - - option - """ - pass - - def setConfigValue(self, section, option, value): - """ - Parameters: - - section - - option - - value - """ - pass - - def getConfig(self, ): - pass - - def getPluginConfig(self, ): + def getServerVersion(self, ): pass - def configureSection(self, section): - """ - Parameters: - - section - """ + def statusServer(self, ): pass def pauseServer(self, ): @@ -52,15 +28,9 @@ class Iface(object): def togglePause(self, ): pass - def statusServer(self, ): - pass - def freeSpace(self, ): pass - def getServerVersion(self, ): - pass - def kill(self, ): pass @@ -83,10 +53,48 @@ class Iface(object): def toggleReconnect(self, ): pass - def generatePackages(self, links): + def scanDownloadFolder(self, ): + pass + + def getProgressInfo(self, ): + pass + + def getConfigValue(self, section, option): """ Parameters: - - links + - section + - option + """ + pass + + def setConfigValue(self, section, option, value): + """ + Parameters: + - section + - option + - value + """ + pass + + def getConfig(self, ): + pass + + def getPluginConfig(self, ): + pass + + def configureSection(self, section): + """ + Parameters: + - section + """ + pass + + def setConfigHandler(self, plugin, iid, value): + """ + Parameters: + - plugin + - iid + - value """ pass @@ -128,118 +136,191 @@ class Iface(object): """ pass - def statusDownloads(self, ): + def generatePackages(self, links): + """ + Parameters: + - links + """ pass - def getPackageData(self, pid): + def generateAndAddPackages(self, links, paused): """ Parameters: - - pid + - links + - paused """ pass - def getPackageInfo(self, pid): + def autoAddLinks(self, links): """ Parameters: - - pid + - links """ pass - def getFileData(self, fid): + def createPackage(self, name, folder, root, password, site, comment, paused): """ Parameters: - - fid + - name + - folder + - root + - password + - site + - comment + - paused """ pass - def getQueue(self, ): + def addPackage(self, name, links, password): + """ + Parameters: + - name + - links + - password + """ pass - def getCollector(self, ): + def addPackageP(self, name, links, password, paused): + """ + Parameters: + - name + - links + - password + - paused + """ + pass + + def addPackageChild(self, name, links, password, root, paused): + """ + Parameters: + - name + - links + - password + - root + - paused + """ pass - def getQueueData(self, ): + def uploadContainer(self, filename, data): + """ + Parameters: + - filename + - data + """ pass - def getCollectorData(self, ): + def addLinks(self, pid, links): + """ + Parameters: + - pid + - links + """ pass - def getPackageOrder(self, destination): + def deleteFiles(self, fids): """ Parameters: - - destination + - fids """ pass - def getFileOrder(self, pid): + def deletePackages(self, pids): """ Parameters: - - pid + - pids """ pass - def generateAndAddPackages(self, links, dest): + def getCollector(self, ): + pass + + def addToCollector(self, links): """ Parameters: - links - - dest """ pass - def addPackage(self, name, links, dest, password): + def addFromCollector(self, name, paused): """ Parameters: - name - - links - - dest - - password + - paused """ pass - def addFiles(self, pid, links): + def renameCollPack(self, name, new_name): """ Parameters: - - pid - - links + - name + - new_name """ pass - def uploadContainer(self, filename, data): + def deleteCollPack(self, name): """ Parameters: - - filename - - data + - name """ pass - def deleteFiles(self, fids): + def deleteCollLink(self, url): """ Parameters: - - fids + - url """ pass - def deletePackages(self, pids): + def getAllFiles(self, ): + pass + + def getAllUnfinishedFiles(self, ): + pass + + def getFileTree(self, pid, full): """ Parameters: - - pids + - pid + - full """ pass - def pushToQueue(self, pid): + def getUnfinishedFileTree(self, pid, full): """ Parameters: - pid + - full """ pass - def pullFromQueue(self, pid): + def getPackageContent(self, pid): """ Parameters: - pid """ pass + def getPackageInfo(self, pid): + """ + Parameters: + - pid + """ + pass + + def getFileInfo(self, fid): + """ + Parameters: + - fid + """ + pass + + def findFiles(self, pattern): + """ + Parameters: + - pattern + """ + pass + def restartPackage(self, pid): """ Parameters: @@ -261,29 +342,56 @@ class Iface(object): """ pass + def stopDownloads(self, fids): + """ + Parameters: + - fids + """ + pass + def stopAllDownloads(self, ): pass - def stopDownloads(self, fids): + def restartFailed(self, ): + pass + + def setFilePaused(self, fid, paused): """ Parameters: - - fids + - fid + - paused """ pass - def setPackageName(self, pid, name): + def setPackagePaused(self, pid, paused): """ Parameters: - pid - - name + - paused """ pass - def movePackage(self, destination, pid): + def setPackageFolder(self, pid, path): """ Parameters: - - destination - pid + - path + """ + pass + + def setPackageData(self, pid, data): + """ + Parameters: + - pid + - data + """ + pass + + def movePackage(self, pid, root): + """ + Parameters: + - pid + - root """ pass @@ -295,34 +403,63 @@ class Iface(object): """ pass - def orderPackage(self, pid, position): + def orderPackage(self, pids, position): """ Parameters: - - pid + - pids - position """ pass - def orderFile(self, fid, position): + def orderFiles(self, fids, pid, position): """ Parameters: - - fid + - fids + - pid - position """ pass - def setPackageData(self, pid, data): + def isInteractionWaiting(self, mode): """ Parameters: - - pid - - data + - mode + """ + pass + + def getInteractionTask(self, mode): + """ + Parameters: + - mode """ pass - def deleteFinished(self, ): + def setInteractionResult(self, iid, result): + """ + Parameters: + - iid + - result + """ pass - def restartFailed(self, ): + def generateDownloadLink(self, fid, timeout): + """ + Parameters: + - fid + - timeout + """ + pass + + def getAddonHandler(self, ): + pass + + def callAddonHandler(self, plugin, func, pid_or_fid): + """ + Parameters: + - plugin + - func + - pid_or_fid + """ pass def getEvents(self, uuid): @@ -390,10 +527,12 @@ class Iface(object): """ pass - def call(self, info): + def call(self, plugin, func, arguments): """ Parameters: - - info + - plugin + - func + - arguments """ pass @@ -407,31 +546,6 @@ class Iface(object): """ pass - def isCaptchaWaiting(self, ): - pass - - def getCaptchaTask(self, exclusive): - """ - Parameters: - - exclusive - """ - pass - - def getCaptchaTaskStatus(self, tid): - """ - Parameters: - - tid - """ - pass - - def setCaptchaResult(self, tid, result): - """ - Parameters: - - tid - - result - """ - pass - class Client(Iface): def __init__(self, iprot, oprot=None): @@ -440,149 +554,55 @@ class Client(Iface): self._oprot = oprot self._seqid = 0 - def getConfigValue(self, section, option): - """ - Parameters: - - section - - option - """ - self.send_getConfigValue(section, option) - return self.recv_getConfigValue() + def getServerVersion(self, ): + self.send_getServerVersion() + return self.recv_getServerVersion() - def send_getConfigValue(self, section, option): - self._oprot.writeMessageBegin('getConfigValue', TMessageType.CALL, self._seqid) - args = getConfigValue_args() - args.section = section - args.option = option - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() - - def recv_getConfigValue(self, ): - (fname, mtype, rseqid) = self._iprot.readMessageBegin() - if mtype == TMessageType.EXCEPTION: - x = TApplicationException() - x.read(self._iprot) - self._iprot.readMessageEnd() - raise x - result = getConfigValue_result() - result.read(self._iprot) - self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getConfigValue failed: unknown result"); - - def setConfigValue(self, section, option, value): - """ - Parameters: - - section - - option - - value - """ - self.send_setConfigValue(section, option, value) - self.recv_setConfigValue() - - def send_setConfigValue(self, section, option, value): - self._oprot.writeMessageBegin('setConfigValue', TMessageType.CALL, self._seqid) - args = setConfigValue_args() - args.section = section - args.option = option - args.value = value - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() - - def recv_setConfigValue(self, ): - (fname, mtype, rseqid) = self._iprot.readMessageBegin() - if mtype == TMessageType.EXCEPTION: - x = TApplicationException() - x.read(self._iprot) - self._iprot.readMessageEnd() - raise x - result = setConfigValue_result() - result.read(self._iprot) - self._iprot.readMessageEnd() - return - - def getConfig(self, ): - self.send_getConfig() - return self.recv_getConfig() - - def send_getConfig(self, ): - self._oprot.writeMessageBegin('getConfig', TMessageType.CALL, self._seqid) - args = getConfig_args() - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() - - def recv_getConfig(self, ): - (fname, mtype, rseqid) = self._iprot.readMessageBegin() - if mtype == TMessageType.EXCEPTION: - x = TApplicationException() - x.read(self._iprot) - self._iprot.readMessageEnd() - raise x - result = getConfig_result() - result.read(self._iprot) - self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getConfig failed: unknown result"); - - def getPluginConfig(self, ): - self.send_getPluginConfig() - return self.recv_getPluginConfig() - - def send_getPluginConfig(self, ): - self._oprot.writeMessageBegin('getPluginConfig', TMessageType.CALL, self._seqid) - args = getPluginConfig_args() + def send_getServerVersion(self, ): + self._oprot.writeMessageBegin('getServerVersion', TMessageType.CALL, self._seqid) + args = getServerVersion_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPluginConfig(self, ): + def recv_getServerVersion(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getPluginConfig_result() + result = getServerVersion_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getPluginConfig failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getServerVersion failed: unknown result"); - def configureSection(self, section): - """ - Parameters: - - section - """ - self.send_configureSection(section) - return self.recv_configureSection() + def statusServer(self, ): + self.send_statusServer() + return self.recv_statusServer() - def send_configureSection(self, section): - self._oprot.writeMessageBegin('configureSection', TMessageType.CALL, self._seqid) - args = configureSection_args() - args.section = section + def send_statusServer(self, ): + self._oprot.writeMessageBegin('statusServer', TMessageType.CALL, self._seqid) + args = statusServer_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_configureSection(self, ): + def recv_statusServer(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = configureSection_result() + result = statusServer_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "configureSection failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "statusServer failed: unknown result"); def pauseServer(self, ): self.send_pauseServer() @@ -655,31 +675,6 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "togglePause failed: unknown result"); - def statusServer(self, ): - self.send_statusServer() - return self.recv_statusServer() - - def send_statusServer(self, ): - self._oprot.writeMessageBegin('statusServer', TMessageType.CALL, self._seqid) - args = statusServer_args() - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() - - def recv_statusServer(self, ): - (fname, mtype, rseqid) = self._iprot.readMessageBegin() - if mtype == TMessageType.EXCEPTION: - x = TApplicationException() - x.read(self._iprot) - self._iprot.readMessageEnd() - raise x - result = statusServer_result() - result.read(self._iprot) - self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "statusServer failed: unknown result"); - def freeSpace(self, ): self.send_freeSpace() return self.recv_freeSpace() @@ -705,31 +700,6 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "freeSpace failed: unknown result"); - def getServerVersion(self, ): - self.send_getServerVersion() - return self.recv_getServerVersion() - - def send_getServerVersion(self, ): - self._oprot.writeMessageBegin('getServerVersion', TMessageType.CALL, self._seqid) - args = getServerVersion_args() - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() - - def recv_getServerVersion(self, ): - (fname, mtype, rseqid) = self._iprot.readMessageBegin() - if mtype == TMessageType.EXCEPTION: - x = TApplicationException() - x.read(self._iprot) - self._iprot.readMessageEnd() - raise x - result = getServerVersion_result() - result.read(self._iprot) - self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getServerVersion failed: unknown result"); - def kill(self, ): self.send_kill() self.recv_kill() @@ -881,522 +851,535 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "toggleReconnect failed: unknown result"); - def generatePackages(self, links): - """ - Parameters: - - links - """ - self.send_generatePackages(links) - return self.recv_generatePackages() + def scanDownloadFolder(self, ): + self.send_scanDownloadFolder() + self.recv_scanDownloadFolder() - def send_generatePackages(self, links): - self._oprot.writeMessageBegin('generatePackages', TMessageType.CALL, self._seqid) - args = generatePackages_args() - args.links = links + def send_scanDownloadFolder(self, ): + self._oprot.writeMessageBegin('scanDownloadFolder', TMessageType.CALL, self._seqid) + args = scanDownloadFolder_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_generatePackages(self, ): + def recv_scanDownloadFolder(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = generatePackages_result() + result = scanDownloadFolder_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "generatePackages failed: unknown result"); + return - def checkURLs(self, urls): - """ - Parameters: - - urls - """ - self.send_checkURLs(urls) - return self.recv_checkURLs() + def getProgressInfo(self, ): + self.send_getProgressInfo() + return self.recv_getProgressInfo() - def send_checkURLs(self, urls): - self._oprot.writeMessageBegin('checkURLs', TMessageType.CALL, self._seqid) - args = checkURLs_args() - args.urls = urls + def send_getProgressInfo(self, ): + self._oprot.writeMessageBegin('getProgressInfo', TMessageType.CALL, self._seqid) + args = getProgressInfo_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkURLs(self, ): + def recv_getProgressInfo(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = checkURLs_result() + result = getProgressInfo_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "checkURLs failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getProgressInfo failed: unknown result"); - def parseURLs(self, html, url): + def getConfigValue(self, section, option): """ Parameters: - - html - - url + - section + - option """ - self.send_parseURLs(html, url) - return self.recv_parseURLs() + self.send_getConfigValue(section, option) + return self.recv_getConfigValue() - def send_parseURLs(self, html, url): - self._oprot.writeMessageBegin('parseURLs', TMessageType.CALL, self._seqid) - args = parseURLs_args() - args.html = html - args.url = url + def send_getConfigValue(self, section, option): + self._oprot.writeMessageBegin('getConfigValue', TMessageType.CALL, self._seqid) + args = getConfigValue_args() + args.section = section + args.option = option args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_parseURLs(self, ): + def recv_getConfigValue(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = parseURLs_result() + result = getConfigValue_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "parseURLs failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getConfigValue failed: unknown result"); - def checkOnlineStatus(self, urls): + def setConfigValue(self, section, option, value): """ Parameters: - - urls + - section + - option + - value """ - self.send_checkOnlineStatus(urls) - return self.recv_checkOnlineStatus() + self.send_setConfigValue(section, option, value) + self.recv_setConfigValue() - def send_checkOnlineStatus(self, urls): - self._oprot.writeMessageBegin('checkOnlineStatus', TMessageType.CALL, self._seqid) - args = checkOnlineStatus_args() - args.urls = urls + def send_setConfigValue(self, section, option, value): + self._oprot.writeMessageBegin('setConfigValue', TMessageType.CALL, self._seqid) + args = setConfigValue_args() + args.section = section + args.option = option + args.value = value args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkOnlineStatus(self, ): + def recv_setConfigValue(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = checkOnlineStatus_result() + result = setConfigValue_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "checkOnlineStatus failed: unknown result"); + return - def checkOnlineStatusContainer(self, urls, filename, data): - """ - Parameters: - - urls - - filename - - data - """ - self.send_checkOnlineStatusContainer(urls, filename, data) - return self.recv_checkOnlineStatusContainer() + def getConfig(self, ): + self.send_getConfig() + return self.recv_getConfig() - def send_checkOnlineStatusContainer(self, urls, filename, data): - self._oprot.writeMessageBegin('checkOnlineStatusContainer', TMessageType.CALL, self._seqid) - args = checkOnlineStatusContainer_args() - args.urls = urls - args.filename = filename - args.data = data + def send_getConfig(self, ): + self._oprot.writeMessageBegin('getConfig', TMessageType.CALL, self._seqid) + args = getConfig_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_checkOnlineStatusContainer(self, ): + def recv_getConfig(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = checkOnlineStatusContainer_result() + result = getConfig_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "checkOnlineStatusContainer failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getConfig failed: unknown result"); - def pollResults(self, rid): - """ - Parameters: - - rid - """ - self.send_pollResults(rid) - return self.recv_pollResults() + def getPluginConfig(self, ): + self.send_getPluginConfig() + return self.recv_getPluginConfig() - def send_pollResults(self, rid): - self._oprot.writeMessageBegin('pollResults', TMessageType.CALL, self._seqid) - args = pollResults_args() - args.rid = rid + def send_getPluginConfig(self, ): + self._oprot.writeMessageBegin('getPluginConfig', TMessageType.CALL, self._seqid) + args = getPluginConfig_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pollResults(self, ): + def recv_getPluginConfig(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = pollResults_result() + result = getPluginConfig_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "pollResults failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getPluginConfig failed: unknown result"); - def statusDownloads(self, ): - self.send_statusDownloads() - return self.recv_statusDownloads() + def configureSection(self, section): + """ + Parameters: + - section + """ + self.send_configureSection(section) + return self.recv_configureSection() - def send_statusDownloads(self, ): - self._oprot.writeMessageBegin('statusDownloads', TMessageType.CALL, self._seqid) - args = statusDownloads_args() + def send_configureSection(self, section): + self._oprot.writeMessageBegin('configureSection', TMessageType.CALL, self._seqid) + args = configureSection_args() + args.section = section args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_statusDownloads(self, ): + def recv_configureSection(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = statusDownloads_result() + result = configureSection_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "statusDownloads failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "configureSection failed: unknown result"); - def getPackageData(self, pid): + def setConfigHandler(self, plugin, iid, value): """ Parameters: - - pid + - plugin + - iid + - value """ - self.send_getPackageData(pid) - return self.recv_getPackageData() + self.send_setConfigHandler(plugin, iid, value) + self.recv_setConfigHandler() - def send_getPackageData(self, pid): - self._oprot.writeMessageBegin('getPackageData', TMessageType.CALL, self._seqid) - args = getPackageData_args() - args.pid = pid + def send_setConfigHandler(self, plugin, iid, value): + self._oprot.writeMessageBegin('setConfigHandler', TMessageType.CALL, self._seqid) + args = setConfigHandler_args() + args.plugin = plugin + args.iid = iid + args.value = value args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageData(self, ): + def recv_setConfigHandler(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getPackageData_result() + result = setConfigHandler_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - if result.e is not None: - raise result.e - raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageData failed: unknown result"); + return - def getPackageInfo(self, pid): + def checkURLs(self, urls): """ Parameters: - - pid + - urls """ - self.send_getPackageInfo(pid) - return self.recv_getPackageInfo() + self.send_checkURLs(urls) + return self.recv_checkURLs() - def send_getPackageInfo(self, pid): - self._oprot.writeMessageBegin('getPackageInfo', TMessageType.CALL, self._seqid) - args = getPackageInfo_args() - args.pid = pid + def send_checkURLs(self, urls): + self._oprot.writeMessageBegin('checkURLs', TMessageType.CALL, self._seqid) + args = checkURLs_args() + args.urls = urls args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageInfo(self, ): + def recv_checkURLs(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getPackageInfo_result() + result = checkURLs_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - if result.e is not None: - raise result.e - raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageInfo failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "checkURLs failed: unknown result"); - def getFileData(self, fid): + def parseURLs(self, html, url): """ Parameters: - - fid + - html + - url """ - self.send_getFileData(fid) - return self.recv_getFileData() + self.send_parseURLs(html, url) + return self.recv_parseURLs() - def send_getFileData(self, fid): - self._oprot.writeMessageBegin('getFileData', TMessageType.CALL, self._seqid) - args = getFileData_args() - args.fid = fid + def send_parseURLs(self, html, url): + self._oprot.writeMessageBegin('parseURLs', TMessageType.CALL, self._seqid) + args = parseURLs_args() + args.html = html + args.url = url args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getFileData(self, ): + def recv_parseURLs(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getFileData_result() + result = parseURLs_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - if result.e is not None: - raise result.e - raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileData failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "parseURLs failed: unknown result"); - def getQueue(self, ): - self.send_getQueue() - return self.recv_getQueue() + def checkOnlineStatus(self, urls): + """ + Parameters: + - urls + """ + self.send_checkOnlineStatus(urls) + return self.recv_checkOnlineStatus() - def send_getQueue(self, ): - self._oprot.writeMessageBegin('getQueue', TMessageType.CALL, self._seqid) - args = getQueue_args() + def send_checkOnlineStatus(self, urls): + self._oprot.writeMessageBegin('checkOnlineStatus', TMessageType.CALL, self._seqid) + args = checkOnlineStatus_args() + args.urls = urls args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getQueue(self, ): + def recv_checkOnlineStatus(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getQueue_result() + result = checkOnlineStatus_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getQueue failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "checkOnlineStatus failed: unknown result"); - def getCollector(self, ): - self.send_getCollector() - return self.recv_getCollector() + def checkOnlineStatusContainer(self, urls, filename, data): + """ + Parameters: + - urls + - filename + - data + """ + self.send_checkOnlineStatusContainer(urls, filename, data) + return self.recv_checkOnlineStatusContainer() - def send_getCollector(self, ): - self._oprot.writeMessageBegin('getCollector', TMessageType.CALL, self._seqid) - args = getCollector_args() + def send_checkOnlineStatusContainer(self, urls, filename, data): + self._oprot.writeMessageBegin('checkOnlineStatusContainer', TMessageType.CALL, self._seqid) + args = checkOnlineStatusContainer_args() + args.urls = urls + args.filename = filename + args.data = data args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCollector(self, ): + def recv_checkOnlineStatusContainer(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getCollector_result() + result = checkOnlineStatusContainer_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollector failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "checkOnlineStatusContainer failed: unknown result"); - def getQueueData(self, ): - self.send_getQueueData() - return self.recv_getQueueData() + def pollResults(self, rid): + """ + Parameters: + - rid + """ + self.send_pollResults(rid) + return self.recv_pollResults() - def send_getQueueData(self, ): - self._oprot.writeMessageBegin('getQueueData', TMessageType.CALL, self._seqid) - args = getQueueData_args() + def send_pollResults(self, rid): + self._oprot.writeMessageBegin('pollResults', TMessageType.CALL, self._seqid) + args = pollResults_args() + args.rid = rid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getQueueData(self, ): + def recv_pollResults(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getQueueData_result() + result = pollResults_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getQueueData failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "pollResults failed: unknown result"); - def getCollectorData(self, ): - self.send_getCollectorData() - return self.recv_getCollectorData() + def generatePackages(self, links): + """ + Parameters: + - links + """ + self.send_generatePackages(links) + return self.recv_generatePackages() - def send_getCollectorData(self, ): - self._oprot.writeMessageBegin('getCollectorData', TMessageType.CALL, self._seqid) - args = getCollectorData_args() + def send_generatePackages(self, links): + self._oprot.writeMessageBegin('generatePackages', TMessageType.CALL, self._seqid) + args = generatePackages_args() + args.links = links args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCollectorData(self, ): + def recv_generatePackages(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getCollectorData_result() + result = generatePackages_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollectorData failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "generatePackages failed: unknown result"); - def getPackageOrder(self, destination): + def generateAndAddPackages(self, links, paused): """ Parameters: - - destination + - links + - paused """ - self.send_getPackageOrder(destination) - return self.recv_getPackageOrder() + self.send_generateAndAddPackages(links, paused) + return self.recv_generateAndAddPackages() - def send_getPackageOrder(self, destination): - self._oprot.writeMessageBegin('getPackageOrder', TMessageType.CALL, self._seqid) - args = getPackageOrder_args() - args.destination = destination + def send_generateAndAddPackages(self, links, paused): + self._oprot.writeMessageBegin('generateAndAddPackages', TMessageType.CALL, self._seqid) + args = generateAndAddPackages_args() + args.links = links + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getPackageOrder(self, ): + def recv_generateAndAddPackages(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getPackageOrder_result() + result = generateAndAddPackages_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageOrder failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "generateAndAddPackages failed: unknown result"); - def getFileOrder(self, pid): + def autoAddLinks(self, links): """ Parameters: - - pid + - links """ - self.send_getFileOrder(pid) - return self.recv_getFileOrder() + self.send_autoAddLinks(links) + return self.recv_autoAddLinks() - def send_getFileOrder(self, pid): - self._oprot.writeMessageBegin('getFileOrder', TMessageType.CALL, self._seqid) - args = getFileOrder_args() - args.pid = pid + def send_autoAddLinks(self, links): + self._oprot.writeMessageBegin('autoAddLinks', TMessageType.CALL, self._seqid) + args = autoAddLinks_args() + args.links = links args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getFileOrder(self, ): + def recv_autoAddLinks(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getFileOrder_result() + result = autoAddLinks_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileOrder failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "autoAddLinks failed: unknown result"); - def generateAndAddPackages(self, links, dest): + def createPackage(self, name, folder, root, password, site, comment, paused): """ Parameters: - - links - - dest + - name + - folder + - root + - password + - site + - comment + - paused """ - self.send_generateAndAddPackages(links, dest) - return self.recv_generateAndAddPackages() + self.send_createPackage(name, folder, root, password, site, comment, paused) + return self.recv_createPackage() - def send_generateAndAddPackages(self, links, dest): - self._oprot.writeMessageBegin('generateAndAddPackages', TMessageType.CALL, self._seqid) - args = generateAndAddPackages_args() - args.links = links - args.dest = dest + def send_createPackage(self, name, folder, root, password, site, comment, paused): + self._oprot.writeMessageBegin('createPackage', TMessageType.CALL, self._seqid) + args = createPackage_args() + args.name = name + args.folder = folder + args.root = root + args.password = password + args.site = site + args.comment = comment + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_generateAndAddPackages(self, ): + def recv_createPackage(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = generateAndAddPackages_result() + result = createPackage_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "generateAndAddPackages failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "createPackage failed: unknown result"); - def addPackage(self, name, links, dest, password): + def addPackage(self, name, links, password): """ Parameters: - name - links - - dest - password """ - self.send_addPackage(name, links, dest, password) + self.send_addPackage(name, links, password) return self.recv_addPackage() - def send_addPackage(self, name, links, dest, password): + def send_addPackage(self, name, links, password): self._oprot.writeMessageBegin('addPackage', TMessageType.CALL, self._seqid) args = addPackage_args() args.name = name args.links = links - args.dest = dest args.password = password args.write(self._oprot) self._oprot.writeMessageEnd() @@ -1416,35 +1399,79 @@ class Client(Iface): return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "addPackage failed: unknown result"); - def addFiles(self, pid, links): + def addPackageP(self, name, links, password, paused): """ Parameters: - - pid + - name - links + - password + - paused """ - self.send_addFiles(pid, links) - self.recv_addFiles() + self.send_addPackageP(name, links, password, paused) + return self.recv_addPackageP() - def send_addFiles(self, pid, links): - self._oprot.writeMessageBegin('addFiles', TMessageType.CALL, self._seqid) - args = addFiles_args() - args.pid = pid + def send_addPackageP(self, name, links, password, paused): + self._oprot.writeMessageBegin('addPackageP', TMessageType.CALL, self._seqid) + args = addPackageP_args() + args.name = name args.links = links + args.password = password + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_addFiles(self, ): + def recv_addPackageP(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = addFiles_result() + result = addPackageP_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "addPackageP failed: unknown result"); + + def addPackageChild(self, name, links, password, root, paused): + """ + Parameters: + - name + - links + - password + - root + - paused + """ + self.send_addPackageChild(name, links, password, root, paused) + return self.recv_addPackageChild() + + def send_addPackageChild(self, name, links, password, root, paused): + self._oprot.writeMessageBegin('addPackageChild', TMessageType.CALL, self._seqid) + args = addPackageChild_args() + args.name = name + args.links = links + args.password = password + args.root = root + args.paused = paused + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_addPackageChild(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = addPackageChild_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "addPackageChild failed: unknown result"); def uploadContainer(self, filename, data): """ @@ -1453,7 +1480,7 @@ class Client(Iface): - data """ self.send_uploadContainer(filename, data) - self.recv_uploadContainer() + return self.recv_uploadContainer() def send_uploadContainer(self, filename, data): self._oprot.writeMessageBegin('uploadContainer', TMessageType.CALL, self._seqid) @@ -1474,1881 +1501,2891 @@ class Client(Iface): result = uploadContainer_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "uploadContainer failed: unknown result"); - def deleteFiles(self, fids): + def addLinks(self, pid, links): """ Parameters: - - fids + - pid + - links """ - self.send_deleteFiles(fids) - self.recv_deleteFiles() + self.send_addLinks(pid, links) + self.recv_addLinks() - def send_deleteFiles(self, fids): - self._oprot.writeMessageBegin('deleteFiles', TMessageType.CALL, self._seqid) - args = deleteFiles_args() - args.fids = fids + def send_addLinks(self, pid, links): + self._oprot.writeMessageBegin('addLinks', TMessageType.CALL, self._seqid) + args = addLinks_args() + args.pid = pid + args.links = links args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deleteFiles(self, ): + def recv_addLinks(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = deleteFiles_result() + result = addLinks_result() result.read(self._iprot) self._iprot.readMessageEnd() + if result.e is not None: + raise result.e return - def deletePackages(self, pids): + def deleteFiles(self, fids): """ Parameters: - - pids + - fids """ - self.send_deletePackages(pids) - self.recv_deletePackages() + self.send_deleteFiles(fids) + self.recv_deleteFiles() - def send_deletePackages(self, pids): - self._oprot.writeMessageBegin('deletePackages', TMessageType.CALL, self._seqid) - args = deletePackages_args() - args.pids = pids + def send_deleteFiles(self, fids): + self._oprot.writeMessageBegin('deleteFiles', TMessageType.CALL, self._seqid) + args = deleteFiles_args() + args.fids = fids args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deletePackages(self, ): + def recv_deleteFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = deletePackages_result() + result = deleteFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def pushToQueue(self, pid): + def deletePackages(self, pids): """ Parameters: - - pid + - pids """ - self.send_pushToQueue(pid) - self.recv_pushToQueue() + self.send_deletePackages(pids) + self.recv_deletePackages() - def send_pushToQueue(self, pid): - self._oprot.writeMessageBegin('pushToQueue', TMessageType.CALL, self._seqid) - args = pushToQueue_args() - args.pid = pid + def send_deletePackages(self, pids): + self._oprot.writeMessageBegin('deletePackages', TMessageType.CALL, self._seqid) + args = deletePackages_args() + args.pids = pids args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pushToQueue(self, ): + def recv_deletePackages(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = pushToQueue_result() + result = deletePackages_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def pullFromQueue(self, pid): - """ - Parameters: - - pid - """ - self.send_pullFromQueue(pid) - self.recv_pullFromQueue() + def getCollector(self, ): + self.send_getCollector() + return self.recv_getCollector() - def send_pullFromQueue(self, pid): - self._oprot.writeMessageBegin('pullFromQueue', TMessageType.CALL, self._seqid) - args = pullFromQueue_args() - args.pid = pid + def send_getCollector(self, ): + self._oprot.writeMessageBegin('getCollector', TMessageType.CALL, self._seqid) + args = getCollector_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_pullFromQueue(self, ): + def recv_getCollector(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = pullFromQueue_result() + result = getCollector_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollector failed: unknown result"); - def restartPackage(self, pid): + def addToCollector(self, links): """ Parameters: - - pid + - links """ - self.send_restartPackage(pid) - self.recv_restartPackage() + self.send_addToCollector(links) + self.recv_addToCollector() - def send_restartPackage(self, pid): - self._oprot.writeMessageBegin('restartPackage', TMessageType.CALL, self._seqid) - args = restartPackage_args() - args.pid = pid + def send_addToCollector(self, links): + self._oprot.writeMessageBegin('addToCollector', TMessageType.CALL, self._seqid) + args = addToCollector_args() + args.links = links args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartPackage(self, ): + def recv_addToCollector(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = restartPackage_result() + result = addToCollector_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def restartFile(self, fid): + def addFromCollector(self, name, paused): """ Parameters: - - fid + - name + - paused """ - self.send_restartFile(fid) - self.recv_restartFile() + self.send_addFromCollector(name, paused) + return self.recv_addFromCollector() - def send_restartFile(self, fid): - self._oprot.writeMessageBegin('restartFile', TMessageType.CALL, self._seqid) - args = restartFile_args() - args.fid = fid + def send_addFromCollector(self, name, paused): + self._oprot.writeMessageBegin('addFromCollector', TMessageType.CALL, self._seqid) + args = addFromCollector_args() + args.name = name + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartFile(self, ): + def recv_addFromCollector(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = restartFile_result() + result = addFromCollector_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "addFromCollector failed: unknown result"); - def recheckPackage(self, pid): + def renameCollPack(self, name, new_name): """ Parameters: - - pid + - name + - new_name """ - self.send_recheckPackage(pid) - self.recv_recheckPackage() + self.send_renameCollPack(name, new_name) + self.recv_renameCollPack() - def send_recheckPackage(self, pid): - self._oprot.writeMessageBegin('recheckPackage', TMessageType.CALL, self._seqid) - args = recheckPackage_args() - args.pid = pid + def send_renameCollPack(self, name, new_name): + self._oprot.writeMessageBegin('renameCollPack', TMessageType.CALL, self._seqid) + args = renameCollPack_args() + args.name = name + args.new_name = new_name args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_recheckPackage(self, ): + def recv_renameCollPack(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = recheckPackage_result() + result = renameCollPack_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def stopAllDownloads(self, ): - self.send_stopAllDownloads() - self.recv_stopAllDownloads() + def deleteCollPack(self, name): + """ + Parameters: + - name + """ + self.send_deleteCollPack(name) + self.recv_deleteCollPack() - def send_stopAllDownloads(self, ): - self._oprot.writeMessageBegin('stopAllDownloads', TMessageType.CALL, self._seqid) - args = stopAllDownloads_args() + def send_deleteCollPack(self, name): + self._oprot.writeMessageBegin('deleteCollPack', TMessageType.CALL, self._seqid) + args = deleteCollPack_args() + args.name = name args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_stopAllDownloads(self, ): + def recv_deleteCollPack(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = stopAllDownloads_result() + result = deleteCollPack_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def stopDownloads(self, fids): + def deleteCollLink(self, url): """ Parameters: - - fids + - url """ - self.send_stopDownloads(fids) - self.recv_stopDownloads() + self.send_deleteCollLink(url) + self.recv_deleteCollLink() - def send_stopDownloads(self, fids): - self._oprot.writeMessageBegin('stopDownloads', TMessageType.CALL, self._seqid) - args = stopDownloads_args() - args.fids = fids + def send_deleteCollLink(self, url): + self._oprot.writeMessageBegin('deleteCollLink', TMessageType.CALL, self._seqid) + args = deleteCollLink_args() + args.url = url args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_stopDownloads(self, ): + def recv_deleteCollLink(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = stopDownloads_result() + result = deleteCollLink_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def setPackageName(self, pid, name): - """ - Parameters: - - pid - - name - """ - self.send_setPackageName(pid, name) - self.recv_setPackageName() + def getAllFiles(self, ): + self.send_getAllFiles() + return self.recv_getAllFiles() - def send_setPackageName(self, pid, name): - self._oprot.writeMessageBegin('setPackageName', TMessageType.CALL, self._seqid) - args = setPackageName_args() - args.pid = pid - args.name = name + def send_getAllFiles(self, ): + self._oprot.writeMessageBegin('getAllFiles', TMessageType.CALL, self._seqid) + args = getAllFiles_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setPackageName(self, ): + def recv_getAllFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = setPackageName_result() + result = getAllFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllFiles failed: unknown result"); - def movePackage(self, destination, pid): - """ - Parameters: - - destination - - pid - """ - self.send_movePackage(destination, pid) - self.recv_movePackage() + def getAllUnfinishedFiles(self, ): + self.send_getAllUnfinishedFiles() + return self.recv_getAllUnfinishedFiles() - def send_movePackage(self, destination, pid): - self._oprot.writeMessageBegin('movePackage', TMessageType.CALL, self._seqid) - args = movePackage_args() - args.destination = destination - args.pid = pid + def send_getAllUnfinishedFiles(self, ): + self._oprot.writeMessageBegin('getAllUnfinishedFiles', TMessageType.CALL, self._seqid) + args = getAllUnfinishedFiles_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_movePackage(self, ): + def recv_getAllUnfinishedFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = movePackage_result() + result = getAllUnfinishedFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllUnfinishedFiles failed: unknown result"); - def moveFiles(self, fids, pid): + def getFileTree(self, pid, full): """ Parameters: - - fids - pid + - full """ - self.send_moveFiles(fids, pid) - self.recv_moveFiles() + self.send_getFileTree(pid, full) + return self.recv_getFileTree() - def send_moveFiles(self, fids, pid): - self._oprot.writeMessageBegin('moveFiles', TMessageType.CALL, self._seqid) - args = moveFiles_args() - args.fids = fids + def send_getFileTree(self, pid, full): + self._oprot.writeMessageBegin('getFileTree', TMessageType.CALL, self._seqid) + args = getFileTree_args() args.pid = pid + args.full = full args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_moveFiles(self, ): + def recv_getFileTree(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = moveFiles_result() + result = getFileTree_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileTree failed: unknown result"); - def orderPackage(self, pid, position): + def getUnfinishedFileTree(self, pid, full): """ Parameters: - pid - - position + - full """ - self.send_orderPackage(pid, position) - self.recv_orderPackage() + self.send_getUnfinishedFileTree(pid, full) + return self.recv_getUnfinishedFileTree() - def send_orderPackage(self, pid, position): - self._oprot.writeMessageBegin('orderPackage', TMessageType.CALL, self._seqid) - args = orderPackage_args() + def send_getUnfinishedFileTree(self, pid, full): + self._oprot.writeMessageBegin('getUnfinishedFileTree', TMessageType.CALL, self._seqid) + args = getUnfinishedFileTree_args() args.pid = pid - args.position = position + args.full = full args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_orderPackage(self, ): + def recv_getUnfinishedFileTree(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = orderPackage_result() + result = getUnfinishedFileTree_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getUnfinishedFileTree failed: unknown result"); - def orderFile(self, fid, position): + def getPackageContent(self, pid): """ Parameters: - - fid - - position + - pid """ - self.send_orderFile(fid, position) - self.recv_orderFile() + self.send_getPackageContent(pid) + return self.recv_getPackageContent() - def send_orderFile(self, fid, position): - self._oprot.writeMessageBegin('orderFile', TMessageType.CALL, self._seqid) - args = orderFile_args() - args.fid = fid - args.position = position + def send_getPackageContent(self, pid): + self._oprot.writeMessageBegin('getPackageContent', TMessageType.CALL, self._seqid) + args = getPackageContent_args() + args.pid = pid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_orderFile(self, ): + def recv_getPackageContent(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = orderFile_result() + result = getPackageContent_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageContent failed: unknown result"); - def setPackageData(self, pid, data): + def getPackageInfo(self, pid): """ Parameters: - pid - - data """ - self.send_setPackageData(pid, data) - self.recv_setPackageData() + self.send_getPackageInfo(pid) + return self.recv_getPackageInfo() - def send_setPackageData(self, pid, data): - self._oprot.writeMessageBegin('setPackageData', TMessageType.CALL, self._seqid) - args = setPackageData_args() + def send_getPackageInfo(self, pid): + self._oprot.writeMessageBegin('getPackageInfo', TMessageType.CALL, self._seqid) + args = getPackageInfo_args() args.pid = pid - args.data = data args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setPackageData(self, ): + def recv_getPackageInfo(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = setPackageData_result() + result = getPackageInfo_result() result.read(self._iprot) self._iprot.readMessageEnd() + if result.success is not None: + return result.success if result.e is not None: raise result.e - return + raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageInfo failed: unknown result"); - def deleteFinished(self, ): - self.send_deleteFinished() - return self.recv_deleteFinished() + def getFileInfo(self, fid): + """ + Parameters: + - fid + """ + self.send_getFileInfo(fid) + return self.recv_getFileInfo() - def send_deleteFinished(self, ): - self._oprot.writeMessageBegin('deleteFinished', TMessageType.CALL, self._seqid) - args = deleteFinished_args() + def send_getFileInfo(self, fid): + self._oprot.writeMessageBegin('getFileInfo', TMessageType.CALL, self._seqid) + args = getFileInfo_args() + args.fid = fid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_deleteFinished(self, ): + def recv_getFileInfo(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = deleteFinished_result() + result = getFileInfo_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "deleteFinished failed: unknown result"); + if result.e is not None: + raise result.e + raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileInfo failed: unknown result"); - def restartFailed(self, ): - self.send_restartFailed() - self.recv_restartFailed() + def findFiles(self, pattern): + """ + Parameters: + - pattern + """ + self.send_findFiles(pattern) + return self.recv_findFiles() - def send_restartFailed(self, ): - self._oprot.writeMessageBegin('restartFailed', TMessageType.CALL, self._seqid) - args = restartFailed_args() + def send_findFiles(self, pattern): + self._oprot.writeMessageBegin('findFiles', TMessageType.CALL, self._seqid) + args = findFiles_args() + args.pattern = pattern args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_restartFailed(self, ): + def recv_findFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = restartFailed_result() + result = findFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() - return + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "findFiles failed: unknown result"); - def getEvents(self, uuid): + def restartPackage(self, pid): """ Parameters: - - uuid + - pid """ - self.send_getEvents(uuid) - return self.recv_getEvents() + self.send_restartPackage(pid) + self.recv_restartPackage() - def send_getEvents(self, uuid): - self._oprot.writeMessageBegin('getEvents', TMessageType.CALL, self._seqid) - args = getEvents_args() - args.uuid = uuid + def send_restartPackage(self, pid): + self._oprot.writeMessageBegin('restartPackage', TMessageType.CALL, self._seqid) + args = restartPackage_args() + args.pid = pid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getEvents(self, ): + def recv_restartPackage(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getEvents_result() + result = restartPackage_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getEvents failed: unknown result"); + return - def getAccounts(self, refresh): + def restartFile(self, fid): """ Parameters: - - refresh + - fid """ - self.send_getAccounts(refresh) - return self.recv_getAccounts() + self.send_restartFile(fid) + self.recv_restartFile() - def send_getAccounts(self, refresh): - self._oprot.writeMessageBegin('getAccounts', TMessageType.CALL, self._seqid) - args = getAccounts_args() - args.refresh = refresh + def send_restartFile(self, fid): + self._oprot.writeMessageBegin('restartFile', TMessageType.CALL, self._seqid) + args = restartFile_args() + args.fid = fid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAccounts(self, ): + def recv_restartFile(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getAccounts_result() + result = restartFile_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccounts failed: unknown result"); + return - def getAccountTypes(self, ): - self.send_getAccountTypes() - return self.recv_getAccountTypes() + def recheckPackage(self, pid): + """ + Parameters: + - pid + """ + self.send_recheckPackage(pid) + self.recv_recheckPackage() - def send_getAccountTypes(self, ): - self._oprot.writeMessageBegin('getAccountTypes', TMessageType.CALL, self._seqid) - args = getAccountTypes_args() + def send_recheckPackage(self, pid): + self._oprot.writeMessageBegin('recheckPackage', TMessageType.CALL, self._seqid) + args = recheckPackage_args() + args.pid = pid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAccountTypes(self, ): + def recv_recheckPackage(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getAccountTypes_result() + result = recheckPackage_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccountTypes failed: unknown result"); + return - def updateAccount(self, plugin, account, password, options): + def stopDownloads(self, fids): """ Parameters: - - plugin - - account - - password - - options + - fids """ - self.send_updateAccount(plugin, account, password, options) - self.recv_updateAccount() + self.send_stopDownloads(fids) + self.recv_stopDownloads() - def send_updateAccount(self, plugin, account, password, options): - self._oprot.writeMessageBegin('updateAccount', TMessageType.CALL, self._seqid) - args = updateAccount_args() - args.plugin = plugin - args.account = account - args.password = password - args.options = options + def send_stopDownloads(self, fids): + self._oprot.writeMessageBegin('stopDownloads', TMessageType.CALL, self._seqid) + args = stopDownloads_args() + args.fids = fids args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_updateAccount(self, ): + def recv_stopDownloads(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = updateAccount_result() + result = stopDownloads_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def removeAccount(self, plugin, account): - """ - Parameters: - - plugin - - account - """ - self.send_removeAccount(plugin, account) - self.recv_removeAccount() + def stopAllDownloads(self, ): + self.send_stopAllDownloads() + self.recv_stopAllDownloads() - def send_removeAccount(self, plugin, account): - self._oprot.writeMessageBegin('removeAccount', TMessageType.CALL, self._seqid) - args = removeAccount_args() - args.plugin = plugin - args.account = account + def send_stopAllDownloads(self, ): + self._oprot.writeMessageBegin('stopAllDownloads', TMessageType.CALL, self._seqid) + args = stopAllDownloads_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_removeAccount(self, ): + def recv_stopAllDownloads(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = removeAccount_result() + result = stopAllDownloads_result() result.read(self._iprot) self._iprot.readMessageEnd() return - def login(self, username, password): - """ - Parameters: - - username - - password - """ - self.send_login(username, password) - return self.recv_login() + def restartFailed(self, ): + self.send_restartFailed() + self.recv_restartFailed() - def send_login(self, username, password): - self._oprot.writeMessageBegin('login', TMessageType.CALL, self._seqid) - args = login_args() - args.username = username - args.password = password + def send_restartFailed(self, ): + self._oprot.writeMessageBegin('restartFailed', TMessageType.CALL, self._seqid) + args = restartFailed_args() args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_login(self, ): + def recv_restartFailed(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = login_result() + result = restartFailed_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "login failed: unknown result"); + return - def getUserData(self, username, password): + def setFilePaused(self, fid, paused): """ Parameters: - - username - - password + - fid + - paused """ - self.send_getUserData(username, password) - return self.recv_getUserData() + self.send_setFilePaused(fid, paused) + self.recv_setFilePaused() - def send_getUserData(self, username, password): - self._oprot.writeMessageBegin('getUserData', TMessageType.CALL, self._seqid) - args = getUserData_args() - args.username = username - args.password = password + def send_setFilePaused(self, fid, paused): + self._oprot.writeMessageBegin('setFilePaused', TMessageType.CALL, self._seqid) + args = setFilePaused_args() + args.fid = fid + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getUserData(self, ): + def recv_setFilePaused(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getUserData_result() + result = setFilePaused_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - if result.ex is not None: - raise result.ex - raise TApplicationException(TApplicationException.MISSING_RESULT, "getUserData failed: unknown result"); + if result.e is not None: + raise result.e + return - def getAllUserData(self, ): - self.send_getAllUserData() - return self.recv_getAllUserData() + def setPackagePaused(self, pid, paused): + """ + Parameters: + - pid + - paused + """ + self.send_setPackagePaused(pid, paused) + self.recv_setPackagePaused() - def send_getAllUserData(self, ): - self._oprot.writeMessageBegin('getAllUserData', TMessageType.CALL, self._seqid) - args = getAllUserData_args() + def send_setPackagePaused(self, pid, paused): + self._oprot.writeMessageBegin('setPackagePaused', TMessageType.CALL, self._seqid) + args = setPackagePaused_args() + args.pid = pid + args.paused = paused args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAllUserData(self, ): + def recv_setPackagePaused(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getAllUserData_result() + result = setPackagePaused_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllUserData failed: unknown result"); + if result.e is not None: + raise result.e + return - def getServices(self, ): - self.send_getServices() - return self.recv_getServices() + def setPackageFolder(self, pid, path): + """ + Parameters: + - pid + - path + """ + self.send_setPackageFolder(pid, path) + return self.recv_setPackageFolder() - def send_getServices(self, ): - self._oprot.writeMessageBegin('getServices', TMessageType.CALL, self._seqid) - args = getServices_args() + def send_setPackageFolder(self, pid, path): + self._oprot.writeMessageBegin('setPackageFolder', TMessageType.CALL, self._seqid) + args = setPackageFolder_args() + args.pid = pid + args.path = path args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getServices(self, ): + def recv_setPackageFolder(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getServices_result() + result = setPackageFolder_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getServices failed: unknown result"); + if result.e is not None: + raise result.e + raise TApplicationException(TApplicationException.MISSING_RESULT, "setPackageFolder failed: unknown result"); - def hasService(self, plugin, func): + def setPackageData(self, pid, data): """ Parameters: - - plugin - - func + - pid + - data """ - self.send_hasService(plugin, func) - return self.recv_hasService() + self.send_setPackageData(pid, data) + self.recv_setPackageData() - def send_hasService(self, plugin, func): - self._oprot.writeMessageBegin('hasService', TMessageType.CALL, self._seqid) - args = hasService_args() - args.plugin = plugin - args.func = func + def send_setPackageData(self, pid, data): + self._oprot.writeMessageBegin('setPackageData', TMessageType.CALL, self._seqid) + args = setPackageData_args() + args.pid = pid + args.data = data args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_hasService(self, ): + def recv_setPackageData(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = hasService_result() + result = setPackageData_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "hasService failed: unknown result"); + if result.e is not None: + raise result.e + return - def call(self, info): + def movePackage(self, pid, root): """ Parameters: - - info + - pid + - root """ - self.send_call(info) - return self.recv_call() + self.send_movePackage(pid, root) + return self.recv_movePackage() - def send_call(self, info): - self._oprot.writeMessageBegin('call', TMessageType.CALL, self._seqid) - args = call_args() - args.info = info + def send_movePackage(self, pid, root): + self._oprot.writeMessageBegin('movePackage', TMessageType.CALL, self._seqid) + args = movePackage_args() + args.pid = pid + args.root = root args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_call(self, ): + def recv_movePackage(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = call_result() + result = movePackage_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - if result.ex is not None: - raise result.ex if result.e is not None: raise result.e - raise TApplicationException(TApplicationException.MISSING_RESULT, "call failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "movePackage failed: unknown result"); - def getAllInfo(self, ): - self.send_getAllInfo() - return self.recv_getAllInfo() + def moveFiles(self, fids, pid): + """ + Parameters: + - fids + - pid + """ + self.send_moveFiles(fids, pid) + return self.recv_moveFiles() - def send_getAllInfo(self, ): - self._oprot.writeMessageBegin('getAllInfo', TMessageType.CALL, self._seqid) - args = getAllInfo_args() + def send_moveFiles(self, fids, pid): + self._oprot.writeMessageBegin('moveFiles', TMessageType.CALL, self._seqid) + args = moveFiles_args() + args.fids = fids + args.pid = pid args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getAllInfo(self, ): + def recv_moveFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getAllInfo_result() + result = moveFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllInfo failed: unknown result"); + if result.e is not None: + raise result.e + raise TApplicationException(TApplicationException.MISSING_RESULT, "moveFiles failed: unknown result"); - def getInfoByPlugin(self, plugin): + def orderPackage(self, pids, position): """ Parameters: - - plugin + - pids + - position """ - self.send_getInfoByPlugin(plugin) - return self.recv_getInfoByPlugin() + self.send_orderPackage(pids, position) + self.recv_orderPackage() - def send_getInfoByPlugin(self, plugin): - self._oprot.writeMessageBegin('getInfoByPlugin', TMessageType.CALL, self._seqid) - args = getInfoByPlugin_args() - args.plugin = plugin + def send_orderPackage(self, pids, position): + self._oprot.writeMessageBegin('orderPackage', TMessageType.CALL, self._seqid) + args = orderPackage_args() + args.pids = pids + args.position = position args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getInfoByPlugin(self, ): + def recv_orderPackage(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getInfoByPlugin_result() + result = orderPackage_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getInfoByPlugin failed: unknown result"); - - def isCaptchaWaiting(self, ): - self.send_isCaptchaWaiting() - return self.recv_isCaptchaWaiting() - - def send_isCaptchaWaiting(self, ): - self._oprot.writeMessageBegin('isCaptchaWaiting', TMessageType.CALL, self._seqid) - args = isCaptchaWaiting_args() - args.write(self._oprot) - self._oprot.writeMessageEnd() - self._oprot.trans.flush() + return - def recv_isCaptchaWaiting(self, ): + def orderFiles(self, fids, pid, position): + """ + Parameters: + - fids + - pid + - position + """ + self.send_orderFiles(fids, pid, position) + self.recv_orderFiles() + + def send_orderFiles(self, fids, pid, position): + self._oprot.writeMessageBegin('orderFiles', TMessageType.CALL, self._seqid) + args = orderFiles_args() + args.fids = fids + args.pid = pid + args.position = position + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_orderFiles(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = isCaptchaWaiting_result() + result = orderFiles_result() result.read(self._iprot) self._iprot.readMessageEnd() - if result.success is not None: - return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "isCaptchaWaiting failed: unknown result"); + return - def getCaptchaTask(self, exclusive): + def isInteractionWaiting(self, mode): """ Parameters: - - exclusive + - mode """ - self.send_getCaptchaTask(exclusive) - return self.recv_getCaptchaTask() + self.send_isInteractionWaiting(mode) + return self.recv_isInteractionWaiting() - def send_getCaptchaTask(self, exclusive): - self._oprot.writeMessageBegin('getCaptchaTask', TMessageType.CALL, self._seqid) - args = getCaptchaTask_args() - args.exclusive = exclusive + def send_isInteractionWaiting(self, mode): + self._oprot.writeMessageBegin('isInteractionWaiting', TMessageType.CALL, self._seqid) + args = isInteractionWaiting_args() + args.mode = mode args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCaptchaTask(self, ): + def recv_isInteractionWaiting(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getCaptchaTask_result() + result = isInteractionWaiting_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getCaptchaTask failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "isInteractionWaiting failed: unknown result"); - def getCaptchaTaskStatus(self, tid): + def getInteractionTask(self, mode): """ Parameters: - - tid + - mode """ - self.send_getCaptchaTaskStatus(tid) - return self.recv_getCaptchaTaskStatus() + self.send_getInteractionTask(mode) + return self.recv_getInteractionTask() - def send_getCaptchaTaskStatus(self, tid): - self._oprot.writeMessageBegin('getCaptchaTaskStatus', TMessageType.CALL, self._seqid) - args = getCaptchaTaskStatus_args() - args.tid = tid + def send_getInteractionTask(self, mode): + self._oprot.writeMessageBegin('getInteractionTask', TMessageType.CALL, self._seqid) + args = getInteractionTask_args() + args.mode = mode args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_getCaptchaTaskStatus(self, ): + def recv_getInteractionTask(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = getCaptchaTaskStatus_result() + result = getInteractionTask_result() result.read(self._iprot) self._iprot.readMessageEnd() if result.success is not None: return result.success - raise TApplicationException(TApplicationException.MISSING_RESULT, "getCaptchaTaskStatus failed: unknown result"); + raise TApplicationException(TApplicationException.MISSING_RESULT, "getInteractionTask failed: unknown result"); - def setCaptchaResult(self, tid, result): + def setInteractionResult(self, iid, result): """ Parameters: - - tid + - iid - result """ - self.send_setCaptchaResult(tid, result) - self.recv_setCaptchaResult() + self.send_setInteractionResult(iid, result) + self.recv_setInteractionResult() - def send_setCaptchaResult(self, tid, result): - self._oprot.writeMessageBegin('setCaptchaResult', TMessageType.CALL, self._seqid) - args = setCaptchaResult_args() - args.tid = tid + def send_setInteractionResult(self, iid, result): + self._oprot.writeMessageBegin('setInteractionResult', TMessageType.CALL, self._seqid) + args = setInteractionResult_args() + args.iid = iid args.result = result args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() - def recv_setCaptchaResult(self, ): + def recv_setInteractionResult(self, ): (fname, mtype, rseqid) = self._iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(self._iprot) self._iprot.readMessageEnd() raise x - result = setCaptchaResult_result() + result = setInteractionResult_result() result.read(self._iprot) self._iprot.readMessageEnd() return + def generateDownloadLink(self, fid, timeout): + """ + Parameters: + - fid + - timeout + """ + self.send_generateDownloadLink(fid, timeout) + return self.recv_generateDownloadLink() -class Processor(Iface, TProcessor): - def __init__(self, handler): - self._handler = handler - self._processMap = {} - self._processMap["getConfigValue"] = Processor.process_getConfigValue - self._processMap["setConfigValue"] = Processor.process_setConfigValue - self._processMap["getConfig"] = Processor.process_getConfig - self._processMap["getPluginConfig"] = Processor.process_getPluginConfig - self._processMap["configureSection"] = Processor.process_configureSection - self._processMap["pauseServer"] = Processor.process_pauseServer - self._processMap["unpauseServer"] = Processor.process_unpauseServer - self._processMap["togglePause"] = Processor.process_togglePause - self._processMap["statusServer"] = Processor.process_statusServer - self._processMap["freeSpace"] = Processor.process_freeSpace - self._processMap["getServerVersion"] = Processor.process_getServerVersion - self._processMap["kill"] = Processor.process_kill - self._processMap["restart"] = Processor.process_restart - self._processMap["getLog"] = Processor.process_getLog - self._processMap["isTimeDownload"] = Processor.process_isTimeDownload - self._processMap["isTimeReconnect"] = Processor.process_isTimeReconnect - self._processMap["toggleReconnect"] = Processor.process_toggleReconnect - self._processMap["generatePackages"] = Processor.process_generatePackages - self._processMap["checkURLs"] = Processor.process_checkURLs - self._processMap["parseURLs"] = Processor.process_parseURLs - self._processMap["checkOnlineStatus"] = Processor.process_checkOnlineStatus - self._processMap["checkOnlineStatusContainer"] = Processor.process_checkOnlineStatusContainer - self._processMap["pollResults"] = Processor.process_pollResults - self._processMap["statusDownloads"] = Processor.process_statusDownloads - self._processMap["getPackageData"] = Processor.process_getPackageData - self._processMap["getPackageInfo"] = Processor.process_getPackageInfo - self._processMap["getFileData"] = Processor.process_getFileData - self._processMap["getQueue"] = Processor.process_getQueue - self._processMap["getCollector"] = Processor.process_getCollector - self._processMap["getQueueData"] = Processor.process_getQueueData - self._processMap["getCollectorData"] = Processor.process_getCollectorData - self._processMap["getPackageOrder"] = Processor.process_getPackageOrder - self._processMap["getFileOrder"] = Processor.process_getFileOrder - self._processMap["generateAndAddPackages"] = Processor.process_generateAndAddPackages - self._processMap["addPackage"] = Processor.process_addPackage - self._processMap["addFiles"] = Processor.process_addFiles - self._processMap["uploadContainer"] = Processor.process_uploadContainer - self._processMap["deleteFiles"] = Processor.process_deleteFiles - self._processMap["deletePackages"] = Processor.process_deletePackages - self._processMap["pushToQueue"] = Processor.process_pushToQueue - self._processMap["pullFromQueue"] = Processor.process_pullFromQueue - self._processMap["restartPackage"] = Processor.process_restartPackage - self._processMap["restartFile"] = Processor.process_restartFile - self._processMap["recheckPackage"] = Processor.process_recheckPackage - self._processMap["stopAllDownloads"] = Processor.process_stopAllDownloads - self._processMap["stopDownloads"] = Processor.process_stopDownloads - self._processMap["setPackageName"] = Processor.process_setPackageName - self._processMap["movePackage"] = Processor.process_movePackage - self._processMap["moveFiles"] = Processor.process_moveFiles - self._processMap["orderPackage"] = Processor.process_orderPackage - self._processMap["orderFile"] = Processor.process_orderFile - self._processMap["setPackageData"] = Processor.process_setPackageData - self._processMap["deleteFinished"] = Processor.process_deleteFinished - self._processMap["restartFailed"] = Processor.process_restartFailed - self._processMap["getEvents"] = Processor.process_getEvents - self._processMap["getAccounts"] = Processor.process_getAccounts - self._processMap["getAccountTypes"] = Processor.process_getAccountTypes - self._processMap["updateAccount"] = Processor.process_updateAccount - self._processMap["removeAccount"] = Processor.process_removeAccount - self._processMap["login"] = Processor.process_login - self._processMap["getUserData"] = Processor.process_getUserData - self._processMap["getAllUserData"] = Processor.process_getAllUserData - self._processMap["getServices"] = Processor.process_getServices - self._processMap["hasService"] = Processor.process_hasService - self._processMap["call"] = Processor.process_call - self._processMap["getAllInfo"] = Processor.process_getAllInfo - self._processMap["getInfoByPlugin"] = Processor.process_getInfoByPlugin - self._processMap["isCaptchaWaiting"] = Processor.process_isCaptchaWaiting - self._processMap["getCaptchaTask"] = Processor.process_getCaptchaTask - self._processMap["getCaptchaTaskStatus"] = Processor.process_getCaptchaTaskStatus - self._processMap["setCaptchaResult"] = Processor.process_setCaptchaResult + def send_generateDownloadLink(self, fid, timeout): + self._oprot.writeMessageBegin('generateDownloadLink', TMessageType.CALL, self._seqid) + args = generateDownloadLink_args() + args.fid = fid + args.timeout = timeout + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() - def process(self, iprot, oprot): - (name, type, seqid) = iprot.readMessageBegin() - if name not in self._processMap: - iprot.skip(TType.STRUCT) - iprot.readMessageEnd() - x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) - oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) - x.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - return - else: - self._processMap[name](self, seqid, iprot, oprot) - return True + def recv_generateDownloadLink(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = generateDownloadLink_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "generateDownloadLink failed: unknown result"); - def process_getConfigValue(self, seqid, iprot, oprot): - args = getConfigValue_args() - args.read(iprot) - iprot.readMessageEnd() - result = getConfigValue_result() - result.success = self._handler.getConfigValue(args.section, args.option) - oprot.writeMessageBegin("getConfigValue", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def getAddonHandler(self, ): + self.send_getAddonHandler() + return self.recv_getAddonHandler() - def process_setConfigValue(self, seqid, iprot, oprot): - args = setConfigValue_args() - args.read(iprot) - iprot.readMessageEnd() - result = setConfigValue_result() - self._handler.setConfigValue(args.section, args.option, args.value) - oprot.writeMessageBegin("setConfigValue", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def send_getAddonHandler(self, ): + self._oprot.writeMessageBegin('getAddonHandler', TMessageType.CALL, self._seqid) + args = getAddonHandler_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() - def process_getConfig(self, seqid, iprot, oprot): - args = getConfig_args() - args.read(iprot) - iprot.readMessageEnd() - result = getConfig_result() - result.success = self._handler.getConfig() - oprot.writeMessageBegin("getConfig", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def recv_getAddonHandler(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getAddonHandler_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAddonHandler failed: unknown result"); - def process_getPluginConfig(self, seqid, iprot, oprot): - args = getPluginConfig_args() - args.read(iprot) - iprot.readMessageEnd() - result = getPluginConfig_result() - result.success = self._handler.getPluginConfig() - oprot.writeMessageBegin("getPluginConfig", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def callAddonHandler(self, plugin, func, pid_or_fid): + """ + Parameters: + - plugin + - func + - pid_or_fid + """ + self.send_callAddonHandler(plugin, func, pid_or_fid) + self.recv_callAddonHandler() - def process_configureSection(self, seqid, iprot, oprot): - args = configureSection_args() - args.read(iprot) - iprot.readMessageEnd() - result = configureSection_result() - result.success = self._handler.configureSection(args.section) - oprot.writeMessageBegin("configureSection", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def send_callAddonHandler(self, plugin, func, pid_or_fid): + self._oprot.writeMessageBegin('callAddonHandler', TMessageType.CALL, self._seqid) + args = callAddonHandler_args() + args.plugin = plugin + args.func = func + args.pid_or_fid = pid_or_fid + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() - def process_pauseServer(self, seqid, iprot, oprot): - args = pauseServer_args() - args.read(iprot) - iprot.readMessageEnd() - result = pauseServer_result() - self._handler.pauseServer() - oprot.writeMessageBegin("pauseServer", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def recv_callAddonHandler(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = callAddonHandler_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + return - def process_unpauseServer(self, seqid, iprot, oprot): - args = unpauseServer_args() - args.read(iprot) - iprot.readMessageEnd() - result = unpauseServer_result() - self._handler.unpauseServer() - oprot.writeMessageBegin("unpauseServer", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def getEvents(self, uuid): + """ + Parameters: + - uuid + """ + self.send_getEvents(uuid) + return self.recv_getEvents() - def process_togglePause(self, seqid, iprot, oprot): - args = togglePause_args() - args.read(iprot) - iprot.readMessageEnd() - result = togglePause_result() - result.success = self._handler.togglePause() - oprot.writeMessageBegin("togglePause", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def send_getEvents(self, uuid): + self._oprot.writeMessageBegin('getEvents', TMessageType.CALL, self._seqid) + args = getEvents_args() + args.uuid = uuid + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() - def process_statusServer(self, seqid, iprot, oprot): - args = statusServer_args() - args.read(iprot) - iprot.readMessageEnd() - result = statusServer_result() - result.success = self._handler.statusServer() - oprot.writeMessageBegin("statusServer", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def recv_getEvents(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getEvents_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getEvents failed: unknown result"); - def process_freeSpace(self, seqid, iprot, oprot): + def getAccounts(self, refresh): + """ + Parameters: + - refresh + """ + self.send_getAccounts(refresh) + return self.recv_getAccounts() + + def send_getAccounts(self, refresh): + self._oprot.writeMessageBegin('getAccounts', TMessageType.CALL, self._seqid) + args = getAccounts_args() + args.refresh = refresh + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getAccounts(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getAccounts_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccounts failed: unknown result"); + + def getAccountTypes(self, ): + self.send_getAccountTypes() + return self.recv_getAccountTypes() + + def send_getAccountTypes(self, ): + self._oprot.writeMessageBegin('getAccountTypes', TMessageType.CALL, self._seqid) + args = getAccountTypes_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getAccountTypes(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getAccountTypes_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccountTypes failed: unknown result"); + + def updateAccount(self, plugin, account, password, options): + """ + Parameters: + - plugin + - account + - password + - options + """ + self.send_updateAccount(plugin, account, password, options) + self.recv_updateAccount() + + def send_updateAccount(self, plugin, account, password, options): + self._oprot.writeMessageBegin('updateAccount', TMessageType.CALL, self._seqid) + args = updateAccount_args() + args.plugin = plugin + args.account = account + args.password = password + args.options = options + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_updateAccount(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = updateAccount_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + return + + def removeAccount(self, plugin, account): + """ + Parameters: + - plugin + - account + """ + self.send_removeAccount(plugin, account) + self.recv_removeAccount() + + def send_removeAccount(self, plugin, account): + self._oprot.writeMessageBegin('removeAccount', TMessageType.CALL, self._seqid) + args = removeAccount_args() + args.plugin = plugin + args.account = account + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_removeAccount(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = removeAccount_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + return + + def login(self, username, password): + """ + Parameters: + - username + - password + """ + self.send_login(username, password) + return self.recv_login() + + def send_login(self, username, password): + self._oprot.writeMessageBegin('login', TMessageType.CALL, self._seqid) + args = login_args() + args.username = username + args.password = password + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_login(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = login_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "login failed: unknown result"); + + def getUserData(self, username, password): + """ + Parameters: + - username + - password + """ + self.send_getUserData(username, password) + return self.recv_getUserData() + + def send_getUserData(self, username, password): + self._oprot.writeMessageBegin('getUserData', TMessageType.CALL, self._seqid) + args = getUserData_args() + args.username = username + args.password = password + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getUserData(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getUserData_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ex is not None: + raise result.ex + raise TApplicationException(TApplicationException.MISSING_RESULT, "getUserData failed: unknown result"); + + def getAllUserData(self, ): + self.send_getAllUserData() + return self.recv_getAllUserData() + + def send_getAllUserData(self, ): + self._oprot.writeMessageBegin('getAllUserData', TMessageType.CALL, self._seqid) + args = getAllUserData_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getAllUserData(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getAllUserData_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllUserData failed: unknown result"); + + def getServices(self, ): + self.send_getServices() + return self.recv_getServices() + + def send_getServices(self, ): + self._oprot.writeMessageBegin('getServices', TMessageType.CALL, self._seqid) + args = getServices_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getServices(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getServices_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getServices failed: unknown result"); + + def hasService(self, plugin, func): + """ + Parameters: + - plugin + - func + """ + self.send_hasService(plugin, func) + return self.recv_hasService() + + def send_hasService(self, plugin, func): + self._oprot.writeMessageBegin('hasService', TMessageType.CALL, self._seqid) + args = hasService_args() + args.plugin = plugin + args.func = func + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_hasService(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = hasService_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "hasService failed: unknown result"); + + def call(self, plugin, func, arguments): + """ + Parameters: + - plugin + - func + - arguments + """ + self.send_call(plugin, func, arguments) + return self.recv_call() + + def send_call(self, plugin, func, arguments): + self._oprot.writeMessageBegin('call', TMessageType.CALL, self._seqid) + args = call_args() + args.plugin = plugin + args.func = func + args.arguments = arguments + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_call(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = call_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ex is not None: + raise result.ex + if result.e is not None: + raise result.e + raise TApplicationException(TApplicationException.MISSING_RESULT, "call failed: unknown result"); + + def getAllInfo(self, ): + self.send_getAllInfo() + return self.recv_getAllInfo() + + def send_getAllInfo(self, ): + self._oprot.writeMessageBegin('getAllInfo', TMessageType.CALL, self._seqid) + args = getAllInfo_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getAllInfo(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getAllInfo_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllInfo failed: unknown result"); + + def getInfoByPlugin(self, plugin): + """ + Parameters: + - plugin + """ + self.send_getInfoByPlugin(plugin) + return self.recv_getInfoByPlugin() + + def send_getInfoByPlugin(self, plugin): + self._oprot.writeMessageBegin('getInfoByPlugin', TMessageType.CALL, self._seqid) + args = getInfoByPlugin_args() + args.plugin = plugin + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_getInfoByPlugin(self, ): + (fname, mtype, rseqid) = self._iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(self._iprot) + self._iprot.readMessageEnd() + raise x + result = getInfoByPlugin_result() + result.read(self._iprot) + self._iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "getInfoByPlugin failed: unknown result"); + + +class Processor(Iface, TProcessor): + def __init__(self, handler): + self._handler = handler + self._processMap = {} + self._processMap["getServerVersion"] = Processor.process_getServerVersion + self._processMap["statusServer"] = Processor.process_statusServer + self._processMap["pauseServer"] = Processor.process_pauseServer + self._processMap["unpauseServer"] = Processor.process_unpauseServer + self._processMap["togglePause"] = Processor.process_togglePause + self._processMap["freeSpace"] = Processor.process_freeSpace + self._processMap["kill"] = Processor.process_kill + self._processMap["restart"] = Processor.process_restart + self._processMap["getLog"] = Processor.process_getLog + self._processMap["isTimeDownload"] = Processor.process_isTimeDownload + self._processMap["isTimeReconnect"] = Processor.process_isTimeReconnect + self._processMap["toggleReconnect"] = Processor.process_toggleReconnect + self._processMap["scanDownloadFolder"] = Processor.process_scanDownloadFolder + self._processMap["getProgressInfo"] = Processor.process_getProgressInfo + self._processMap["getConfigValue"] = Processor.process_getConfigValue + self._processMap["setConfigValue"] = Processor.process_setConfigValue + self._processMap["getConfig"] = Processor.process_getConfig + self._processMap["getPluginConfig"] = Processor.process_getPluginConfig + self._processMap["configureSection"] = Processor.process_configureSection + self._processMap["setConfigHandler"] = Processor.process_setConfigHandler + self._processMap["checkURLs"] = Processor.process_checkURLs + self._processMap["parseURLs"] = Processor.process_parseURLs + self._processMap["checkOnlineStatus"] = Processor.process_checkOnlineStatus + self._processMap["checkOnlineStatusContainer"] = Processor.process_checkOnlineStatusContainer + self._processMap["pollResults"] = Processor.process_pollResults + self._processMap["generatePackages"] = Processor.process_generatePackages + self._processMap["generateAndAddPackages"] = Processor.process_generateAndAddPackages + self._processMap["autoAddLinks"] = Processor.process_autoAddLinks + self._processMap["createPackage"] = Processor.process_createPackage + self._processMap["addPackage"] = Processor.process_addPackage + self._processMap["addPackageP"] = Processor.process_addPackageP + self._processMap["addPackageChild"] = Processor.process_addPackageChild + self._processMap["uploadContainer"] = Processor.process_uploadContainer + self._processMap["addLinks"] = Processor.process_addLinks + self._processMap["deleteFiles"] = Processor.process_deleteFiles + self._processMap["deletePackages"] = Processor.process_deletePackages + self._processMap["getCollector"] = Processor.process_getCollector + self._processMap["addToCollector"] = Processor.process_addToCollector + self._processMap["addFromCollector"] = Processor.process_addFromCollector + self._processMap["renameCollPack"] = Processor.process_renameCollPack + self._processMap["deleteCollPack"] = Processor.process_deleteCollPack + self._processMap["deleteCollLink"] = Processor.process_deleteCollLink + self._processMap["getAllFiles"] = Processor.process_getAllFiles + self._processMap["getAllUnfinishedFiles"] = Processor.process_getAllUnfinishedFiles + self._processMap["getFileTree"] = Processor.process_getFileTree + self._processMap["getUnfinishedFileTree"] = Processor.process_getUnfinishedFileTree + self._processMap["getPackageContent"] = Processor.process_getPackageContent + self._processMap["getPackageInfo"] = Processor.process_getPackageInfo + self._processMap["getFileInfo"] = Processor.process_getFileInfo + self._processMap["findFiles"] = Processor.process_findFiles + self._processMap["restartPackage"] = Processor.process_restartPackage + self._processMap["restartFile"] = Processor.process_restartFile + self._processMap["recheckPackage"] = Processor.process_recheckPackage + self._processMap["stopDownloads"] = Processor.process_stopDownloads + self._processMap["stopAllDownloads"] = Processor.process_stopAllDownloads + self._processMap["restartFailed"] = Processor.process_restartFailed + self._processMap["setFilePaused"] = Processor.process_setFilePaused + self._processMap["setPackagePaused"] = Processor.process_setPackagePaused + self._processMap["setPackageFolder"] = Processor.process_setPackageFolder + self._processMap["setPackageData"] = Processor.process_setPackageData + self._processMap["movePackage"] = Processor.process_movePackage + self._processMap["moveFiles"] = Processor.process_moveFiles + self._processMap["orderPackage"] = Processor.process_orderPackage + self._processMap["orderFiles"] = Processor.process_orderFiles + self._processMap["isInteractionWaiting"] = Processor.process_isInteractionWaiting + self._processMap["getInteractionTask"] = Processor.process_getInteractionTask + self._processMap["setInteractionResult"] = Processor.process_setInteractionResult + self._processMap["generateDownloadLink"] = Processor.process_generateDownloadLink + self._processMap["getAddonHandler"] = Processor.process_getAddonHandler + self._processMap["callAddonHandler"] = Processor.process_callAddonHandler + self._processMap["getEvents"] = Processor.process_getEvents + self._processMap["getAccounts"] = Processor.process_getAccounts + self._processMap["getAccountTypes"] = Processor.process_getAccountTypes + self._processMap["updateAccount"] = Processor.process_updateAccount + self._processMap["removeAccount"] = Processor.process_removeAccount + self._processMap["login"] = Processor.process_login + self._processMap["getUserData"] = Processor.process_getUserData + self._processMap["getAllUserData"] = Processor.process_getAllUserData + self._processMap["getServices"] = Processor.process_getServices + self._processMap["hasService"] = Processor.process_hasService + self._processMap["call"] = Processor.process_call + self._processMap["getAllInfo"] = Processor.process_getAllInfo + self._processMap["getInfoByPlugin"] = Processor.process_getInfoByPlugin + + def process(self, iprot, oprot): + (name, type, seqid) = iprot.readMessageBegin() + if name not in self._processMap: + iprot.skip(TType.STRUCT) + iprot.readMessageEnd() + x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) + oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) + x.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + return + else: + self._processMap[name](self, seqid, iprot, oprot) + return True + + def process_getServerVersion(self, seqid, iprot, oprot): + args = getServerVersion_args() + args.read(iprot) + iprot.readMessageEnd() + result = getServerVersion_result() + result.success = self._handler.getServerVersion() + oprot.writeMessageBegin("getServerVersion", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_statusServer(self, seqid, iprot, oprot): + args = statusServer_args() + args.read(iprot) + iprot.readMessageEnd() + result = statusServer_result() + result.success = self._handler.statusServer() + oprot.writeMessageBegin("statusServer", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pauseServer(self, seqid, iprot, oprot): + args = pauseServer_args() + args.read(iprot) + iprot.readMessageEnd() + result = pauseServer_result() + self._handler.pauseServer() + oprot.writeMessageBegin("pauseServer", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_unpauseServer(self, seqid, iprot, oprot): + args = unpauseServer_args() + args.read(iprot) + iprot.readMessageEnd() + result = unpauseServer_result() + self._handler.unpauseServer() + oprot.writeMessageBegin("unpauseServer", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_togglePause(self, seqid, iprot, oprot): + args = togglePause_args() + args.read(iprot) + iprot.readMessageEnd() + result = togglePause_result() + result.success = self._handler.togglePause() + oprot.writeMessageBegin("togglePause", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_freeSpace(self, seqid, iprot, oprot): args = freeSpace_args() args.read(iprot) iprot.readMessageEnd() - result = freeSpace_result() - result.success = self._handler.freeSpace() - oprot.writeMessageBegin("freeSpace", TMessageType.REPLY, seqid) + result = freeSpace_result() + result.success = self._handler.freeSpace() + oprot.writeMessageBegin("freeSpace", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_kill(self, seqid, iprot, oprot): + args = kill_args() + args.read(iprot) + iprot.readMessageEnd() + result = kill_result() + self._handler.kill() + oprot.writeMessageBegin("kill", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_restart(self, seqid, iprot, oprot): + args = restart_args() + args.read(iprot) + iprot.readMessageEnd() + result = restart_result() + self._handler.restart() + oprot.writeMessageBegin("restart", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getLog(self, seqid, iprot, oprot): + args = getLog_args() + args.read(iprot) + iprot.readMessageEnd() + result = getLog_result() + result.success = self._handler.getLog(args.offset) + oprot.writeMessageBegin("getLog", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_isTimeDownload(self, seqid, iprot, oprot): + args = isTimeDownload_args() + args.read(iprot) + iprot.readMessageEnd() + result = isTimeDownload_result() + result.success = self._handler.isTimeDownload() + oprot.writeMessageBegin("isTimeDownload", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_isTimeReconnect(self, seqid, iprot, oprot): + args = isTimeReconnect_args() + args.read(iprot) + iprot.readMessageEnd() + result = isTimeReconnect_result() + result.success = self._handler.isTimeReconnect() + oprot.writeMessageBegin("isTimeReconnect", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_toggleReconnect(self, seqid, iprot, oprot): + args = toggleReconnect_args() + args.read(iprot) + iprot.readMessageEnd() + result = toggleReconnect_result() + result.success = self._handler.toggleReconnect() + oprot.writeMessageBegin("toggleReconnect", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_scanDownloadFolder(self, seqid, iprot, oprot): + args = scanDownloadFolder_args() + args.read(iprot) + iprot.readMessageEnd() + result = scanDownloadFolder_result() + self._handler.scanDownloadFolder() + oprot.writeMessageBegin("scanDownloadFolder", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getProgressInfo(self, seqid, iprot, oprot): + args = getProgressInfo_args() + args.read(iprot) + iprot.readMessageEnd() + result = getProgressInfo_result() + result.success = self._handler.getProgressInfo() + oprot.writeMessageBegin("getProgressInfo", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getConfigValue(self, seqid, iprot, oprot): + args = getConfigValue_args() + args.read(iprot) + iprot.readMessageEnd() + result = getConfigValue_result() + result.success = self._handler.getConfigValue(args.section, args.option) + oprot.writeMessageBegin("getConfigValue", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setConfigValue(self, seqid, iprot, oprot): + args = setConfigValue_args() + args.read(iprot) + iprot.readMessageEnd() + result = setConfigValue_result() + self._handler.setConfigValue(args.section, args.option, args.value) + oprot.writeMessageBegin("setConfigValue", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getConfig(self, seqid, iprot, oprot): + args = getConfig_args() + args.read(iprot) + iprot.readMessageEnd() + result = getConfig_result() + result.success = self._handler.getConfig() + oprot.writeMessageBegin("getConfig", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getPluginConfig(self, seqid, iprot, oprot): + args = getPluginConfig_args() + args.read(iprot) + iprot.readMessageEnd() + result = getPluginConfig_result() + result.success = self._handler.getPluginConfig() + oprot.writeMessageBegin("getPluginConfig", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_configureSection(self, seqid, iprot, oprot): + args = configureSection_args() + args.read(iprot) + iprot.readMessageEnd() + result = configureSection_result() + result.success = self._handler.configureSection(args.section) + oprot.writeMessageBegin("configureSection", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setConfigHandler(self, seqid, iprot, oprot): + args = setConfigHandler_args() + args.read(iprot) + iprot.readMessageEnd() + result = setConfigHandler_result() + self._handler.setConfigHandler(args.plugin, args.iid, args.value) + oprot.writeMessageBegin("setConfigHandler", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_checkURLs(self, seqid, iprot, oprot): + args = checkURLs_args() + args.read(iprot) + iprot.readMessageEnd() + result = checkURLs_result() + result.success = self._handler.checkURLs(args.urls) + oprot.writeMessageBegin("checkURLs", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_parseURLs(self, seqid, iprot, oprot): + args = parseURLs_args() + args.read(iprot) + iprot.readMessageEnd() + result = parseURLs_result() + result.success = self._handler.parseURLs(args.html, args.url) + oprot.writeMessageBegin("parseURLs", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_checkOnlineStatus(self, seqid, iprot, oprot): + args = checkOnlineStatus_args() + args.read(iprot) + iprot.readMessageEnd() + result = checkOnlineStatus_result() + result.success = self._handler.checkOnlineStatus(args.urls) + oprot.writeMessageBegin("checkOnlineStatus", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_checkOnlineStatusContainer(self, seqid, iprot, oprot): + args = checkOnlineStatusContainer_args() + args.read(iprot) + iprot.readMessageEnd() + result = checkOnlineStatusContainer_result() + result.success = self._handler.checkOnlineStatusContainer(args.urls, args.filename, args.data) + oprot.writeMessageBegin("checkOnlineStatusContainer", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pollResults(self, seqid, iprot, oprot): + args = pollResults_args() + args.read(iprot) + iprot.readMessageEnd() + result = pollResults_result() + result.success = self._handler.pollResults(args.rid) + oprot.writeMessageBegin("pollResults", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_generatePackages(self, seqid, iprot, oprot): + args = generatePackages_args() + args.read(iprot) + iprot.readMessageEnd() + result = generatePackages_result() + result.success = self._handler.generatePackages(args.links) + oprot.writeMessageBegin("generatePackages", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_generateAndAddPackages(self, seqid, iprot, oprot): + args = generateAndAddPackages_args() + args.read(iprot) + iprot.readMessageEnd() + result = generateAndAddPackages_result() + result.success = self._handler.generateAndAddPackages(args.links, args.paused) + oprot.writeMessageBegin("generateAndAddPackages", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_autoAddLinks(self, seqid, iprot, oprot): + args = autoAddLinks_args() + args.read(iprot) + iprot.readMessageEnd() + result = autoAddLinks_result() + result.success = self._handler.autoAddLinks(args.links) + oprot.writeMessageBegin("autoAddLinks", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_createPackage(self, seqid, iprot, oprot): + args = createPackage_args() + args.read(iprot) + iprot.readMessageEnd() + result = createPackage_result() + result.success = self._handler.createPackage(args.name, args.folder, args.root, args.password, args.site, args.comment, args.paused) + oprot.writeMessageBegin("createPackage", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addPackage(self, seqid, iprot, oprot): + args = addPackage_args() + args.read(iprot) + iprot.readMessageEnd() + result = addPackage_result() + result.success = self._handler.addPackage(args.name, args.links, args.password) + oprot.writeMessageBegin("addPackage", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addPackageP(self, seqid, iprot, oprot): + args = addPackageP_args() + args.read(iprot) + iprot.readMessageEnd() + result = addPackageP_result() + result.success = self._handler.addPackageP(args.name, args.links, args.password, args.paused) + oprot.writeMessageBegin("addPackageP", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addPackageChild(self, seqid, iprot, oprot): + args = addPackageChild_args() + args.read(iprot) + iprot.readMessageEnd() + result = addPackageChild_result() + result.success = self._handler.addPackageChild(args.name, args.links, args.password, args.root, args.paused) + oprot.writeMessageBegin("addPackageChild", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_uploadContainer(self, seqid, iprot, oprot): + args = uploadContainer_args() + args.read(iprot) + iprot.readMessageEnd() + result = uploadContainer_result() + result.success = self._handler.uploadContainer(args.filename, args.data) + oprot.writeMessageBegin("uploadContainer", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addLinks(self, seqid, iprot, oprot): + args = addLinks_args() + args.read(iprot) + iprot.readMessageEnd() + result = addLinks_result() + try: + self._handler.addLinks(args.pid, args.links) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("addLinks", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_deleteFiles(self, seqid, iprot, oprot): + args = deleteFiles_args() + args.read(iprot) + iprot.readMessageEnd() + result = deleteFiles_result() + self._handler.deleteFiles(args.fids) + oprot.writeMessageBegin("deleteFiles", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_deletePackages(self, seqid, iprot, oprot): + args = deletePackages_args() + args.read(iprot) + iprot.readMessageEnd() + result = deletePackages_result() + self._handler.deletePackages(args.pids) + oprot.writeMessageBegin("deletePackages", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getCollector(self, seqid, iprot, oprot): + args = getCollector_args() + args.read(iprot) + iprot.readMessageEnd() + result = getCollector_result() + result.success = self._handler.getCollector() + oprot.writeMessageBegin("getCollector", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addToCollector(self, seqid, iprot, oprot): + args = addToCollector_args() + args.read(iprot) + iprot.readMessageEnd() + result = addToCollector_result() + self._handler.addToCollector(args.links) + oprot.writeMessageBegin("addToCollector", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_addFromCollector(self, seqid, iprot, oprot): + args = addFromCollector_args() + args.read(iprot) + iprot.readMessageEnd() + result = addFromCollector_result() + result.success = self._handler.addFromCollector(args.name, args.paused) + oprot.writeMessageBegin("addFromCollector", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_renameCollPack(self, seqid, iprot, oprot): + args = renameCollPack_args() + args.read(iprot) + iprot.readMessageEnd() + result = renameCollPack_result() + self._handler.renameCollPack(args.name, args.new_name) + oprot.writeMessageBegin("renameCollPack", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_deleteCollPack(self, seqid, iprot, oprot): + args = deleteCollPack_args() + args.read(iprot) + iprot.readMessageEnd() + result = deleteCollPack_result() + self._handler.deleteCollPack(args.name) + oprot.writeMessageBegin("deleteCollPack", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_deleteCollLink(self, seqid, iprot, oprot): + args = deleteCollLink_args() + args.read(iprot) + iprot.readMessageEnd() + result = deleteCollLink_result() + self._handler.deleteCollLink(args.url) + oprot.writeMessageBegin("deleteCollLink", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getAllFiles(self, seqid, iprot, oprot): + args = getAllFiles_args() + args.read(iprot) + iprot.readMessageEnd() + result = getAllFiles_result() + result.success = self._handler.getAllFiles() + oprot.writeMessageBegin("getAllFiles", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getAllUnfinishedFiles(self, seqid, iprot, oprot): + args = getAllUnfinishedFiles_args() + args.read(iprot) + iprot.readMessageEnd() + result = getAllUnfinishedFiles_result() + result.success = self._handler.getAllUnfinishedFiles() + oprot.writeMessageBegin("getAllUnfinishedFiles", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getFileTree(self, seqid, iprot, oprot): + args = getFileTree_args() + args.read(iprot) + iprot.readMessageEnd() + result = getFileTree_result() + result.success = self._handler.getFileTree(args.pid, args.full) + oprot.writeMessageBegin("getFileTree", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getUnfinishedFileTree(self, seqid, iprot, oprot): + args = getUnfinishedFileTree_args() + args.read(iprot) + iprot.readMessageEnd() + result = getUnfinishedFileTree_result() + result.success = self._handler.getUnfinishedFileTree(args.pid, args.full) + oprot.writeMessageBegin("getUnfinishedFileTree", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getPackageContent(self, seqid, iprot, oprot): + args = getPackageContent_args() + args.read(iprot) + iprot.readMessageEnd() + result = getPackageContent_result() + result.success = self._handler.getPackageContent(args.pid) + oprot.writeMessageBegin("getPackageContent", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getPackageInfo(self, seqid, iprot, oprot): + args = getPackageInfo_args() + args.read(iprot) + iprot.readMessageEnd() + result = getPackageInfo_result() + try: + result.success = self._handler.getPackageInfo(args.pid) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("getPackageInfo", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getFileInfo(self, seqid, iprot, oprot): + args = getFileInfo_args() + args.read(iprot) + iprot.readMessageEnd() + result = getFileInfo_result() + try: + result.success = self._handler.getFileInfo(args.fid) + except FileDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("getFileInfo", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_getServerVersion(self, seqid, iprot, oprot): - args = getServerVersion_args() + def process_findFiles(self, seqid, iprot, oprot): + args = findFiles_args() args.read(iprot) iprot.readMessageEnd() - result = getServerVersion_result() - result.success = self._handler.getServerVersion() - oprot.writeMessageBegin("getServerVersion", TMessageType.REPLY, seqid) + result = findFiles_result() + result.success = self._handler.findFiles(args.pattern) + oprot.writeMessageBegin("findFiles", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_kill(self, seqid, iprot, oprot): - args = kill_args() + def process_restartPackage(self, seqid, iprot, oprot): + args = restartPackage_args() args.read(iprot) iprot.readMessageEnd() - result = kill_result() - self._handler.kill() - oprot.writeMessageBegin("kill", TMessageType.REPLY, seqid) + result = restartPackage_result() + self._handler.restartPackage(args.pid) + oprot.writeMessageBegin("restartPackage", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_restart(self, seqid, iprot, oprot): - args = restart_args() + def process_restartFile(self, seqid, iprot, oprot): + args = restartFile_args() args.read(iprot) iprot.readMessageEnd() - result = restart_result() - self._handler.restart() - oprot.writeMessageBegin("restart", TMessageType.REPLY, seqid) + result = restartFile_result() + self._handler.restartFile(args.fid) + oprot.writeMessageBegin("restartFile", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_getLog(self, seqid, iprot, oprot): - args = getLog_args() + def process_recheckPackage(self, seqid, iprot, oprot): + args = recheckPackage_args() args.read(iprot) iprot.readMessageEnd() - result = getLog_result() - result.success = self._handler.getLog(args.offset) - oprot.writeMessageBegin("getLog", TMessageType.REPLY, seqid) + result = recheckPackage_result() + self._handler.recheckPackage(args.pid) + oprot.writeMessageBegin("recheckPackage", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_stopDownloads(self, seqid, iprot, oprot): + args = stopDownloads_args() + args.read(iprot) + iprot.readMessageEnd() + result = stopDownloads_result() + self._handler.stopDownloads(args.fids) + oprot.writeMessageBegin("stopDownloads", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_stopAllDownloads(self, seqid, iprot, oprot): + args = stopAllDownloads_args() + args.read(iprot) + iprot.readMessageEnd() + result = stopAllDownloads_result() + self._handler.stopAllDownloads() + oprot.writeMessageBegin("stopAllDownloads", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_restartFailed(self, seqid, iprot, oprot): + args = restartFailed_args() + args.read(iprot) + iprot.readMessageEnd() + result = restartFailed_result() + self._handler.restartFailed() + oprot.writeMessageBegin("restartFailed", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setFilePaused(self, seqid, iprot, oprot): + args = setFilePaused_args() + args.read(iprot) + iprot.readMessageEnd() + result = setFilePaused_result() + try: + self._handler.setFilePaused(args.fid, args.paused) + except FileDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("setFilePaused", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setPackagePaused(self, seqid, iprot, oprot): + args = setPackagePaused_args() + args.read(iprot) + iprot.readMessageEnd() + result = setPackagePaused_result() + try: + self._handler.setPackagePaused(args.pid, args.paused) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("setPackagePaused", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setPackageFolder(self, seqid, iprot, oprot): + args = setPackageFolder_args() + args.read(iprot) + iprot.readMessageEnd() + result = setPackageFolder_result() + try: + result.success = self._handler.setPackageFolder(args.pid, args.path) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("setPackageFolder", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setPackageData(self, seqid, iprot, oprot): + args = setPackageData_args() + args.read(iprot) + iprot.readMessageEnd() + result = setPackageData_result() + try: + self._handler.setPackageData(args.pid, args.data) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("setPackageData", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_movePackage(self, seqid, iprot, oprot): + args = movePackage_args() + args.read(iprot) + iprot.readMessageEnd() + result = movePackage_result() + try: + result.success = self._handler.movePackage(args.pid, args.root) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("movePackage", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_moveFiles(self, seqid, iprot, oprot): + args = moveFiles_args() + args.read(iprot) + iprot.readMessageEnd() + result = moveFiles_result() + try: + result.success = self._handler.moveFiles(args.fids, args.pid) + except PackageDoesNotExists, e: + result.e = e + oprot.writeMessageBegin("moveFiles", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_orderPackage(self, seqid, iprot, oprot): + args = orderPackage_args() + args.read(iprot) + iprot.readMessageEnd() + result = orderPackage_result() + self._handler.orderPackage(args.pids, args.position) + oprot.writeMessageBegin("orderPackage", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_orderFiles(self, seqid, iprot, oprot): + args = orderFiles_args() + args.read(iprot) + iprot.readMessageEnd() + result = orderFiles_result() + self._handler.orderFiles(args.fids, args.pid, args.position) + oprot.writeMessageBegin("orderFiles", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_isInteractionWaiting(self, seqid, iprot, oprot): + args = isInteractionWaiting_args() + args.read(iprot) + iprot.readMessageEnd() + result = isInteractionWaiting_result() + result.success = self._handler.isInteractionWaiting(args.mode) + oprot.writeMessageBegin("isInteractionWaiting", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getInteractionTask(self, seqid, iprot, oprot): + args = getInteractionTask_args() + args.read(iprot) + iprot.readMessageEnd() + result = getInteractionTask_result() + result.success = self._handler.getInteractionTask(args.mode) + oprot.writeMessageBegin("getInteractionTask", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_setInteractionResult(self, seqid, iprot, oprot): + args = setInteractionResult_args() + args.read(iprot) + iprot.readMessageEnd() + result = setInteractionResult_result() + self._handler.setInteractionResult(args.iid, args.result) + oprot.writeMessageBegin("setInteractionResult", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_generateDownloadLink(self, seqid, iprot, oprot): + args = generateDownloadLink_args() + args.read(iprot) + iprot.readMessageEnd() + result = generateDownloadLink_result() + result.success = self._handler.generateDownloadLink(args.fid, args.timeout) + oprot.writeMessageBegin("generateDownloadLink", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getAddonHandler(self, seqid, iprot, oprot): + args = getAddonHandler_args() + args.read(iprot) + iprot.readMessageEnd() + result = getAddonHandler_result() + result.success = self._handler.getAddonHandler() + oprot.writeMessageBegin("getAddonHandler", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_callAddonHandler(self, seqid, iprot, oprot): + args = callAddonHandler_args() + args.read(iprot) + iprot.readMessageEnd() + result = callAddonHandler_result() + self._handler.callAddonHandler(args.plugin, args.func, args.pid_or_fid) + oprot.writeMessageBegin("callAddonHandler", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getEvents(self, seqid, iprot, oprot): + args = getEvents_args() + args.read(iprot) + iprot.readMessageEnd() + result = getEvents_result() + result.success = self._handler.getEvents(args.uuid) + oprot.writeMessageBegin("getEvents", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getAccounts(self, seqid, iprot, oprot): + args = getAccounts_args() + args.read(iprot) + iprot.readMessageEnd() + result = getAccounts_result() + result.success = self._handler.getAccounts(args.refresh) + oprot.writeMessageBegin("getAccounts", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_getAccountTypes(self, seqid, iprot, oprot): + args = getAccountTypes_args() + args.read(iprot) + iprot.readMessageEnd() + result = getAccountTypes_result() + result.success = self._handler.getAccountTypes() + oprot.writeMessageBegin("getAccountTypes", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_updateAccount(self, seqid, iprot, oprot): + args = updateAccount_args() + args.read(iprot) + iprot.readMessageEnd() + result = updateAccount_result() + self._handler.updateAccount(args.plugin, args.account, args.password, args.options) + oprot.writeMessageBegin("updateAccount", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_removeAccount(self, seqid, iprot, oprot): + args = removeAccount_args() + args.read(iprot) + iprot.readMessageEnd() + result = removeAccount_result() + self._handler.removeAccount(args.plugin, args.account) + oprot.writeMessageBegin("removeAccount", TMessageType.REPLY, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_login(self, seqid, iprot, oprot): + args = login_args() + args.read(iprot) + iprot.readMessageEnd() + result = login_result() + result.success = self._handler.login(args.username, args.password) + oprot.writeMessageBegin("login", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_isTimeDownload(self, seqid, iprot, oprot): - args = isTimeDownload_args() + def process_getUserData(self, seqid, iprot, oprot): + args = getUserData_args() args.read(iprot) iprot.readMessageEnd() - result = isTimeDownload_result() - result.success = self._handler.isTimeDownload() - oprot.writeMessageBegin("isTimeDownload", TMessageType.REPLY, seqid) + result = getUserData_result() + try: + result.success = self._handler.getUserData(args.username, args.password) + except UserDoesNotExists, ex: + result.ex = ex + oprot.writeMessageBegin("getUserData", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_isTimeReconnect(self, seqid, iprot, oprot): - args = isTimeReconnect_args() + def process_getAllUserData(self, seqid, iprot, oprot): + args = getAllUserData_args() args.read(iprot) iprot.readMessageEnd() - result = isTimeReconnect_result() - result.success = self._handler.isTimeReconnect() - oprot.writeMessageBegin("isTimeReconnect", TMessageType.REPLY, seqid) + result = getAllUserData_result() + result.success = self._handler.getAllUserData() + oprot.writeMessageBegin("getAllUserData", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_toggleReconnect(self, seqid, iprot, oprot): - args = toggleReconnect_args() + def process_getServices(self, seqid, iprot, oprot): + args = getServices_args() args.read(iprot) iprot.readMessageEnd() - result = toggleReconnect_result() - result.success = self._handler.toggleReconnect() - oprot.writeMessageBegin("toggleReconnect", TMessageType.REPLY, seqid) + result = getServices_result() + result.success = self._handler.getServices() + oprot.writeMessageBegin("getServices", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_generatePackages(self, seqid, iprot, oprot): - args = generatePackages_args() + def process_hasService(self, seqid, iprot, oprot): + args = hasService_args() args.read(iprot) iprot.readMessageEnd() - result = generatePackages_result() - result.success = self._handler.generatePackages(args.links) - oprot.writeMessageBegin("generatePackages", TMessageType.REPLY, seqid) + result = hasService_result() + result.success = self._handler.hasService(args.plugin, args.func) + oprot.writeMessageBegin("hasService", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_checkURLs(self, seqid, iprot, oprot): - args = checkURLs_args() + def process_call(self, seqid, iprot, oprot): + args = call_args() args.read(iprot) iprot.readMessageEnd() - result = checkURLs_result() - result.success = self._handler.checkURLs(args.urls) - oprot.writeMessageBegin("checkURLs", TMessageType.REPLY, seqid) + result = call_result() + try: + result.success = self._handler.call(args.plugin, args.func, args.arguments) + except ServiceDoesNotExists, ex: + result.ex = ex + except ServiceException, e: + result.e = e + oprot.writeMessageBegin("call", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_parseURLs(self, seqid, iprot, oprot): - args = parseURLs_args() + def process_getAllInfo(self, seqid, iprot, oprot): + args = getAllInfo_args() args.read(iprot) iprot.readMessageEnd() - result = parseURLs_result() - result.success = self._handler.parseURLs(args.html, args.url) - oprot.writeMessageBegin("parseURLs", TMessageType.REPLY, seqid) + result = getAllInfo_result() + result.success = self._handler.getAllInfo() + oprot.writeMessageBegin("getAllInfo", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_checkOnlineStatus(self, seqid, iprot, oprot): - args = checkOnlineStatus_args() + def process_getInfoByPlugin(self, seqid, iprot, oprot): + args = getInfoByPlugin_args() args.read(iprot) iprot.readMessageEnd() - result = checkOnlineStatus_result() - result.success = self._handler.checkOnlineStatus(args.urls) - oprot.writeMessageBegin("checkOnlineStatus", TMessageType.REPLY, seqid) + result = getInfoByPlugin_result() + result.success = self._handler.getInfoByPlugin(args.plugin) + oprot.writeMessageBegin("getInfoByPlugin", TMessageType.REPLY, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() - def process_checkOnlineStatusContainer(self, seqid, iprot, oprot): - args = checkOnlineStatusContainer_args() - args.read(iprot) - iprot.readMessageEnd() - result = checkOnlineStatusContainer_result() - result.success = self._handler.checkOnlineStatusContainer(args.urls, args.filename, args.data) - oprot.writeMessageBegin("checkOnlineStatusContainer", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_pollResults(self, seqid, iprot, oprot): - args = pollResults_args() - args.read(iprot) - iprot.readMessageEnd() - result = pollResults_result() - result.success = self._handler.pollResults(args.rid) - oprot.writeMessageBegin("pollResults", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +# HELPER FUNCTIONS AND STRUCTURES + +class getServerVersion_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class getServerVersion_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + + thrift_spec = ( + (0, TType.STRING, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + +class statusServer_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class statusServer_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + + thrift_spec = ( + (0, TType.STRUCT, 'success', (ServerStatus, ServerStatus.thrift_spec), None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + +class pauseServer_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class pauseServer_result(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class unpauseServer_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class unpauseServer_result(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class togglePause_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class togglePause_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + +class freeSpace_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class freeSpace_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + + thrift_spec = ( + (0, TType.I64, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + +class kill_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class kill_result(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class restart_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class restart_result(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) - def process_statusDownloads(self, seqid, iprot, oprot): - args = statusDownloads_args() - args.read(iprot) - iprot.readMessageEnd() - result = statusDownloads_result() - result.success = self._handler.statusDownloads() - oprot.writeMessageBegin("statusDownloads", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_getPackageData(self, seqid, iprot, oprot): - args = getPackageData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getPackageData_result() - try: - result.success = self._handler.getPackageData(args.pid) - except PackageDoesNotExists, e: - result.e = e - oprot.writeMessageBegin("getPackageData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class getLog_args(TBase): + """ + Attributes: + - offset + """ - def process_getPackageInfo(self, seqid, iprot, oprot): - args = getPackageInfo_args() - args.read(iprot) - iprot.readMessageEnd() - result = getPackageInfo_result() - try: - result.success = self._handler.getPackageInfo(args.pid) - except PackageDoesNotExists, e: - result.e = e - oprot.writeMessageBegin("getPackageInfo", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + 'offset', + ] - def process_getFileData(self, seqid, iprot, oprot): - args = getFileData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getFileData_result() - try: - result.success = self._handler.getFileData(args.fid) - except FileDoesNotExists, e: - result.e = e - oprot.writeMessageBegin("getFileData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + None, # 0 + (1, TType.I32, 'offset', None, None, ), # 1 + ) - def process_getQueue(self, seqid, iprot, oprot): - args = getQueue_args() - args.read(iprot) - iprot.readMessageEnd() - result = getQueue_result() - result.success = self._handler.getQueue() - oprot.writeMessageBegin("getQueue", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def __init__(self, offset=None,): + self.offset = offset - def process_getCollector(self, seqid, iprot, oprot): - args = getCollector_args() - args.read(iprot) - iprot.readMessageEnd() - result = getCollector_result() - result.success = self._handler.getCollector() - oprot.writeMessageBegin("getCollector", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_getQueueData(self, seqid, iprot, oprot): - args = getQueueData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getQueueData_result() - result.success = self._handler.getQueueData() - oprot.writeMessageBegin("getQueueData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class getLog_result(TBase): + """ + Attributes: + - success + """ - def process_getCollectorData(self, seqid, iprot, oprot): - args = getCollectorData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getCollectorData_result() - result.success = self._handler.getCollectorData() - oprot.writeMessageBegin("getCollectorData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + 'success', + ] - def process_getPackageOrder(self, seqid, iprot, oprot): - args = getPackageOrder_args() - args.read(iprot) - iprot.readMessageEnd() - result = getPackageOrder_result() - result.success = self._handler.getPackageOrder(args.destination) - oprot.writeMessageBegin("getPackageOrder", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + ) - def process_getFileOrder(self, seqid, iprot, oprot): - args = getFileOrder_args() - args.read(iprot) - iprot.readMessageEnd() - result = getFileOrder_result() - result.success = self._handler.getFileOrder(args.pid) - oprot.writeMessageBegin("getFileOrder", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def __init__(self, success=None,): + self.success = success - def process_generateAndAddPackages(self, seqid, iprot, oprot): - args = generateAndAddPackages_args() - args.read(iprot) - iprot.readMessageEnd() - result = generateAndAddPackages_result() - result.success = self._handler.generateAndAddPackages(args.links, args.dest) - oprot.writeMessageBegin("generateAndAddPackages", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_addPackage(self, seqid, iprot, oprot): - args = addPackage_args() - args.read(iprot) - iprot.readMessageEnd() - result = addPackage_result() - result.success = self._handler.addPackage(args.name, args.links, args.dest, args.password) - oprot.writeMessageBegin("addPackage", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class isTimeDownload_args(TBase): - def process_addFiles(self, seqid, iprot, oprot): - args = addFiles_args() - args.read(iprot) - iprot.readMessageEnd() - result = addFiles_result() - self._handler.addFiles(args.pid, args.links) - oprot.writeMessageBegin("addFiles", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + ] - def process_uploadContainer(self, seqid, iprot, oprot): - args = uploadContainer_args() - args.read(iprot) - iprot.readMessageEnd() - result = uploadContainer_result() - self._handler.uploadContainer(args.filename, args.data) - oprot.writeMessageBegin("uploadContainer", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + ) - def process_deleteFiles(self, seqid, iprot, oprot): - args = deleteFiles_args() - args.read(iprot) - iprot.readMessageEnd() - result = deleteFiles_result() - self._handler.deleteFiles(args.fids) - oprot.writeMessageBegin("deleteFiles", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_deletePackages(self, seqid, iprot, oprot): - args = deletePackages_args() - args.read(iprot) - iprot.readMessageEnd() - result = deletePackages_result() - self._handler.deletePackages(args.pids) - oprot.writeMessageBegin("deletePackages", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class isTimeDownload_result(TBase): + """ + Attributes: + - success + """ - def process_pushToQueue(self, seqid, iprot, oprot): - args = pushToQueue_args() - args.read(iprot) - iprot.readMessageEnd() - result = pushToQueue_result() - self._handler.pushToQueue(args.pid) - oprot.writeMessageBegin("pushToQueue", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + 'success', + ] - def process_pullFromQueue(self, seqid, iprot, oprot): - args = pullFromQueue_args() - args.read(iprot) - iprot.readMessageEnd() - result = pullFromQueue_result() - self._handler.pullFromQueue(args.pid) - oprot.writeMessageBegin("pullFromQueue", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + ) - def process_restartPackage(self, seqid, iprot, oprot): - args = restartPackage_args() - args.read(iprot) - iprot.readMessageEnd() - result = restartPackage_result() - self._handler.restartPackage(args.pid) - oprot.writeMessageBegin("restartPackage", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def __init__(self, success=None,): + self.success = success - def process_restartFile(self, seqid, iprot, oprot): - args = restartFile_args() - args.read(iprot) - iprot.readMessageEnd() - result = restartFile_result() - self._handler.restartFile(args.fid) - oprot.writeMessageBegin("restartFile", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_recheckPackage(self, seqid, iprot, oprot): - args = recheckPackage_args() - args.read(iprot) - iprot.readMessageEnd() - result = recheckPackage_result() - self._handler.recheckPackage(args.pid) - oprot.writeMessageBegin("recheckPackage", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class isTimeReconnect_args(TBase): - def process_stopAllDownloads(self, seqid, iprot, oprot): - args = stopAllDownloads_args() - args.read(iprot) - iprot.readMessageEnd() - result = stopAllDownloads_result() - self._handler.stopAllDownloads() - oprot.writeMessageBegin("stopAllDownloads", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + ] + + thrift_spec = ( + ) - def process_stopDownloads(self, seqid, iprot, oprot): - args = stopDownloads_args() - args.read(iprot) - iprot.readMessageEnd() - result = stopDownloads_result() - self._handler.stopDownloads(args.fids) - oprot.writeMessageBegin("stopDownloads", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_setPackageName(self, seqid, iprot, oprot): - args = setPackageName_args() - args.read(iprot) - iprot.readMessageEnd() - result = setPackageName_result() - self._handler.setPackageName(args.pid, args.name) - oprot.writeMessageBegin("setPackageName", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class isTimeReconnect_result(TBase): + """ + Attributes: + - success + """ - def process_movePackage(self, seqid, iprot, oprot): - args = movePackage_args() - args.read(iprot) - iprot.readMessageEnd() - result = movePackage_result() - self._handler.movePackage(args.destination, args.pid) - oprot.writeMessageBegin("movePackage", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + 'success', + ] - def process_moveFiles(self, seqid, iprot, oprot): - args = moveFiles_args() - args.read(iprot) - iprot.readMessageEnd() - result = moveFiles_result() - self._handler.moveFiles(args.fids, args.pid) - oprot.writeMessageBegin("moveFiles", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + ) - def process_orderPackage(self, seqid, iprot, oprot): - args = orderPackage_args() - args.read(iprot) - iprot.readMessageEnd() - result = orderPackage_result() - self._handler.orderPackage(args.pid, args.position) - oprot.writeMessageBegin("orderPackage", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def __init__(self, success=None,): + self.success = success - def process_orderFile(self, seqid, iprot, oprot): - args = orderFile_args() - args.read(iprot) - iprot.readMessageEnd() - result = orderFile_result() - self._handler.orderFile(args.fid, args.position) - oprot.writeMessageBegin("orderFile", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_setPackageData(self, seqid, iprot, oprot): - args = setPackageData_args() - args.read(iprot) - iprot.readMessageEnd() - result = setPackageData_result() - try: - self._handler.setPackageData(args.pid, args.data) - except PackageDoesNotExists, e: - result.e = e - oprot.writeMessageBegin("setPackageData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class toggleReconnect_args(TBase): - def process_deleteFinished(self, seqid, iprot, oprot): - args = deleteFinished_args() - args.read(iprot) - iprot.readMessageEnd() - result = deleteFinished_result() - result.success = self._handler.deleteFinished() - oprot.writeMessageBegin("deleteFinished", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + ] - def process_restartFailed(self, seqid, iprot, oprot): - args = restartFailed_args() - args.read(iprot) - iprot.readMessageEnd() - result = restartFailed_result() - self._handler.restartFailed() - oprot.writeMessageBegin("restartFailed", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + ) - def process_getEvents(self, seqid, iprot, oprot): - args = getEvents_args() - args.read(iprot) - iprot.readMessageEnd() - result = getEvents_result() - result.success = self._handler.getEvents(args.uuid) - oprot.writeMessageBegin("getEvents", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_getAccounts(self, seqid, iprot, oprot): - args = getAccounts_args() - args.read(iprot) - iprot.readMessageEnd() - result = getAccounts_result() - result.success = self._handler.getAccounts(args.refresh) - oprot.writeMessageBegin("getAccounts", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class toggleReconnect_result(TBase): + """ + Attributes: + - success + """ - def process_getAccountTypes(self, seqid, iprot, oprot): - args = getAccountTypes_args() - args.read(iprot) - iprot.readMessageEnd() - result = getAccountTypes_result() - result.success = self._handler.getAccountTypes() - oprot.writeMessageBegin("getAccountTypes", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + 'success', + ] - def process_updateAccount(self, seqid, iprot, oprot): - args = updateAccount_args() - args.read(iprot) - iprot.readMessageEnd() - result = updateAccount_result() - self._handler.updateAccount(args.plugin, args.account, args.password, args.options) - oprot.writeMessageBegin("updateAccount", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + ) - def process_removeAccount(self, seqid, iprot, oprot): - args = removeAccount_args() - args.read(iprot) - iprot.readMessageEnd() - result = removeAccount_result() - self._handler.removeAccount(args.plugin, args.account) - oprot.writeMessageBegin("removeAccount", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + def __init__(self, success=None,): + self.success = success - def process_login(self, seqid, iprot, oprot): - args = login_args() - args.read(iprot) - iprot.readMessageEnd() - result = login_result() - result.success = self._handler.login(args.username, args.password) - oprot.writeMessageBegin("login", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_getUserData(self, seqid, iprot, oprot): - args = getUserData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getUserData_result() - try: - result.success = self._handler.getUserData(args.username, args.password) - except UserDoesNotExists, ex: - result.ex = ex - oprot.writeMessageBegin("getUserData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class scanDownloadFolder_args(TBase): - def process_getAllUserData(self, seqid, iprot, oprot): - args = getAllUserData_args() - args.read(iprot) - iprot.readMessageEnd() - result = getAllUserData_result() - result.success = self._handler.getAllUserData() - oprot.writeMessageBegin("getAllUserData", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + ] - def process_getServices(self, seqid, iprot, oprot): - args = getServices_args() - args.read(iprot) - iprot.readMessageEnd() - result = getServices_result() - result.success = self._handler.getServices() - oprot.writeMessageBegin("getServices", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + ) - def process_hasService(self, seqid, iprot, oprot): - args = hasService_args() - args.read(iprot) - iprot.readMessageEnd() - result = hasService_result() - result.success = self._handler.hasService(args.plugin, args.func) - oprot.writeMessageBegin("hasService", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_call(self, seqid, iprot, oprot): - args = call_args() - args.read(iprot) - iprot.readMessageEnd() - result = call_result() - try: - result.success = self._handler.call(args.info) - except ServiceDoesNotExists, ex: - result.ex = ex - except ServiceException, e: - result.e = e - oprot.writeMessageBegin("call", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class scanDownloadFolder_result(TBase): - def process_getAllInfo(self, seqid, iprot, oprot): - args = getAllInfo_args() - args.read(iprot) - iprot.readMessageEnd() - result = getAllInfo_result() - result.success = self._handler.getAllInfo() - oprot.writeMessageBegin("getAllInfo", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + __slots__ = [ + ] - def process_getInfoByPlugin(self, seqid, iprot, oprot): - args = getInfoByPlugin_args() - args.read(iprot) - iprot.readMessageEnd() - result = getInfoByPlugin_result() - result.success = self._handler.getInfoByPlugin(args.plugin) - oprot.writeMessageBegin("getInfoByPlugin", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() + thrift_spec = ( + ) - def process_isCaptchaWaiting(self, seqid, iprot, oprot): - args = isCaptchaWaiting_args() - args.read(iprot) - iprot.readMessageEnd() - result = isCaptchaWaiting_result() - result.success = self._handler.isCaptchaWaiting() - oprot.writeMessageBegin("isCaptchaWaiting", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_getCaptchaTask(self, seqid, iprot, oprot): - args = getCaptchaTask_args() - args.read(iprot) - iprot.readMessageEnd() - result = getCaptchaTask_result() - result.success = self._handler.getCaptchaTask(args.exclusive) - oprot.writeMessageBegin("getCaptchaTask", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class getProgressInfo_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) - def process_getCaptchaTaskStatus(self, seqid, iprot, oprot): - args = getCaptchaTaskStatus_args() - args.read(iprot) - iprot.readMessageEnd() - result = getCaptchaTaskStatus_result() - result.success = self._handler.getCaptchaTaskStatus(args.tid) - oprot.writeMessageBegin("getCaptchaTaskStatus", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() - def process_setCaptchaResult(self, seqid, iprot, oprot): - args = setCaptchaResult_args() - args.read(iprot) - iprot.readMessageEnd() - result = setCaptchaResult_result() - self._handler.setCaptchaResult(args.tid, args.result) - oprot.writeMessageBegin("setCaptchaResult", TMessageType.REPLY, seqid) - result.write(oprot) - oprot.writeMessageEnd() - oprot.trans.flush() +class getProgressInfo_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + thrift_spec = ( + (0, TType.LIST, 'success', (TType.STRUCT,(ProgressInfo, ProgressInfo.thrift_spec)), None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success -# HELPER FUNCTIONS AND STRUCTURES class getConfigValue_args(TBase): """ @@ -3518,16 +4555,34 @@ class configureSection_result(TBase): self.success = success -class pauseServer_args(TBase): +class setConfigHandler_args(TBase): + """ + Attributes: + - plugin + - iid + - value + """ __slots__ = [ + 'plugin', + 'iid', + 'value', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'plugin', None, None, ), # 1 + (2, TType.I32, 'iid', None, None, ), # 2 + (3, TType.STRING, 'value', None, None, ), # 3 ) + def __init__(self, plugin=None, iid=None, value=None,): + self.plugin = plugin + self.iid = iid + self.value = value -class pauseServer_result(TBase): + +class setConfigHandler_result(TBase): __slots__ = [ ] @@ -3536,34 +4591,67 @@ class pauseServer_result(TBase): ) -class unpauseServer_args(TBase): +class checkURLs_args(TBase): + """ + Attributes: + - urls + """ __slots__ = [ + 'urls', ] thrift_spec = ( + None, # 0 + (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 ) + def __init__(self, urls=None,): + self.urls = urls -class unpauseServer_result(TBase): + +class checkURLs_result(TBase): + """ + Attributes: + - success + """ __slots__ = [ + 'success', ] thrift_spec = ( + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 ) + def __init__(self, success=None,): + self.success = success -class togglePause_args(TBase): + +class parseURLs_args(TBase): + """ + Attributes: + - html + - url + """ __slots__ = [ + 'html', + 'url', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'html', None, None, ), # 1 + (2, TType.STRING, 'url', None, None, ), # 2 ) + def __init__(self, html=None, url=None,): + self.html = html + self.url = url + -class togglePause_result(TBase): +class parseURLs_result(TBase): """ Attributes: - success @@ -3574,23 +4662,33 @@ class togglePause_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class statusServer_args(TBase): +class checkOnlineStatus_args(TBase): + """ + Attributes: + - urls + """ __slots__ = [ + 'urls', ] thrift_spec = ( + None, # 0 + (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 ) + def __init__(self, urls=None,): + self.urls = urls -class statusServer_result(TBase): + +class checkOnlineStatus_result(TBase): """ Attributes: - success @@ -3601,23 +4699,41 @@ class statusServer_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (ServerStatus, ServerStatus.thrift_spec), None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class freeSpace_args(TBase): +class checkOnlineStatusContainer_args(TBase): + """ + Attributes: + - urls + - filename + - data + """ __slots__ = [ + 'urls', + 'filename', + 'data', ] thrift_spec = ( + None, # 0 + (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 + (2, TType.STRING, 'filename', None, None, ), # 2 + (3, TType.STRING, 'data', None, None, ), # 3 ) + def __init__(self, urls=None, filename=None, data=None,): + self.urls = urls + self.filename = filename + self.data = data + -class freeSpace_result(TBase): +class checkOnlineStatusContainer_result(TBase): """ Attributes: - success @@ -3628,23 +4744,33 @@ class freeSpace_result(TBase): ] thrift_spec = ( - (0, TType.I64, 'success', None, None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getServerVersion_args(TBase): +class pollResults_args(TBase): + """ + Attributes: + - rid + """ __slots__ = [ + 'rid', ] thrift_spec = ( + None, # 0 + (1, TType.I32, 'rid', None, None, ), # 1 ) + def __init__(self, rid=None,): + self.rid = rid -class getServerVersion_result(TBase): + +class pollResults_result(TBase): """ Attributes: - success @@ -3655,69 +4781,111 @@ class getServerVersion_result(TBase): ] thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 + (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class kill_args(TBase): +class generatePackages_args(TBase): + """ + Attributes: + - links + """ __slots__ = [ + 'links', ] thrift_spec = ( + None, # 0 + (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 ) + def __init__(self, links=None,): + self.links = links -class kill_result(TBase): + +class generatePackages_result(TBase): + """ + Attributes: + - success + """ __slots__ = [ + 'success', ] thrift_spec = ( + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 ) + def __init__(self, success=None,): + self.success = success + -class restart_args(TBase): +class generateAndAddPackages_args(TBase): + """ + Attributes: + - links + - paused + """ __slots__ = [ + 'links', + 'paused', ] thrift_spec = ( + None, # 0 + (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 + (2, TType.BOOL, 'paused', None, None, ), # 2 ) + def __init__(self, links=None, paused=None,): + self.links = links + self.paused = paused + -class restart_result(TBase): +class generateAndAddPackages_result(TBase): + """ + Attributes: + - success + """ __slots__ = [ + 'success', ] thrift_spec = ( + (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 ) + def __init__(self, success=None,): + self.success = success -class getLog_args(TBase): + +class autoAddLinks_args(TBase): """ Attributes: - - offset + - links """ __slots__ = [ - 'offset', + 'links', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'offset', None, None, ), # 1 + (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 ) - def __init__(self, offset=None,): - self.offset = offset + def __init__(self, links=None,): + self.links = links -class getLog_result(TBase): +class autoAddLinks_result(TBase): """ Attributes: - success @@ -3728,23 +4896,102 @@ class getLog_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRING,None), None, ), # 0 + (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class isTimeDownload_args(TBase): +class createPackage_args(TBase): + """ + Attributes: + - name + - folder + - root + - password + - site + - comment + - paused + """ __slots__ = [ + 'name', + 'folder', + 'root', + 'password', + 'site', + 'comment', + 'paused', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.STRING, 'folder', None, None, ), # 2 + (3, TType.I32, 'root', None, None, ), # 3 + (4, TType.STRING, 'password', None, None, ), # 4 + (5, TType.STRING, 'site', None, None, ), # 5 + (6, TType.STRING, 'comment', None, None, ), # 6 + (7, TType.BOOL, 'paused', None, None, ), # 7 ) + def __init__(self, name=None, folder=None, root=None, password=None, site=None, comment=None, paused=None,): + self.name = name + self.folder = folder + self.root = root + self.password = password + self.site = site + self.comment = comment + self.paused = paused -class isTimeDownload_result(TBase): + +class createPackage_result(TBase): + """ + Attributes: + - success + """ + + __slots__ = [ + 'success', + ] + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + +class addPackage_args(TBase): + """ + Attributes: + - name + - links + - password + """ + + __slots__ = [ + 'name', + 'links', + 'password', + ] + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 + (3, TType.STRING, 'password', None, None, ), # 3 + ) + + def __init__(self, name=None, links=None, password=None,): + self.name = name + self.links = links + self.password = password + + +class addPackage_result(TBase): """ Attributes: - success @@ -3755,23 +5002,45 @@ class isTimeDownload_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.I32, 'success', None, None, ), # 0 ) def __init__(self, success=None,): self.success = success -class isTimeReconnect_args(TBase): +class addPackageP_args(TBase): + """ + Attributes: + - name + - links + - password + - paused + """ __slots__ = [ + 'name', + 'links', + 'password', + 'paused', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 + (3, TType.STRING, 'password', None, None, ), # 3 + (4, TType.BOOL, 'paused', None, None, ), # 4 ) + def __init__(self, name=None, links=None, password=None, paused=None,): + self.name = name + self.links = links + self.password = password + self.paused = paused + -class isTimeReconnect_result(TBase): +class addPackageP_result(TBase): """ Attributes: - success @@ -3782,23 +5051,49 @@ class isTimeReconnect_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.I32, 'success', None, None, ), # 0 ) def __init__(self, success=None,): self.success = success -class toggleReconnect_args(TBase): +class addPackageChild_args(TBase): + """ + Attributes: + - name + - links + - password + - root + - paused + """ __slots__ = [ + 'name', + 'links', + 'password', + 'root', + 'paused', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 + (3, TType.STRING, 'password', None, None, ), # 3 + (4, TType.I32, 'root', None, None, ), # 4 + (5, TType.BOOL, 'paused', None, None, ), # 5 ) + def __init__(self, name=None, links=None, password=None, root=None, paused=None,): + self.name = name + self.links = links + self.password = password + self.root = root + self.paused = paused + -class toggleReconnect_result(TBase): +class addPackageChild_result(TBase): """ Attributes: - success @@ -3809,33 +5104,37 @@ class toggleReconnect_result(TBase): ] thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 + (0, TType.I32, 'success', None, None, ), # 0 ) def __init__(self, success=None,): self.success = success -class generatePackages_args(TBase): +class uploadContainer_args(TBase): """ Attributes: - - links + - filename + - data """ __slots__ = [ - 'links', + 'filename', + 'data', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 + (1, TType.STRING, 'filename', None, None, ), # 1 + (2, TType.STRING, 'data', None, None, ), # 2 ) - def __init__(self, links=None,): - self.links = links + def __init__(self, filename=None, data=None,): + self.filename = filename + self.data = data -class generatePackages_result(TBase): +class uploadContainer_result(TBase): """ Attributes: - success @@ -3846,156 +5145,121 @@ class generatePackages_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 + (0, TType.I32, 'success', None, None, ), # 0 ) def __init__(self, success=None,): self.success = success -class checkURLs_args(TBase): +class addLinks_args(TBase): """ Attributes: - - urls + - pid + - links """ __slots__ = [ - 'urls', + 'pid', + 'links', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 + (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 ) - def __init__(self, urls=None,): - self.urls = urls + def __init__(self, pid=None, links=None,): + self.pid = pid + self.links = links -class checkURLs_result(TBase): +class addLinks_result(TBase): """ Attributes: - - success + - e """ __slots__ = [ - 'success', + 'e', ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 + None, # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None,): - self.success = success + def __init__(self, e=None,): + self.e = e -class parseURLs_args(TBase): +class deleteFiles_args(TBase): """ Attributes: - - html - - url + - fids """ __slots__ = [ - 'html', - 'url', + 'fids', ] thrift_spec = ( None, # 0 - (1, TType.STRING, 'html', None, None, ), # 1 - (2, TType.STRING, 'url', None, None, ), # 2 + (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 ) - def __init__(self, html=None, url=None,): - self.html = html - self.url = url + def __init__(self, fids=None,): + self.fids = fids -class parseURLs_result(TBase): - """ - Attributes: - - success - """ +class deleteFiles_result(TBase): __slots__ = [ - 'success', ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 0 ) - def __init__(self, success=None,): - self.success = success - -class checkOnlineStatus_args(TBase): +class deletePackages_args(TBase): """ Attributes: - - urls + - pids """ __slots__ = [ - 'urls', + 'pids', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 + (1, TType.LIST, 'pids', (TType.I32,None), None, ), # 1 ) - def __init__(self, urls=None,): - self.urls = urls + def __init__(self, pids=None,): + self.pids = pids -class checkOnlineStatus_result(TBase): - """ - Attributes: - - success - """ +class deletePackages_result(TBase): __slots__ = [ - 'success', ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 ) - def __init__(self, success=None,): - self.success = success - -class checkOnlineStatusContainer_args(TBase): - """ - Attributes: - - urls - - filename - - data - """ +class getCollector_args(TBase): __slots__ = [ - 'urls', - 'filename', - 'data', ] thrift_spec = ( - None, # 0 - (1, TType.LIST, 'urls', (TType.STRING,None), None, ), # 1 - (2, TType.STRING, 'filename', None, None, ), # 2 - (3, TType.STRING, 'data', None, None, ), # 3 ) - def __init__(self, urls=None, filename=None, data=None,): - self.urls = urls - self.filename = filename - self.data = data - -class checkOnlineStatusContainer_result(TBase): +class getCollector_result(TBase): """ Attributes: - success @@ -4006,60 +5270,65 @@ class checkOnlineStatusContainer_result(TBase): ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT,(LinkStatus, LinkStatus.thrift_spec)), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class pollResults_args(TBase): +class addToCollector_args(TBase): """ Attributes: - - rid + - links """ __slots__ = [ - 'rid', + 'links', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'rid', None, None, ), # 1 + (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 ) - def __init__(self, rid=None,): - self.rid = rid + def __init__(self, links=None,): + self.links = links -class pollResults_result(TBase): - """ - Attributes: - - success - """ +class addToCollector_result(TBase): __slots__ = [ - 'success', ] thrift_spec = ( - (0, TType.STRUCT, 'success', (OnlineCheck, OnlineCheck.thrift_spec), None, ), # 0 ) - def __init__(self, success=None,): - self.success = success - -class statusDownloads_args(TBase): +class addFromCollector_args(TBase): + """ + Attributes: + - name + - paused + """ __slots__ = [ + 'name', + 'paused', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.BOOL, 'paused', None, None, ), # 2 ) + def __init__(self, name=None, paused=None,): + self.name = name + self.paused = paused + -class statusDownloads_result(TBase): +class addFromCollector_result(TBase): """ Attributes: - success @@ -4070,137 +5339,102 @@ class statusDownloads_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(DownloadInfo, DownloadInfo.thrift_spec)), None, ), # 0 + (0, TType.I32, 'success', None, None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getPackageData_args(TBase): +class renameCollPack_args(TBase): """ Attributes: - - pid + - name + - new_name """ __slots__ = [ - 'pid', + 'name', + 'new_name', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.STRING, 'name', None, None, ), # 1 + (2, TType.STRING, 'new_name', None, None, ), # 2 ) - def __init__(self, pid=None,): - self.pid = pid + def __init__(self, name=None, new_name=None,): + self.name = name + self.new_name = new_name -class getPackageData_result(TBase): - """ - Attributes: - - success - - e - """ +class renameCollPack_result(TBase): __slots__ = [ - 'success', - 'e', ] thrift_spec = ( - (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None, e=None,): - self.success = success - self.e = e - -class getPackageInfo_args(TBase): +class deleteCollPack_args(TBase): """ Attributes: - - pid + - name """ __slots__ = [ - 'pid', + 'name', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.STRING, 'name', None, None, ), # 1 ) - def __init__(self, pid=None,): - self.pid = pid + def __init__(self, name=None,): + self.name = name -class getPackageInfo_result(TBase): - """ - Attributes: - - success - - e - """ +class deleteCollPack_result(TBase): __slots__ = [ - 'success', - 'e', ] thrift_spec = ( - (0, TType.STRUCT, 'success', (PackageData, PackageData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None, e=None,): - self.success = success - self.e = e - -class getFileData_args(TBase): +class deleteCollLink_args(TBase): """ Attributes: - - fid + - url """ __slots__ = [ - 'fid', + 'url', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 + (1, TType.STRING, 'url', None, None, ), # 1 ) - def __init__(self, fid=None,): - self.fid = fid + def __init__(self, url=None,): + self.url = url -class getFileData_result(TBase): - """ - Attributes: - - success - - e - """ +class deleteCollLink_result(TBase): __slots__ = [ - 'success', - 'e', ] thrift_spec = ( - (0, TType.STRUCT, 'success', (FileData, FileData.thrift_spec), None, ), # 0 - (1, TType.STRUCT, 'e', (FileDoesNotExists, FileDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None, e=None,): - self.success = success - self.e = e - -class getQueue_args(TBase): +class getAllFiles_args(TBase): __slots__ = [ ] @@ -4209,7 +5443,7 @@ class getQueue_args(TBase): ) -class getQueue_result(TBase): +class getAllFiles_result(TBase): """ Attributes: - success @@ -4220,14 +5454,14 @@ class getQueue_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageView, PackageView.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getCollector_args(TBase): +class getAllUnfinishedFiles_args(TBase): __slots__ = [ ] @@ -4236,7 +5470,7 @@ class getCollector_args(TBase): ) -class getCollector_result(TBase): +class getAllUnfinishedFiles_result(TBase): """ Attributes: - success @@ -4247,23 +5481,37 @@ class getCollector_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageView, PackageView.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getQueueData_args(TBase): +class getFileTree_args(TBase): + """ + Attributes: + - pid + - full + """ __slots__ = [ + 'pid', + 'full', ] thrift_spec = ( + None, # 0 + (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.BOOL, 'full', None, None, ), # 2 ) + def __init__(self, pid=None, full=None,): + self.pid = pid + self.full = full + -class getQueueData_result(TBase): +class getFileTree_result(TBase): """ Attributes: - success @@ -4274,23 +5522,37 @@ class getQueueData_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageView, PackageView.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getCollectorData_args(TBase): +class getUnfinishedFileTree_args(TBase): + """ + Attributes: + - pid + - full + """ __slots__ = [ + 'pid', + 'full', ] thrift_spec = ( + None, # 0 + (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.BOOL, 'full', None, None, ), # 2 ) + def __init__(self, pid=None, full=None,): + self.pid = pid + self.full = full + -class getCollectorData_result(TBase): +class getUnfinishedFileTree_result(TBase): """ Attributes: - success @@ -4301,33 +5563,33 @@ class getCollectorData_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.STRUCT,(PackageData, PackageData.thrift_spec)), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageView, PackageView.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getPackageOrder_args(TBase): +class getPackageContent_args(TBase): """ Attributes: - - destination + - pid """ __slots__ = [ - 'destination', + 'pid', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'destination', None, None, ), # 1 + (1, TType.I32, 'pid', None, None, ), # 1 ) - def __init__(self, destination=None,): - self.destination = destination + def __init__(self, pid=None,): + self.pid = pid -class getPackageOrder_result(TBase): +class getPackageContent_result(TBase): """ Attributes: - success @@ -4338,14 +5600,14 @@ class getPackageOrder_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.I16,None,TType.I32,None), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageView, PackageView.thrift_spec), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class getFileOrder_args(TBase): +class getPackageInfo_args(TBase): """ Attributes: - pid @@ -4364,97 +5626,89 @@ class getFileOrder_args(TBase): self.pid = pid -class getFileOrder_result(TBase): +class getPackageInfo_result(TBase): """ Attributes: - success + - e """ __slots__ = [ 'success', + 'e', ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.I16,None,TType.I32,None), None, ), # 0 + (0, TType.STRUCT, 'success', (PackageInfo, PackageInfo.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None,): + def __init__(self, success=None, e=None,): self.success = success + self.e = e -class generateAndAddPackages_args(TBase): +class getFileInfo_args(TBase): """ Attributes: - - links - - dest + - fid """ __slots__ = [ - 'links', - 'dest', + 'fid', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'links', (TType.STRING,None), None, ), # 1 - (2, TType.I32, 'dest', None, None, ), # 2 + (1, TType.I32, 'fid', None, None, ), # 1 ) - def __init__(self, links=None, dest=None,): - self.links = links - self.dest = dest + def __init__(self, fid=None,): + self.fid = fid -class generateAndAddPackages_result(TBase): +class getFileInfo_result(TBase): """ Attributes: - success + - e """ __slots__ = [ 'success', + 'e', ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 + (0, TType.STRUCT, 'success', (FileInfo, FileInfo.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'e', (FileDoesNotExists, FileDoesNotExists.thrift_spec), None, ), # 1 ) - def __init__(self, success=None,): + def __init__(self, success=None, e=None,): self.success = success + self.e = e -class addPackage_args(TBase): +class findFiles_args(TBase): """ Attributes: - - name - - links - - dest - - password + - pattern """ __slots__ = [ - 'name', - 'links', - 'dest', - 'password', + 'pattern', ] thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 - (3, TType.I32, 'dest', None, None, ), # 3 - (4, TType.STRING, 'password', None, None, ), # 4 + (1, TType.STRING, 'pattern', None, None, ), # 1 ) - def __init__(self, name=None, links=None, dest=None, password=None,): - self.name = name - self.links = links - self.dest = dest - self.password = password + def __init__(self, pattern=None,): + self.pattern = pattern -class addPackage_result(TBase): +class findFiles_result(TBase): """ Attributes: - success @@ -4465,37 +5719,33 @@ class addPackage_result(TBase): ] thrift_spec = ( - (0, TType.I32, 'success', None, None, ), # 0 + (0, TType.MAP, 'success', (TType.I32,None,TType.STRUCT,(FileInfo, FileInfo.thrift_spec)), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class addFiles_args(TBase): +class restartPackage_args(TBase): """ Attributes: - pid - - links """ __slots__ = [ 'pid', - 'links', ] thrift_spec = ( None, # 0 (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.LIST, 'links', (TType.STRING,None), None, ), # 2 ) - def __init__(self, pid=None, links=None,): + def __init__(self, pid=None,): self.pid = pid - self.links = links -class addFiles_result(TBase): +class restartPackage_result(TBase): __slots__ = [ ] @@ -4504,30 +5754,26 @@ class addFiles_result(TBase): ) -class uploadContainer_args(TBase): +class restartFile_args(TBase): """ Attributes: - - filename - - data + - fid """ __slots__ = [ - 'filename', - 'data', + 'fid', ] thrift_spec = ( None, # 0 - (1, TType.STRING, 'filename', None, None, ), # 1 - (2, TType.STRING, 'data', None, None, ), # 2 + (1, TType.I32, 'fid', None, None, ), # 1 ) - def __init__(self, filename=None, data=None,): - self.filename = filename - self.data = data + def __init__(self, fid=None,): + self.fid = fid -class uploadContainer_result(TBase): +class restartFile_result(TBase): __slots__ = [ ] @@ -4536,26 +5782,26 @@ class uploadContainer_result(TBase): ) -class deleteFiles_args(TBase): +class recheckPackage_args(TBase): """ Attributes: - - fids + - pid """ __slots__ = [ - 'fids', + 'pid', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 + (1, TType.I32, 'pid', None, None, ), # 1 ) - def __init__(self, fids=None,): - self.fids = fids + def __init__(self, pid=None,): + self.pid = pid -class deleteFiles_result(TBase): +class recheckPackage_result(TBase): __slots__ = [ ] @@ -4564,26 +5810,26 @@ class deleteFiles_result(TBase): ) -class deletePackages_args(TBase): +class stopDownloads_args(TBase): """ Attributes: - - pids + - fids """ __slots__ = [ - 'pids', + 'fids', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'pids', (TType.I32,None), None, ), # 1 + (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 ) - def __init__(self, pids=None,): - self.pids = pids + def __init__(self, fids=None,): + self.fids = fids -class deletePackages_result(TBase): +class stopDownloads_result(TBase): __slots__ = [ ] @@ -4592,26 +5838,34 @@ class deletePackages_result(TBase): ) -class pushToQueue_args(TBase): - """ - Attributes: - - pid - """ +class stopAllDownloads_args(TBase): __slots__ = [ - 'pid', ] thrift_spec = ( - None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 ) - def __init__(self, pid=None,): - self.pid = pid +class stopAllDownloads_result(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) + + +class restartFailed_args(TBase): + + __slots__ = [ + ] + + thrift_spec = ( + ) -class pushToQueue_result(TBase): + +class restartFailed_result(TBase): __slots__ = [ ] @@ -4620,188 +5874,291 @@ class pushToQueue_result(TBase): ) -class pullFromQueue_args(TBase): +class setFilePaused_args(TBase): """ Attributes: - - pid + - fid + - paused """ __slots__ = [ - 'pid', + 'fid', + 'paused', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 + (1, TType.I32, 'fid', None, None, ), # 1 + (2, TType.BOOL, 'paused', None, None, ), # 2 ) - def __init__(self, pid=None,): - self.pid = pid + def __init__(self, fid=None, paused=None,): + self.fid = fid + self.paused = paused -class pullFromQueue_result(TBase): +class setFilePaused_result(TBase): + """ + Attributes: + - e + """ __slots__ = [ + 'e', ] thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'e', (FileDoesNotExists, FileDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, e=None,): + self.e = e -class restartPackage_args(TBase): + +class setPackagePaused_args(TBase): """ Attributes: - pid + - paused """ __slots__ = [ 'pid', + 'paused', ] thrift_spec = ( None, # 0 (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.BOOL, 'paused', None, None, ), # 2 ) - def __init__(self, pid=None,): + def __init__(self, pid=None, paused=None,): self.pid = pid + self.paused = paused -class restartPackage_result(TBase): +class setPackagePaused_result(TBase): + """ + Attributes: + - e + """ __slots__ = [ + 'e', ] thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, e=None,): + self.e = e -class restartFile_args(TBase): + +class setPackageFolder_args(TBase): """ Attributes: - - fid + - pid + - path """ __slots__ = [ - 'fid', + 'pid', + 'path', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 + (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.STRING, 'path', None, None, ), # 2 ) - def __init__(self, fid=None,): - self.fid = fid + def __init__(self, pid=None, path=None,): + self.pid = pid + self.path = path -class restartFile_result(TBase): +class setPackageFolder_result(TBase): + """ + Attributes: + - success + - e + """ __slots__ = [ + 'success', + 'e', ] thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, success=None, e=None,): + self.success = success + self.e = e -class recheckPackage_args(TBase): + +class setPackageData_args(TBase): """ Attributes: - pid + - data """ __slots__ = [ 'pid', + 'data', ] thrift_spec = ( None, # 0 (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.MAP, 'data', (TType.STRING,None,TType.STRING,None), None, ), # 2 ) - def __init__(self, pid=None,): + def __init__(self, pid=None, data=None,): self.pid = pid + self.data = data -class recheckPackage_result(TBase): +class setPackageData_result(TBase): + """ + Attributes: + - e + """ __slots__ = [ + 'e', ] thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, e=None,): + self.e = e -class stopAllDownloads_args(TBase): + +class movePackage_args(TBase): + """ + Attributes: + - pid + - root + """ __slots__ = [ + 'pid', + 'root', ] thrift_spec = ( + None, # 0 + (1, TType.I32, 'pid', None, None, ), # 1 + (2, TType.I32, 'root', None, None, ), # 2 ) + def __init__(self, pid=None, root=None,): + self.pid = pid + self.root = root + -class stopAllDownloads_result(TBase): +class movePackage_result(TBase): + """ + Attributes: + - success + - e + """ __slots__ = [ + 'success', + 'e', ] thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, success=None, e=None,): + self.success = success + self.e = e + -class stopDownloads_args(TBase): +class moveFiles_args(TBase): """ Attributes: - fids + - pid """ __slots__ = [ 'fids', + 'pid', ] thrift_spec = ( None, # 0 (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 + (2, TType.I32, 'pid', None, None, ), # 2 ) - def __init__(self, fids=None,): + def __init__(self, fids=None, pid=None,): self.fids = fids + self.pid = pid -class stopDownloads_result(TBase): +class moveFiles_result(TBase): + """ + Attributes: + - success + - e + """ __slots__ = [ + 'success', + 'e', ] thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 ) + def __init__(self, success=None, e=None,): + self.success = success + self.e = e + -class setPackageName_args(TBase): +class orderPackage_args(TBase): """ Attributes: - - pid - - name + - pids + - position """ __slots__ = [ - 'pid', - 'name', + 'pids', + 'position', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.STRING, 'name', None, None, ), # 2 + (1, TType.LIST, 'pids', (TType.I32,None), None, ), # 1 + (2, TType.I16, 'position', None, None, ), # 2 ) - def __init__(self, pid=None, name=None,): - self.pid = pid - self.name = name + def __init__(self, pids=None, position=None,): + self.pids = pids + self.position = position -class setPackageName_result(TBase): +class orderPackage_result(TBase): __slots__ = [ ] @@ -4810,30 +6167,34 @@ class setPackageName_result(TBase): ) -class movePackage_args(TBase): +class orderFiles_args(TBase): """ Attributes: - - destination + - fids - pid + - position """ __slots__ = [ - 'destination', + 'fids', 'pid', + 'position', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'destination', None, None, ), # 1 + (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 (2, TType.I32, 'pid', None, None, ), # 2 + (3, TType.I16, 'position', None, None, ), # 3 ) - def __init__(self, destination=None, pid=None,): - self.destination = destination + def __init__(self, fids=None, pid=None, position=None,): + self.fids = fids self.pid = pid + self.position = position -class movePackage_result(TBase): +class orderFiles_result(TBase): __slots__ = [ ] @@ -4842,94 +6203,104 @@ class movePackage_result(TBase): ) -class moveFiles_args(TBase): +class isInteractionWaiting_args(TBase): """ Attributes: - - fids - - pid + - mode """ __slots__ = [ - 'fids', - 'pid', + 'mode', ] thrift_spec = ( None, # 0 - (1, TType.LIST, 'fids', (TType.I32,None), None, ), # 1 - (2, TType.I32, 'pid', None, None, ), # 2 + (1, TType.I16, 'mode', None, None, ), # 1 ) - def __init__(self, fids=None, pid=None,): - self.fids = fids - self.pid = pid + def __init__(self, mode=None,): + self.mode = mode -class moveFiles_result(TBase): +class isInteractionWaiting_result(TBase): + """ + Attributes: + - success + """ __slots__ = [ + 'success', ] thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 ) + def __init__(self, success=None,): + self.success = success -class orderPackage_args(TBase): + +class getInteractionTask_args(TBase): """ Attributes: - - pid - - position + - mode """ __slots__ = [ - 'pid', - 'position', + 'mode', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.I16, 'position', None, None, ), # 2 + (1, TType.I16, 'mode', None, None, ), # 1 ) - def __init__(self, pid=None, position=None,): - self.pid = pid - self.position = position + def __init__(self, mode=None,): + self.mode = mode -class orderPackage_result(TBase): +class getInteractionTask_result(TBase): + """ + Attributes: + - success + """ __slots__ = [ + 'success', ] thrift_spec = ( + (0, TType.STRUCT, 'success', (InteractionTask, InteractionTask.thrift_spec), None, ), # 0 ) + def __init__(self, success=None,): + self.success = success + -class orderFile_args(TBase): +class setInteractionResult_args(TBase): """ Attributes: - - fid - - position + - iid + - result """ __slots__ = [ - 'fid', - 'position', + 'iid', + 'result', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 - (2, TType.I16, 'position', None, None, ), # 2 + (1, TType.I32, 'iid', None, None, ), # 1 + (2, TType.STRING, 'result', None, None, ), # 2 ) - def __init__(self, fid=None, position=None,): - self.fid = fid - self.position = position + def __init__(self, iid=None, result=None,): + self.iid = iid + self.result = result -class orderFile_result(TBase): +class setInteractionResult_result(TBase): __slots__ = [ ] @@ -4938,49 +6309,48 @@ class orderFile_result(TBase): ) -class setPackageData_args(TBase): +class generateDownloadLink_args(TBase): """ Attributes: - - pid - - data + - fid + - timeout """ __slots__ = [ - 'pid', - 'data', + 'fid', + 'timeout', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'pid', None, None, ), # 1 - (2, TType.MAP, 'data', (TType.STRING,None,TType.STRING,None), None, ), # 2 + (1, TType.I32, 'fid', None, None, ), # 1 + (2, TType.I16, 'timeout', None, None, ), # 2 ) - def __init__(self, pid=None, data=None,): - self.pid = pid - self.data = data + def __init__(self, fid=None, timeout=None,): + self.fid = fid + self.timeout = timeout -class setPackageData_result(TBase): +class generateDownloadLink_result(TBase): """ Attributes: - - e + - success """ __slots__ = [ - 'e', + 'success', ] thrift_spec = ( - None, # 0 - (1, TType.STRUCT, 'e', (PackageDoesNotExists, PackageDoesNotExists.thrift_spec), None, ), # 1 + (0, TType.STRING, 'success', None, None, ), # 0 ) - def __init__(self, e=None,): - self.e = e + def __init__(self, success=None,): + self.success = success -class deleteFinished_args(TBase): +class getAddonHandler_args(TBase): __slots__ = [ ] @@ -4989,7 +6359,7 @@ class deleteFinished_args(TBase): ) -class deleteFinished_result(TBase): +class getAddonHandler_result(TBase): """ Attributes: - success @@ -5000,23 +6370,41 @@ class deleteFinished_result(TBase): ] thrift_spec = ( - (0, TType.LIST, 'success', (TType.I32,None), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRUCT,(AddonService, AddonService.thrift_spec))), None, ), # 0 ) def __init__(self, success=None,): self.success = success -class restartFailed_args(TBase): +class callAddonHandler_args(TBase): + """ + Attributes: + - plugin + - func + - pid_or_fid + """ __slots__ = [ + 'plugin', + 'func', + 'pid_or_fid', ] thrift_spec = ( + None, # 0 + (1, TType.STRING, 'plugin', None, None, ), # 1 + (2, TType.STRING, 'func', None, None, ), # 2 + (3, TType.I32, 'pid_or_fid', None, None, ), # 3 ) + def __init__(self, plugin=None, func=None, pid_or_fid=None,): + self.plugin = plugin + self.func = func + self.pid_or_fid = pid_or_fid + -class restartFailed_result(TBase): +class callAddonHandler_result(TBase): __slots__ = [ ] @@ -5331,7 +6719,7 @@ class getServices_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.MAP,(TType.STRING,None,TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRUCT,(AddonService, AddonService.thrift_spec))), None, ), # 0 ) def __init__(self, success=None,): @@ -5382,20 +6770,28 @@ class hasService_result(TBase): class call_args(TBase): """ Attributes: - - info + - plugin + - func + - arguments """ __slots__ = [ - 'info', + 'plugin', + 'func', + 'arguments', ] thrift_spec = ( None, # 0 - (1, TType.STRUCT, 'info', (ServiceCall, ServiceCall.thrift_spec), None, ), # 1 + (1, TType.STRING, 'plugin', None, None, ), # 1 + (2, TType.STRING, 'func', None, None, ), # 2 + (3, TType.STRING, 'arguments', None, None, ), # 3 ) - def __init__(self, info=None,): - self.info = info + def __init__(self, plugin=None, func=None, arguments=None,): + self.plugin = plugin + self.func = func + self.arguments = arguments class call_result(TBase): @@ -5444,7 +6840,7 @@ class getAllInfo_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.MAP,(TType.STRING,None,TType.STRING,None)), None, ), # 0 + (0, TType.MAP, 'success', (TType.STRING,None,TType.LIST,(TType.STRUCT,(AddonInfo, AddonInfo.thrift_spec))), None, ), # 0 ) def __init__(self, success=None,): @@ -5481,142 +6877,9 @@ class getInfoByPlugin_result(TBase): ] thrift_spec = ( - (0, TType.MAP, 'success', (TType.STRING,None,TType.STRING,None), None, ), # 0 - ) - - def __init__(self, success=None,): - self.success = success - - -class isCaptchaWaiting_args(TBase): - - __slots__ = [ - ] - - thrift_spec = ( - ) - - -class isCaptchaWaiting_result(TBase): - """ - Attributes: - - success - """ - - __slots__ = [ - 'success', - ] - - thrift_spec = ( - (0, TType.BOOL, 'success', None, None, ), # 0 - ) - - def __init__(self, success=None,): - self.success = success - - -class getCaptchaTask_args(TBase): - """ - Attributes: - - exclusive - """ - - __slots__ = [ - 'exclusive', - ] - - thrift_spec = ( - None, # 0 - (1, TType.BOOL, 'exclusive', None, None, ), # 1 - ) - - def __init__(self, exclusive=None,): - self.exclusive = exclusive - - -class getCaptchaTask_result(TBase): - """ - Attributes: - - success - """ - - __slots__ = [ - 'success', - ] - - thrift_spec = ( - (0, TType.STRUCT, 'success', (CaptchaTask, CaptchaTask.thrift_spec), None, ), # 0 - ) - - def __init__(self, success=None,): - self.success = success - - -class getCaptchaTaskStatus_args(TBase): - """ - Attributes: - - tid - """ - - __slots__ = [ - 'tid', - ] - - thrift_spec = ( - None, # 0 - (1, TType.I32, 'tid', None, None, ), # 1 - ) - - def __init__(self, tid=None,): - self.tid = tid - - -class getCaptchaTaskStatus_result(TBase): - """ - Attributes: - - success - """ - - __slots__ = [ - 'success', - ] - - thrift_spec = ( - (0, TType.STRING, 'success', None, None, ), # 0 + (0, TType.LIST, 'success', (TType.STRUCT,(AddonInfo, AddonInfo.thrift_spec)), None, ), # 0 ) def __init__(self, success=None,): self.success = success - -class setCaptchaResult_args(TBase): - """ - Attributes: - - tid - - result - """ - - __slots__ = [ - 'tid', - 'result', - ] - - thrift_spec = ( - None, # 0 - (1, TType.I32, 'tid', None, None, ), # 1 - (2, TType.STRING, 'result', None, None, ), # 2 - ) - - def __init__(self, tid=None, result=None,): - self.tid = tid - self.result = result - - -class setCaptchaResult_result(TBase): - - __slots__ = [ - ] - - thrift_spec = ( - ) - diff --git a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py index b2da9748d..fbbc599a8 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py +++ b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py @@ -12,129 +12,187 @@ from thrift.protocol.TBase import TBase, TExceptionBase class DownloadStatus(TBase): - Finished = 0 + NA = 0 Offline = 1 Online = 2 Queued = 3 - Skipped = 4 - Waiting = 5 - TempOffline = 6 - Starting = 7 - Failed = 8 - Aborted = 9 - Decrypting = 10 - Custom = 11 - Downloading = 12 - Processing = 13 - Unknown = 14 + Paused = 4 + Finished = 5 + Skipped = 6 + Failed = 7 + Starting = 8 + Waiting = 9 + Downloading = 10 + TempOffline = 11 + Aborted = 12 + Decrypting = 13 + Processing = 14 + Custom = 15 + Unknown = 16 _VALUES_TO_NAMES = { - 0: "Finished", + 0: "NA", 1: "Offline", 2: "Online", 3: "Queued", - 4: "Skipped", - 5: "Waiting", - 6: "TempOffline", - 7: "Starting", - 8: "Failed", - 9: "Aborted", - 10: "Decrypting", - 11: "Custom", - 12: "Downloading", - 13: "Processing", - 14: "Unknown", + 4: "Paused", + 5: "Finished", + 6: "Skipped", + 7: "Failed", + 8: "Starting", + 9: "Waiting", + 10: "Downloading", + 11: "TempOffline", + 12: "Aborted", + 13: "Decrypting", + 14: "Processing", + 15: "Custom", + 16: "Unknown", } _NAMES_TO_VALUES = { - "Finished": 0, + "NA": 0, "Offline": 1, "Online": 2, "Queued": 3, - "Skipped": 4, - "Waiting": 5, - "TempOffline": 6, - "Starting": 7, - "Failed": 8, - "Aborted": 9, - "Decrypting": 10, - "Custom": 11, - "Downloading": 12, - "Processing": 13, - "Unknown": 14, + "Paused": 4, + "Finished": 5, + "Skipped": 6, + "Failed": 7, + "Starting": 8, + "Waiting": 9, + "Downloading": 10, + "TempOffline": 11, + "Aborted": 12, + "Decrypting": 13, + "Processing": 14, + "Custom": 15, + "Unknown": 16, } -class Destination(TBase): - Collector = 0 - Queue = 1 +class MediaType(TBase): + All = 0 + Other = 1 + Audio = 2 + Image = 4 + Video = 8 + Document = 16 + Archive = 32 _VALUES_TO_NAMES = { - 0: "Collector", - 1: "Queue", + 0: "All", + 1: "Other", + 2: "Audio", + 4: "Image", + 8: "Video", + 16: "Document", + 32: "Archive", } _NAMES_TO_VALUES = { - "Collector": 0, - "Queue": 1, + "All": 0, + "Other": 1, + "Audio": 2, + "Image": 4, + "Video": 8, + "Document": 16, + "Archive": 32, + } + +class FileStatus(TBase): + Ok = 0 + Missing = 1 + Remote = 2 + + _VALUES_TO_NAMES = { + 0: "Ok", + 1: "Missing", + 2: "Remote", + } + + _NAMES_TO_VALUES = { + "Ok": 0, + "Missing": 1, + "Remote": 2, + } + +class PackageStatus(TBase): + Ok = 0 + Paused = 1 + Remote = 2 + + _VALUES_TO_NAMES = { + 0: "Ok", + 1: "Paused", + 2: "Remote", + } + + _NAMES_TO_VALUES = { + "Ok": 0, + "Paused": 1, + "Remote": 2, } class Input(TBase): - NONE = 0 - TEXT = 1 - TEXTBOX = 2 - PASSWORD = 3 - BOOL = 4 - CLICK = 5 - CHOICE = 6 - MULTIPLE = 7 - LIST = 8 - TABLE = 9 + NA = 0 + Text = 1 + TextBox = 2 + Password = 3 + Bool = 4 + Click = 5 + Choice = 6 + Multiple = 7 + List = 8 + Table = 9 _VALUES_TO_NAMES = { - 0: "NONE", - 1: "TEXT", - 2: "TEXTBOX", - 3: "PASSWORD", - 4: "BOOL", - 5: "CLICK", - 6: "CHOICE", - 7: "MULTIPLE", - 8: "LIST", - 9: "TABLE", + 0: "NA", + 1: "Text", + 2: "TextBox", + 3: "Password", + 4: "Bool", + 5: "Click", + 6: "Choice", + 7: "Multiple", + 8: "List", + 9: "Table", } _NAMES_TO_VALUES = { - "NONE": 0, - "TEXT": 1, - "TEXTBOX": 2, - "PASSWORD": 3, - "BOOL": 4, - "CLICK": 5, - "CHOICE": 6, - "MULTIPLE": 7, - "LIST": 8, - "TABLE": 9, + "NA": 0, + "Text": 1, + "TextBox": 2, + "Password": 3, + "Bool": 4, + "Click": 5, + "Choice": 6, + "Multiple": 7, + "List": 8, + "Table": 9, } class Output(TBase): - CAPTCHA = 1 - QUESTION = 2 - NOTIFICATION = 4 + All = 0 + Notification = 1 + Captcha = 2 + Query = 4 _VALUES_TO_NAMES = { - 1: "CAPTCHA", - 2: "QUESTION", - 4: "NOTIFICATION", + 0: "All", + 1: "Notification", + 2: "Captcha", + 4: "Query", } _NAMES_TO_VALUES = { - "CAPTCHA": 1, - "QUESTION": 2, - "NOTIFICATION": 4, + "All": 0, + "Notification": 1, + "Captcha": 2, + "Query": 4, } -class DownloadInfo(TBase): +class ProgressInfo(TBase): """ Attributes: - fid @@ -184,7 +242,7 @@ class DownloadInfo(TBase): (6, TType.I64, 'bleft', None, None, ), # 6 (7, TType.I64, 'size', None, None, ), # 7 (8, TType.STRING, 'format_size', None, None, ), # 8 - (9, TType.BYTE, 'percent', None, None, ), # 9 + (9, TType.I16, 'percent', None, None, ), # 9 (10, TType.I32, 'status', None, None, ), # 10 (11, TType.STRING, 'statusmsg', None, None, ), # 11 (12, TType.STRING, 'format_wait', None, None, ), # 12 @@ -256,97 +314,159 @@ class ServerStatus(TBase): self.reconnect = reconnect -class FileData(TBase): +class DownloadInfo(TBase): """ Attributes: - - fid - url - - name - plugin - - size - - format_size + - hash - status - statusmsg - - packageID - error - - order """ __slots__ = [ - 'fid', 'url', - 'name', 'plugin', - 'size', - 'format_size', + 'hash', 'status', 'statusmsg', - 'packageID', 'error', - 'order', ] thrift_spec = ( None, # 0 - (1, TType.I32, 'fid', None, None, ), # 1 - (2, TType.STRING, 'url', None, None, ), # 2 - (3, TType.STRING, 'name', None, None, ), # 3 - (4, TType.STRING, 'plugin', None, None, ), # 4 - (5, TType.I64, 'size', None, None, ), # 5 - (6, TType.STRING, 'format_size', None, None, ), # 6 - (7, TType.I32, 'status', None, None, ), # 7 - (8, TType.STRING, 'statusmsg', None, None, ), # 8 - (9, TType.I32, 'packageID', None, None, ), # 9 - (10, TType.STRING, 'error', None, None, ), # 10 - (11, TType.I16, 'order', None, None, ), # 11 + (1, TType.STRING, 'url', None, None, ), # 1 + (2, TType.STRING, 'plugin', None, None, ), # 2 + (3, TType.STRING, 'hash', None, None, ), # 3 + (4, TType.I32, 'status', None, None, ), # 4 + (5, TType.STRING, 'statusmsg', None, None, ), # 5 + (6, TType.STRING, 'error', None, None, ), # 6 ) - def __init__(self, fid=None, url=None, name=None, plugin=None, size=None, format_size=None, status=None, statusmsg=None, packageID=None, error=None, order=None,): - self.fid = fid + def __init__(self, url=None, plugin=None, hash=None, status=None, statusmsg=None, error=None,): self.url = url - self.name = name self.plugin = plugin - self.size = size - self.format_size = format_size + self.hash = hash self.status = status self.statusmsg = statusmsg - self.packageID = packageID self.error = error - self.order = order -class PackageData(TBase): +class FileInfo(TBase): + """ + Attributes: + - fid + - name + - package + - size + - status + - media + - added + - fileorder + - download + """ + + __slots__ = [ + 'fid', + 'name', + 'package', + 'size', + 'status', + 'media', + 'added', + 'fileorder', + 'download', + ] + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fid', None, None, ), # 1 + (2, TType.STRING, 'name', None, None, ), # 2 + (3, TType.I32, 'package', None, None, ), # 3 + (4, TType.I64, 'size', None, None, ), # 4 + (5, TType.I32, 'status', None, None, ), # 5 + (6, TType.I32, 'media', None, None, ), # 6 + (7, TType.I64, 'added', None, None, ), # 7 + (8, TType.I16, 'fileorder', None, None, ), # 8 + (9, TType.STRUCT, 'download', (DownloadInfo, DownloadInfo.thrift_spec), None, ), # 9 + ) + + def __init__(self, fid=None, name=None, package=None, size=None, status=None, media=None, added=None, fileorder=None, download=None,): + self.fid = fid + self.name = name + self.package = package + self.size = size + self.status = status + self.media = media + self.added = added + self.fileorder = fileorder + self.download = download + + +class PackageStats(TBase): + """ + Attributes: + - linkstotal + - linksdone + - sizetotal + - sizedone + """ + + __slots__ = [ + 'linkstotal', + 'linksdone', + 'sizetotal', + 'sizedone', + ] + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'linkstotal', None, None, ), # 1 + (2, TType.I16, 'linksdone', None, None, ), # 2 + (3, TType.I64, 'sizetotal', None, None, ), # 3 + (4, TType.I64, 'sizedone', None, None, ), # 4 + ) + + def __init__(self, linkstotal=None, linksdone=None, sizetotal=None, sizedone=None,): + self.linkstotal = linkstotal + self.linksdone = linksdone + self.sizetotal = sizetotal + self.sizedone = sizedone + + +class PackageInfo(TBase): """ Attributes: - pid - name - folder + - root - site + - comment - password - - dest - - order - - linksdone - - sizedone - - sizetotal - - linkstotal - - links + - added + - status + - packageorder + - stats - fids + - pids """ __slots__ = [ 'pid', 'name', 'folder', + 'root', 'site', + 'comment', 'password', - 'dest', - 'order', - 'linksdone', - 'sizedone', - 'sizetotal', - 'linkstotal', - 'links', + 'added', + 'status', + 'packageorder', + 'stats', 'fids', + 'pids', ] thrift_spec = ( @@ -354,32 +474,98 @@ class PackageData(TBase): (1, TType.I32, 'pid', None, None, ), # 1 (2, TType.STRING, 'name', None, None, ), # 2 (3, TType.STRING, 'folder', None, None, ), # 3 - (4, TType.STRING, 'site', None, None, ), # 4 - (5, TType.STRING, 'password', None, None, ), # 5 - (6, TType.I32, 'dest', None, None, ), # 6 - (7, TType.I16, 'order', None, None, ), # 7 - (8, TType.I16, 'linksdone', None, None, ), # 8 - (9, TType.I64, 'sizedone', None, None, ), # 9 - (10, TType.I64, 'sizetotal', None, None, ), # 10 - (11, TType.I16, 'linkstotal', None, None, ), # 11 - (12, TType.LIST, 'links', (TType.STRUCT,(FileData, FileData.thrift_spec)), None, ), # 12 - (13, TType.LIST, 'fids', (TType.I32,None), None, ), # 13 + (4, TType.I32, 'root', None, None, ), # 4 + (5, TType.STRING, 'site', None, None, ), # 5 + (6, TType.STRING, 'comment', None, None, ), # 6 + (7, TType.STRING, 'password', None, None, ), # 7 + (8, TType.I64, 'added', None, None, ), # 8 + (9, TType.I32, 'status', None, None, ), # 9 + (10, TType.I16, 'packageorder', None, None, ), # 10 + (11, TType.STRUCT, 'stats', (PackageStats, PackageStats.thrift_spec), None, ), # 11 + (12, TType.LIST, 'fids', (TType.I32,None), None, ), # 12 + (13, TType.LIST, 'pids', (TType.I32,None), None, ), # 13 ) - def __init__(self, pid=None, name=None, folder=None, site=None, password=None, dest=None, order=None, linksdone=None, sizedone=None, sizetotal=None, linkstotal=None, links=None, fids=None,): + def __init__(self, pid=None, name=None, folder=None, root=None, site=None, comment=None, password=None, added=None, status=None, packageorder=None, stats=None, fids=None, pids=None,): self.pid = pid self.name = name self.folder = folder + self.root = root self.site = site + self.comment = comment self.password = password - self.dest = dest - self.order = order - self.linksdone = linksdone - self.sizedone = sizedone - self.sizetotal = sizetotal - self.linkstotal = linkstotal - self.links = links + self.added = added + self.status = status + self.packageorder = packageorder + self.stats = stats self.fids = fids + self.pids = pids + + +class PackageView(TBase): + """ + Attributes: + - root + - files + - packages + """ + + __slots__ = [ + 'root', + 'files', + 'packages', + ] + + thrift_spec = ( + None, # 0 + (1, TType.STRUCT, 'root', (PackageInfo, PackageInfo.thrift_spec), None, ), # 1 + (2, TType.MAP, 'files', (TType.I32,None,TType.STRUCT,(FileInfo, FileInfo.thrift_spec)), None, ), # 2 + (3, TType.MAP, 'packages', (TType.I32,None,TType.STRUCT,(PackageInfo, PackageInfo.thrift_spec)), None, ), # 3 + ) + + def __init__(self, root=None, files=None, packages=None,): + self.root = root + self.files = files + self.packages = packages + + +class LinkStatus(TBase): + """ + Attributes: + - url + - name + - plugin + - size + - status + - packagename + """ + + __slots__ = [ + 'url', + 'name', + 'plugin', + 'size', + 'status', + 'packagename', + ] + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'url', None, None, ), # 1 + (2, TType.STRING, 'name', None, None, ), # 2 + (3, TType.STRING, 'plugin', None, None, ), # 3 + (4, TType.I64, 'size', None, None, ), # 4 + (5, TType.I32, 'status', None, None, ), # 5 + (6, TType.STRING, 'packagename', None, None, ), # 6 + ) + + def __init__(self, url=None, name=None, plugin=None, size=None, status=None, packagename=None,): + self.url = url + self.name = name + self.plugin = plugin + self.size = size + self.status = status + self.packagename = packagename class InteractionTask(TBase): @@ -387,10 +573,9 @@ class InteractionTask(TBase): Attributes: - iid - input - - structure - - preset - - output - data + - output + - default_value - title - description - plugin @@ -399,10 +584,9 @@ class InteractionTask(TBase): __slots__ = [ 'iid', 'input', - 'structure', - 'preset', - 'output', 'data', + 'output', + 'default_value', 'title', 'description', 'plugin', @@ -412,32 +596,57 @@ class InteractionTask(TBase): None, # 0 (1, TType.I32, 'iid', None, None, ), # 1 (2, TType.I32, 'input', None, None, ), # 2 - (3, TType.LIST, 'structure', (TType.STRING,None), None, ), # 3 - (4, TType.LIST, 'preset', (TType.STRING,None), None, ), # 4 - (5, TType.I32, 'output', None, None, ), # 5 - (6, TType.LIST, 'data', (TType.STRING,None), None, ), # 6 - (7, TType.STRING, 'title', None, None, ), # 7 - (8, TType.STRING, 'description', None, None, ), # 8 - (9, TType.STRING, 'plugin', None, None, ), # 9 + (3, TType.LIST, 'data', (TType.STRING,None), None, ), # 3 + (4, TType.I32, 'output', None, None, ), # 4 + (5, TType.STRING, 'default_value', None, None, ), # 5 + (6, TType.STRING, 'title', None, None, ), # 6 + (7, TType.STRING, 'description', None, None, ), # 7 + (8, TType.STRING, 'plugin', None, None, ), # 8 ) - def __init__(self, iid=None, input=None, structure=None, preset=None, output=None, data=None, title=None, description=None, plugin=None,): + def __init__(self, iid=None, input=None, data=None, output=None, default_value=None, title=None, description=None, plugin=None,): self.iid = iid self.input = input - self.structure = structure - self.preset = preset - self.output = output self.data = data + self.output = output + self.default_value = default_value self.title = title self.description = description self.plugin = plugin +class AddonInfo(TBase): + """ + Attributes: + - func_name + - description + - value + """ + + __slots__ = [ + 'func_name', + 'description', + 'value', + ] + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'func_name', None, None, ), # 1 + (2, TType.STRING, 'description', None, None, ), # 2 + (3, TType.STRING, 'value', None, None, ), # 3 + ) + + def __init__(self, func_name=None, description=None, value=None,): + self.func_name = func_name + self.description = description + self.value = value + + class ConfigItem(TBase): """ Attributes: - name - - long_name + - display_name - description - type - default_value @@ -446,7 +655,7 @@ class ConfigItem(TBase): __slots__ = [ 'name', - 'long_name', + 'display_name', 'description', 'type', 'default_value', @@ -456,16 +665,16 @@ class ConfigItem(TBase): thrift_spec = ( None, # 0 (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'long_name', None, None, ), # 2 + (2, TType.STRING, 'display_name', None, None, ), # 2 (3, TType.STRING, 'description', None, None, ), # 3 (4, TType.STRING, 'type', None, None, ), # 4 (5, TType.STRING, 'default_value', None, None, ), # 5 (6, TType.STRING, 'value', None, None, ), # 6 ) - def __init__(self, name=None, long_name=None, description=None, type=None, default_value=None, value=None,): + def __init__(self, name=None, display_name=None, description=None, type=None, default_value=None, value=None,): self.name = name - self.long_name = long_name + self.display_name = display_name self.description = description self.type = type self.default_value = default_value @@ -476,72 +685,45 @@ class ConfigSection(TBase): """ Attributes: - name - - long_name + - display_name - description - long_description - items + - info - handler """ __slots__ = [ 'name', - 'long_name', + 'display_name', 'description', 'long_description', 'items', + 'info', 'handler', ] thrift_spec = ( None, # 0 (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'long_name', None, None, ), # 2 + (2, TType.STRING, 'display_name', None, None, ), # 2 (3, TType.STRING, 'description', None, None, ), # 3 (4, TType.STRING, 'long_description', None, None, ), # 4 (5, TType.LIST, 'items', (TType.STRUCT,(ConfigItem, ConfigItem.thrift_spec)), None, ), # 5 - (6, TType.MAP, 'handler', (TType.STRING,None,TType.STRUCT,(InteractionTask, InteractionTask.thrift_spec)), None, ), # 6 + (6, TType.LIST, 'info', (TType.STRUCT,(AddonInfo, AddonInfo.thrift_spec)), None, ), # 6 + (7, TType.LIST, 'handler', (TType.STRUCT,(InteractionTask, InteractionTask.thrift_spec)), None, ), # 7 ) - def __init__(self, name=None, long_name=None, description=None, long_description=None, items=None, handler=None,): + def __init__(self, name=None, display_name=None, description=None, long_description=None, items=None, info=None, handler=None,): self.name = name - self.long_name = long_name + self.display_name = display_name self.description = description self.long_description = long_description self.items = items + self.info = info self.handler = handler -class CaptchaTask(TBase): - """ - Attributes: - - tid - - data - - type - - resultType - """ - - __slots__ = [ - 'tid', - 'data', - 'type', - 'resultType', - ] - - thrift_spec = ( - None, # 0 - (1, TType.I16, 'tid', None, None, ), # 1 - (2, TType.STRING, 'data', None, None, ), # 2 - (3, TType.STRING, 'type', None, None, ), # 3 - (4, TType.STRING, 'resultType', None, None, ), # 4 - ) - - def __init__(self, tid=None, data=None, type=None, resultType=None,): - self.tid = tid - self.data = data - self.type = type - self.resultType = resultType - - class EventInfo(TBase): """ Attributes: @@ -636,7 +818,7 @@ class AccountInfo(TBase): (6, TType.I64, 'maxtraffic', None, None, ), # 6 (7, TType.BOOL, 'premium', None, None, ), # 7 (8, TType.BOOL, 'activated', None, None, ), # 8 - (9, TType.MAP, 'options', (TType.STRING,None,TType.LIST,(TType.STRING,None)), None, ), # 9 + (9, TType.MAP, 'options', (TType.STRING,None,TType.STRING,None), None, ), # 9 ) def __init__(self, plugin=None, loginname=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, options=None,): @@ -651,66 +833,35 @@ class AccountInfo(TBase): self.options = options -class ServiceCall(TBase): +class AddonService(TBase): """ Attributes: - - plugin - - func - - arguments - """ - - __slots__ = [ - 'plugin', - 'func', - 'arguments', - ] - - thrift_spec = ( - None, # 0 - (1, TType.STRING, 'plugin', None, None, ), # 1 - (2, TType.STRING, 'func', None, None, ), # 2 - (3, TType.STRING, 'arguments', None, None, ), # 3 - ) - - def __init__(self, plugin=None, func=None, arguments=None,): - self.plugin = plugin - self.func = func - self.arguments = arguments - - -class OnlineStatus(TBase): - """ - Attributes: - - name - - plugin - - packagename - - status - - size + - func_name + - description + - media + - package """ __slots__ = [ - 'name', - 'plugin', - 'packagename', - 'status', - 'size', + 'func_name', + 'description', + 'media', + 'package', ] thrift_spec = ( None, # 0 - (1, TType.STRING, 'name', None, None, ), # 1 - (2, TType.STRING, 'plugin', None, None, ), # 2 - (3, TType.STRING, 'packagename', None, None, ), # 3 - (4, TType.I32, 'status', None, None, ), # 4 - (5, TType.I64, 'size', None, None, ), # 5 + (1, TType.STRING, 'func_name', None, None, ), # 1 + (2, TType.STRING, 'description', None, None, ), # 2 + (3, TType.I16, 'media', None, None, ), # 3 + (4, TType.BOOL, 'package', None, None, ), # 4 ) - def __init__(self, name=None, plugin=None, packagename=None, status=None, size=None,): - self.name = name - self.plugin = plugin - self.packagename = packagename - self.status = status - self.size = size + def __init__(self, func_name=None, description=None, media=None, package=None,): + self.func_name = func_name + self.description = description + self.media = media + self.package = package class OnlineCheck(TBase): @@ -728,7 +879,7 @@ class OnlineCheck(TBase): thrift_spec = ( None, # 0 (1, TType.I32, 'rid', None, None, ), # 1 - (2, TType.MAP, 'data', (TType.STRING,None,TType.STRUCT,(OnlineStatus, OnlineStatus.thrift_spec)), None, ), # 2 + (2, TType.MAP, 'data', (TType.STRING,None,TType.STRUCT,(LinkStatus, LinkStatus.thrift_spec)), None, ), # 2 ) def __init__(self, rid=None, data=None,): diff --git a/module/setup.py b/module/setup.py index d16b8c9e2..ff862893f 100644 --- a/module/setup.py +++ b/module/setup.py @@ -378,6 +378,7 @@ class Setup(): db.removeUser(username) noaction = False elif action == "4": + db.syncSave() break finally: if not noaction: diff --git a/module/threads/AddonThread.py b/module/threads/AddonThread.py new file mode 100644 index 000000000..3a378ad6e --- /dev/null +++ b/module/threads/AddonThread.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from copy import copy +from traceback import print_exc + +from BaseThread import BaseThread + +class AddonThread(BaseThread): + """thread for addons""" + + def __init__(self, m, function, args, kwargs): + """Constructor""" + BaseThread.__init__(self, m) + + self.f = function + self.args = args + self.kwargs = kwargs + + self.active = [] + + m.localThreads.append(self) + + self.start() + + def getActiveFiles(self): + return self.active + + def addActive(self, pyfile): + """ Adds a pyfile to active list and thus will be displayed on overview""" + if pyfile not in self.active: + self.active.append(pyfile) + + def finishFile(self, pyfile): + if pyfile in self.active: + self.active.remove(pyfile) + + pyfile.finishIfDone() + + def run(self): + try: + try: + self.kwargs["thread"] = self + self.f(*self.args, **self.kwargs) + except TypeError, e: + #dirty method to filter out exceptions + if "unexpected keyword argument 'thread'" not in e.args[0]: + raise + + del self.kwargs["thread"] + self.f(*self.args, **self.kwargs) + except Exception, e: + if hasattr(self.f, "im_self"): + addon = self.f.im_self + addon.logError(_("An Error occured"), e) + if self.m.core.debug: + print_exc() + self.writeDebugReport(addon.__name__, plugin=addon) + + finally: + local = copy(self.active) + for x in local: + self.finishFile(x) + + self.m.localThreads.remove(self) \ No newline at end of file diff --git a/module/threads/DecrypterThread.py b/module/threads/DecrypterThread.py index ce3c8cd83..39448a620 100644 --- a/module/threads/DecrypterThread.py +++ b/module/threads/DecrypterThread.py @@ -55,6 +55,7 @@ class DecrypterThread(BaseThread): plugin.logDebug("Decrypted", plugin_result) result.extend(plugin_result) + #TODO result = uniqify(result) pack_names = {} urls = [] @@ -73,7 +74,7 @@ class DecrypterThread(BaseThread): self.m.core.api.addFiles(self.pid, urls) for p in pack_names.itervalues(): - self.m.core.api.addPackage(p.name, p.urls, p.dest, pack.password) + self.m.core.api.addPackage(p.name, p.urls, pack.password) if not result: self.log.info(_("No links decrypted")) diff --git a/module/threads/DownloadThread.py b/module/threads/DownloadThread.py index bd15b9b87..6239cddd8 100644 --- a/module/threads/DownloadThread.py +++ b/module/threads/DownloadThread.py @@ -64,11 +64,11 @@ class DownloadThread(BaseThread): self.log.info(_("Download starts: %s" % pyfile.name)) # start download - self.core.hookManager.downloadPreparing(pyfile) + self.core.addonManager.downloadPreparing(pyfile) pyfile.plugin.preprocessing(self) self.log.info(_("Download finished: %s") % pyfile.name) - self.core.hookManager.downloadFinished(pyfile) + self.core.addonManager.downloadFinished(pyfile) self.core.files.checkPackageFinished(pyfile) except NotImplementedError: @@ -117,7 +117,7 @@ class DownloadThread(BaseThread): self.log.warning(_("Download failed: %(name)s | %(msg)s") % {"name": pyfile.name, "msg": msg}) pyfile.error = msg - self.core.hookManager.downloadFailed(pyfile) + self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue @@ -158,7 +158,7 @@ class DownloadThread(BaseThread): print_exc() self.writeDebugReport(pyfile.plugin.__name__, pyfile) - self.core.hookManager.downloadFailed(pyfile) + self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue @@ -179,7 +179,7 @@ class DownloadThread(BaseThread): continue - except (Exception, BadHeader), e: + except Exception, e: if isinstance(e, BadHeader) and e.code == 500: pyfile.setStatus("temp. offline") self.log.warning(_("Download is temporary offline: %s") % pyfile.name) @@ -194,7 +194,7 @@ class DownloadThread(BaseThread): print_exc() self.writeDebugReport(pyfile.plugin.__name__, pyfile) - self.core.hookManager.downloadFailed(pyfile) + self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue diff --git a/module/threads/HookThread.py b/module/threads/HookThread.py deleted file mode 100644 index bffa72ca0..000000000 --- a/module/threads/HookThread.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from copy import copy -from traceback import print_exc - -from BaseThread import BaseThread - -class HookThread(BaseThread): - """thread for hooks""" - - def __init__(self, m, function, args, kwargs): - """Constructor""" - BaseThread.__init__(self, m) - - self.f = function - self.args = args - self.kwargs = kwargs - - self.active = [] - - m.localThreads.append(self) - - self.start() - - def getActiveFiles(self): - return self.active - - def addActive(self, pyfile): - """ Adds a pyfile to active list and thus will be displayed on overview""" - if pyfile not in self.active: - self.active.append(pyfile) - - def finishFile(self, pyfile): - if pyfile in self.active: - self.active.remove(pyfile) - - pyfile.finishIfDone() - - def run(self): - try: - try: - self.kwargs["thread"] = self - self.f(*self.args, **self.kwargs) - except TypeError, e: - #dirty method to filter out exceptions - if "unexpected keyword argument 'thread'" not in e.args[0]: - raise - - del self.kwargs["thread"] - self.f(*self.args, **self.kwargs) - except Exception, e: - if hasattr(self.f, "im_self"): - hook = self.f.im_self - hook.logError(_("An Error occured"), e) - if self.m.core.debug: - print_exc() - self.writeDebugReport(hook.__name__, plugin=hook) - - finally: - local = copy(self.active) - for x in local: - self.finishFile(x) - - self.m.localThreads.remove(self) \ No newline at end of file diff --git a/module/threads/InfoThread.py b/module/threads/InfoThread.py index 7db85803a..a8a2c6e7e 100644 --- a/module/threads/InfoThread.py +++ b/module/threads/InfoThread.py @@ -4,7 +4,7 @@ from time import time from traceback import print_exc -from module.Api import OnlineStatus +from module.Api import LinkStatus from module.common.packagetools import parseNames from module.utils import has_method, accumulate @@ -100,7 +100,7 @@ class InfoThread(BaseThread): if len(self.cache) >= 20 or force: #used for package generating - tmp = [(name, (url, OnlineStatus(name, plugin, "unknown", status, int(size)))) + tmp = [(name, (url, LinkStatus(name, plugin, "unknown", status, int(size)))) for name, size, status, url in self.cache] data = parseNames(tmp) @@ -161,7 +161,7 @@ class InfoThread(BaseThread): # only decrypt files if has_method(klass, "decryptFile"): - urls = p.decrypt(urls) + urls = klass.decrypt(urls) data, crypter = self.m.core.pluginManager.parseUrls(urls) return data diff --git a/module/threads/ThreadManager.py b/module/threads/ThreadManager.py index f8b5c0aba..b3a1e8c6c 100644 --- a/module/threads/ThreadManager.py +++ b/module/threads/ThreadManager.py @@ -47,7 +47,7 @@ class ThreadManager: self.log = core.log self.threads = [] # thread list - self.localThreads = [] #hook+decrypter threads + self.localThreads = [] #addon+decrypter threads self.pause = True @@ -189,7 +189,7 @@ class ThreadManager: ip = self.getIP() - self.core.hookManager.beforeReconnecting(ip) + self.core.addonManager.beforeReconnecting(ip) self.log.debug("Old IP: %s" % ip) @@ -206,7 +206,7 @@ class ThreadManager: reconn.wait() sleep(1) ip = self.getIP() - self.core.hookManager.afterReconnecting(ip) + self.core.addonManager.afterReconnecting(ip) self.log.info(_("Reconnected, new IP: %s") % ip) diff --git a/module/utils/__init__.py b/module/utils/__init__.py index cdad1d222..db43f330d 100644 --- a/module/utils/__init__.py +++ b/module/utils/__init__.py @@ -63,24 +63,39 @@ def to_list(value): return value if type(value) == list else [value] def formatSize(size): - """formats size of bytes""" - size = int(size) + print "Deprecated formatSize, use format_size" + return format_size(size) + +def format_size(bytes): + bytes = int(bytes) steps = 0 sizes = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB") - while size > 1000: - size /= 1024.0 + while bytes > 1000: + bytes /= 1024.0 steps += 1 - return "%.2f %s" % (size, sizes[steps]) - + return "%.2f %s" % (bytes, sizes[steps]) def formatSpeed(speed): - return formatSize(speed) + "/s" + print "Deprecated formatSpeed, use format_speed" + return format_speed(speed) + +def format_speed(speed): + return format_size(speed) + "/s" + +def format_time(seconds): + if seconds < 0: return "00:00:00" + hours, seconds = divmod(seconds, 3600) + minutes, seconds = divmod(seconds, 60) + return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) def uniqify(seq): #by Dave Kirby """ removes duplicates from list, preserve order """ seen = set() return [x for x in seq if x not in seen and not seen.add(x)] +def bits_set(bits, compare): + """ checks if all bits are set in compare, or bits is 0 """ + return bits == (bits & compare) def parseFileSize(string, unit=None): #returns bytes if not unit: diff --git a/module/web/api_app.py b/module/web/api_app.py index affcdb39a..6c93266fc 100644 --- a/module/web/api_app.py +++ b/module/web/api_app.py @@ -24,13 +24,17 @@ class TBaseEncoder(json.JSONEncoder): return json.JSONEncoder.default(self, o) +def add_header(r): + r.headers.replace("Content-type", "application/json") + r.headers.append("Cache-Control", "no-cache, must-revalidate") + r.headers.append("Access-Control-Allow-Origin", "*") # allow xhr requests + # accepting positional arguments, as well as kwargs via post and get # only forbidden path symbol are "?", which is used to seperate GET data and # @route("/api/") @route("/api/", method="POST") def call_api(func, args=""): - response.headers.replace("Content-type", "application/json") - response.headers.append("Cache-Control", "no-cache, must-revalidate") + add_header(response) s = request.environ.get('beaker.session') if 'session' in request.POST: @@ -62,6 +66,7 @@ def callApi(func, *args, **kwargs): print "Invalid API call", func return HTTPError(404, json.dumps("Not Found")) + # TODO: encoding result = getattr(PYLOAD, func)(*[literal_eval(x) for x in args], **dict([(x, literal_eval(y)) for x, y in kwargs.iteritems()])) @@ -74,8 +79,7 @@ def callApi(func, *args, **kwargs): #post -> username, password @route("/api/login", method="POST") def login(): - response.headers.replace("Content-type", "application/json") - response.headers.append("Cache-Control", "no-cache, must-revalidate") + add_header(response) user = request.forms.get("username") password = request.forms.get("password") @@ -97,8 +101,7 @@ def login(): @route("/api/logout") def logout(): - response.headers.replace("Content-type", "application/json") - response.headers.append("Cache-Control", "no-cache, must-revalidate") + add_header(response) s = request.environ.get('beaker.session') s.delete() diff --git a/module/web/json_app.py b/module/web/json_app.py index 5acafe153..fcaa906e1 100644 --- a/module/web/json_app.py +++ b/module/web/json_app.py @@ -11,16 +11,7 @@ from webinterface import PYLOAD from utils import login_required, render_to_response, toDict -from module.utils import decode, formatSize - - -def format_time(seconds): - seconds = int(seconds) - - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - +from module.utils import decode, format_size def get_sort_key(item): return item["order"] @@ -49,7 +40,7 @@ def links(): ids.append(link['fid']) if link['status'] == 12: - link['info'] = "%s @ %s/s" % (link['format_eta'], formatSize(link['speed'])) + link['info'] = "%s @ %s/s" % (link['format_eta'], format_size(link['speed'])) elif link['status'] == 5: link['percent'] = 0 link['size'] = 0 diff --git a/module/web/pyload_app.py b/module/web/pyload_app.py index dcfc3266e..4edc6e0a5 100644 --- a/module/web/pyload_app.py +++ b/module/web/pyload_app.py @@ -25,6 +25,7 @@ import sys from os.path import isdir, isfile, join, abspath from sys import getfilesystemencoding from urllib import unquote +from traceback import print_exc from bottle import route, static_file, request, response, redirect, HTTPError, error @@ -35,8 +36,8 @@ from utils import render_to_response, parse_permissions, parse_userdata, \ from filters import relpath, unquotepath -from module.utils import formatSize -from module.utils.fs import save_join, fs_encode, fs_decode, listdir, free_space +from module.utils import format_size +from module.utils.fs import save_join, fs_encode, fs_decode, listdir # Helper @@ -79,7 +80,7 @@ def error500(error): if error.traceback: print error.traceback - return base(["An Error occured, please enable debug mode to get more details.", error, + return base(["An error occured while processing the request.", error, error.traceback.replace("\n", "
") if error.traceback else "No Traceback"]) # render js @@ -151,10 +152,11 @@ def logout(): @login_required("LIST") def home(): try: - res = [toDict(x) for x in PYLOAD.statusDownloads()] + res = [toDict(x) for x in PYLOAD.getProgressInfo()] except: s = request.environ.get('beaker.session') s.delete() + print_exc() return redirect("/login") for link in res: @@ -241,7 +243,7 @@ def get_download(path): @route("/settings") @login_required('SETTINGS') def config(): - conf = PYLOAD.getConfigPointer() + conf = PYLOAD.getConfigRef() conf_menu = [] plugin_menu = [] @@ -509,7 +511,7 @@ def setup(): @login_required("STATUS") @route("/info") def info(): - conf = PYLOAD.getConfigPointer() + conf = PYLOAD.getConfigRef() if hasattr(os, "uname"): extra = os.uname() @@ -521,7 +523,7 @@ def info(): "version": PYLOAD.getServerVersion(), "folder": abspath(PYLOAD_DIR), "config": abspath(""), "download": abspath(conf["general"]["download_folder"]), - "freespace": formatSize(PYLOAD.freeSpace()), + "freespace": format_size(PYLOAD.freeSpace()), "remote": conf["remote"]["port"], "webif": conf["webinterface"]["port"], "language": conf["general"]["language"]} diff --git a/module/web/utils.py b/module/web/utils.py index a89c87558..5cb0cebdd 100644 --- a/module/web/utils.py +++ b/module/web/utils.py @@ -104,6 +104,7 @@ def login_required(perm=None): if s.get("name", None) and s.get("authenticated", False): if perm: perms = parse_permissions(s) + if perm not in perms or not perms[perm]: if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return HTTPError(403, "Forbidden") diff --git a/module/web/webinterface.py b/module/web/webinterface.py index ec8b2e56c..56043063e 100644 --- a/module/web/webinterface.py +++ b/module/web/webinterface.py @@ -30,7 +30,7 @@ PYLOAD_DIR = abspath(join(PROJECT_DIR, "..", "..")) sys.path.append(PYLOAD_DIR) from module import InitHomeDir -from module.utils import decode, formatSize +from module.utils import decode, format_size import bottle from bottle import run, app @@ -92,7 +92,7 @@ env.filters["path_make_relative"] = path_make_relative env.filters["path_make_absolute"] = path_make_absolute env.filters["decode"] = decode env.filters["type"] = lambda x: str(type(x)) -env.filters["formatsize"] = formatSize +env.filters["formatsize"] = format_size env.filters["getitem"] = lambda x, y: x.__getitem__(y) if PREFIX: env.filters["url"] = lambda x: x -- cgit v1.2.3