diff options
Diffstat (limited to 'module/Api.py')
-rw-r--r-- | module/Api.py | 770 |
1 files changed, 377 insertions, 393 deletions
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) |