diff options
Diffstat (limited to 'module/Api.py')
-rw-r--r-- | module/Api.py | 276 |
1 files changed, 115 insertions, 161 deletions
diff --git a/module/Api.py b/module/Api.py index f0bf5e264..e5d26631f 100644 --- a/module/Api.py +++ b/module/Api.py @@ -17,13 +17,16 @@ @author: RaNaN """ +import re from base64 import standard_b64encode -from os.path import join +from os.path import join, isabs from time import time -import re +from itertools import chain + from PyFile import PyFile -from utils import freeSpace, compare_time +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 @@ -32,6 +35,7 @@ if activated: try: from remote.thriftbackend.thriftgen.pyload.ttypes import * from remote.thriftbackend.thriftgen.pyload.Pyload import Iface + BaseObject = TBase except ImportError: print "Thrift not imported" @@ -49,7 +53,7 @@ def permission(bits): def __new__(cls, func, *args, **kwargs): permMap[func.__name__] = bits return func - + return _Dec @@ -67,10 +71,12 @@ class PERMS: ACCOUNTS = 256 # can access accounts LOGS = 512 # can see server logs + class ROLE: ADMIN = 0 #admin has all permissions implicit USER = 1 + def has_permission(userperms, perms): # bytewise or perms before if needed return perms == (userperms & perms) @@ -97,80 +103,45 @@ class Api(Iface): 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"]) + p["format_size"], p["status"], p["statusmsg"], + p["package"], p["error"], p["order"]) return f - def _convertConfigFormat(self, c): - sections = {} - for sectionName, sub in c.iteritems(): - section = ConfigSection(sectionName, sub["desc"]) - items = [] - for key, data in sub.iteritems(): - if key in ("desc", "outline"): - continue - item = ConfigItem() - item.name = key - item.description = data["desc"] - item.value = str(data["value"]) if not isinstance(data["value"], basestring) else data["value"] - item.type = data["type"] - items.append(item) - section.items = items - sections[sectionName] = section - if "outline" in sub: - section.outline = sub["outline"] - return sections - @permission(PERMS.SETTINGS) - def getConfigValue(self, category, option, section="core"): + def getConfigValue(self, section, option): """Retrieve config value. - :param category: name of category, or plugin + :param section: name of category, or plugin :param option: config option - :param section: 'plugin' or 'core' :return: config value as string """ - if section == "core": - value = self.core.config[category][option] - else: - value = self.core.config.getPlugin(category, option) - - return str(value) if not isinstance(value, basestring) else value + value = self.core.config.get(section, option) + return to_string(value) @permission(PERMS.SETTINGS) - def setConfigValue(self, category, option, value, section="core"): + def setConfigValue(self, section, option, value): """Set new config value. - :param category: + :param section: :param option: :param value: new config value - :param section: 'plugin' or 'core """ - self.core.hookManager.dispatchEvent("configChanged", category, option, value, section) - - if section == "core": - self.core.config[category][option] = value - - if option in ("limit_speed", "max_speed"): #not so nice to update the limit - self.core.requestFactory.updateBucket() + if option in ("limit_speed", "max_speed"): #not so nice to update the limit + self.core.requestFactory.updateBucket() - elif section == "plugin": - self.core.config.setPlugin(category, option, value) + self.core.config.set(section, option, value) @permission(PERMS.SETTINGS) def getConfig(self): """Retrieves complete config of core. - + :return: list of `ConfigSection` """ - return self._convertConfigFormat(self.core.config.config) - - def getConfigDict(self): - """Retrieves complete config in dict format, not for RPC. + 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()]) - :return: dict - """ - return self.core.config.config @permission(PERMS.SETTINGS) def getPluginConfig(self): @@ -178,15 +149,25 @@ class Api(Iface): :return: list of `ConfigSection` """ - return self._convertConfigFormat(self.core.config.plugin) + return dict([(section, ConfigSection(section, + data.name, data.description, data.long_desc)) for + section, data in self.core.config.getPluginSections()]) - def getPluginConfigDict(self): - """Plugin config as dict, not for RPC. + 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()] - :return: dict - """ - return self.core.config.plugin + #TODO: config handler + + return sec + def getConfigPointer(self): + """Config instance, not for RPC""" + return self.core.config @permission(PERMS.STATUS) def pauseServer(self): @@ -219,13 +200,13 @@ class Api(Iface): @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()) + 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 @@ -235,7 +216,7 @@ class Api(Iface): @permission(PERMS.STATUS) def freeSpace(self): """Available free space at download directory in bytes""" - return freeSpace(self.core.config["general"]["download_folder"]) + return free_space(self.core.config["general"]["download_folder"]) @permission(PERMS.ALL) def getServerVersion(self): @@ -308,12 +289,13 @@ class Api(Iface): return data @permission(PERMS.ADD) - def addPackage(self, name, links, dest=Destination.Queue): + def addPackage(self, name, links, dest=Destination.Queue, password=""): """Adds a package, with links to desired destination. :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 """ if self.core.config['general']['folder_per_package']: @@ -321,19 +303,36 @@ class Api(Iface): else: folder = "" - folder = folder.replace("http://", "").replace(":", "").replace("/", "_").replace("\\", "_") - - pid = self.core.files.addPackage(name, folder, dest) + if isabs(folder): + folder = folder.replace("/", "_") - self.core.files.addLinks(links, pid) + folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "") self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)}) - - self.core.files.save() + pid = self.core.files.addPackage(name, folder, dest, password) + self.addFiles(pid, links) return pid @permission(PERMS.ADD) + def addFiles(self, pid, links): + """Adds files to specific package. + + :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.debug("Added %d links to package #%d " % (len(hoster), pid)) + self.core.files.save() + + @permission(PERMS.ADD) def parseURLs(self, html=None, url=None): """Parses html content or any arbitaty text for links and returns result of `checkURLs` @@ -360,10 +359,10 @@ class Api(Iface): :param urls: :return: {plugin: urls} """ - data = self.core.pluginManager.parseUrls(urls) + data, crypter = self.core.pluginManager.parseUrls(urls) plugins = {} - for url, plugin in data: + for url, plugin in chain(data, crypter): if plugin in plugins: plugins[plugin].append(url) else: @@ -373,15 +372,14 @@ class Api(Iface): @permission(PERMS.ADD) def checkOnlineStatus(self, urls): - """ initiates online status check + """ initiates online status check, will also decrypt files. :param urls: :return: initial set of data as `OnlineCheck` instance containing the result id """ - data = self.core.pluginManager.parseUrls(urls) - - rid = self.core.threadManager.createResultThread(data, False) + 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] data = parseNames(tmp) result = {} @@ -391,6 +389,9 @@ class Api(Iface): status.packagename = k result[url] = status + data.update(crypter) # hoster and crypter will be processed + rid = self.core.threadManager.createResultThread(data, False) + return OnlineCheck(rid, result) @permission(PERMS.ADD) @@ -405,8 +406,8 @@ class Api(Iface): th = open(join(self.core.config["general"]["download_folder"], "tmp_" + container), "wb") th.write(str(data)) th.close() - - return self.checkOnlineStatus(urls + [th.name]) + urls.append(th.name) + return self.checkOnlineStatus(urls) @permission(PERMS.ADD) def pollResults(self, rid): @@ -445,18 +446,6 @@ class Api(Iface): return [self.addPackage(name, urls, dest) for name, urls in self.generatePackages(links).iteritems()] - @permission(PERMS.ADD) - def checkAndAddPackages(self, links, dest=Destination.Queue): - """Checks online status, retrieves names, and will add packages.\ - Because of this packages are not added immediatly, only for internal use. - - :param links: list of urls - :param dest: `Destination` - :return: None - """ - data = self.core.pluginManager.parseUrls(links) - self.core.threadManager.createResultThread(data, True) - @permission(PERMS.LIST) def getPackageData(self, pid): @@ -471,8 +460,8 @@ class Api(Iface): raise PackageDoesNotExists(pid) 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()]) + data["queue"], data["order"], + links=[self._convertPyFile(x) for x in data["links"].itervalues()]) return pdata @@ -484,13 +473,13 @@ class Api(Iface): :return: `PackageData` with .fid attribute """ data = self.core.files.getPackageData(int(pid)) - + if not data: raise PackageDoesNotExists(pid) pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"], - data["queue"], data["order"], - fids=[int(x) for x in data["links"]]) + data["queue"], data["order"], + fids=[int(x) for x in data["links"]]) return pdata @@ -511,7 +500,7 @@ class Api(Iface): @permission(PERMS.DELETE) def deleteFiles(self, fids): """Deletes several file entries from pyload. - + :param fids: list of file ids """ for id in fids: @@ -538,9 +527,9 @@ class Api(Iface): :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"]) + 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.LIST) @@ -551,9 +540,9 @@ class Api(Iface): :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()]) + 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) @@ -563,9 +552,9 @@ class Api(Iface): :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"]) + pack["password"], pack["queue"], pack["order"], + pack["linksdone"], pack["sizedone"], pack["sizetotal"], + pack["linkstotal"]) for pack in self.core.files.getInfoData(Destination.Collector).itervalues()] @permission(PERMS.LIST) @@ -575,24 +564,11 @@ class Api(Iface): :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"], - links=[self._convertPyFile(x) for x in pack["links"].itervalues()]) + 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()] - - @permission(PERMS.ADD) - def addFiles(self, pid, links): - """Adds files to specific package. - - :param pid: package id - :param links: list of urls - """ - self.core.files.addLinks(links, int(pid)) - - self.core.log.info(_("Added %(count)d links to package #%(package)d ") % {"count": len(links), "package": pid}) - self.core.files.save() - @permission(PERMS.MODIFY) def pushToQueue(self, pid): """Moves package from Collector to Queue. @@ -699,7 +675,7 @@ class Api(Iface): th.write(str(data)) th.close() - self.addPackage(th.name, [th.name], Destination.Queue) + return self.addPackage(th.name, [th.name]) @permission(PERMS.MODIFY) def orderPackage(self, pid, position): @@ -839,31 +815,11 @@ class Api(Iface): def getEvents(self, uuid): """Lists occured events, may be affected to changes in future. - :param uuid: + :param uuid: self assigned string uuid which has to be unique :return: list of `Events` """ - events = self.core.pullManager.getEvents(uuid) - newEvents = [] - - def convDest(d): - return Destination.Queue if d == "queue" else Destination.Collector - - for e in events: - event = EventInfo() - event.eventname = e[0] - if e[0] in ("update", "remove", "insert"): - event.id = e[3] - event.type = ElementType.Package if e[2] == "pack" else ElementType.File - event.destination = convDest(e[1]) - elif e[0] == "order": - if e[1]: - event.id = e[1] - event.type = ElementType.Package if e[2] == "pack" else ElementType.File - event.destination = convDest(e[3]) - elif e[0] == "reload": - event.destination = convDest(e[1]) - newEvents.append(event) - return newEvents + # TODO + pass @permission(PERMS.ACCOUNTS) def getAccounts(self, refresh): @@ -872,21 +828,20 @@ class Api(Iface): :param refresh: reload account info :return: list of `AccountInfo` """ - accs = self.core.accountManager.getAccountInfos(False, refresh) + accs = self.core.accountManager.getAllAccounts(refresh) accounts = [] - for group in accs.values(): - accounts.extend([AccountInfo(acc["validuntil"], acc["login"], acc["options"], acc["valid"], - acc["trafficleft"], acc["maxtraffic"], acc["premium"], acc["type"]) - for acc in group]) + for plugin in accs.itervalues(): + accounts.extend(plugin.values()) + return accounts @permission(PERMS.ALL) def getAccountTypes(self): """All available account types. - :return: list + :return: string list """ - return self.core.accountManager.accounts.keys() + return self.core.pluginManager.getPlugins("accounts").keys() @permission(PERMS.ACCOUNTS) def updateAccount(self, plugin, account, password=None, options={}): @@ -946,11 +901,11 @@ class Api(Iface): @permission(PERMS.ALL) def getUserData(self, username, password): """similar to `checkAuth` but returns UserData thrift type """ - user = self.checkAuth(username, password) + user = self.checkAuth(username, password) if user: return UserData(user["name"], user["email"], user["role"], user["permission"], user["template"]) - else: - return UserData() + + raise UserDoesNotExists(username) def getAllUserData(self): @@ -996,13 +951,12 @@ class Api(Iface): plugin = info.plugin func = info.func args = info.arguments - parse = info.parseArguments if not self.hasService(plugin, func): raise ServiceDoesNotExists(plugin, func) try: - ret = self.core.hookManager.callRPC(plugin, func, args, parse) + ret = self.core.hookManager.callRPC(plugin, func, args) return str(ret) except Exception, e: raise ServiceException(e.message) @@ -1030,4 +984,4 @@ class Api(Iface): def setUserPermission(self, user, permission, role): self.core.db.setPermission(user, permission) - self.core.db.setRole(user, role)
\ No newline at end of file + self.core.db.setRole(user, role) |