summaryrefslogtreecommitdiffstats
path: root/module/Api.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/Api.py')
-rw-r--r--module/Api.py276
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)