summaryrefslogtreecommitdiffstats
path: root/pyload/api
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/api')
-rw-r--r--pyload/api/__init__.py196
-rw-r--r--pyload/api/types.py12
2 files changed, 82 insertions, 126 deletions
diff --git a/pyload/api/__init__.py b/pyload/api/__init__.py
index e7e082ecd..365828d0a 100644
--- a/pyload/api/__init__.py
+++ b/pyload/api/__init__.py
@@ -31,12 +31,17 @@ from utils import compare_time, freeSpace, html_unescape, save_filename
if activated:
try:
+ from lib.thrift.protocol import TBase
from remote.thriftbackend.thriftgen.pyload.ttypes import *
from remote.thriftbackend.thriftgen.pyload.Pyload import Iface
+
BaseObject = TBase
+
except ImportError:
- print "Thrift not imported"
from pyload.api.types import *
+
+ print "Thrift not imported"
+
else:
from pyload.api.types import *
@@ -44,34 +49,37 @@ else:
# unlisted functions are for admins only
permMap = {}
+
# decorator only called on init, never initialized, so has no effect on runtime
def permission(bits):
class _Dec(object):
def __new__(cls, func, *args, **kwargs):
permMap[func.__name__] = bits
return func
-
return _Dec
urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-=\\\.&\[\]\|]*)", re.IGNORECASE)
-class PERMS:
+
+class PERMS(object):
ALL = 0 # requires no permission, but login
ADD = 1 # can add packages
- DELETE = 2 # can delete packages
- STATUS = 4 # see and change server status
- LIST = 16 # see queue and collector
- MODIFY = 32 # moddify some attribute of downloads
+ DELETE = 2 # can delete packages
+ STATUS = 4 # see and change server status
+ LIST = 16 # see queue and collector
+ 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
+ SETTINGS = 128 # can access settings
+ ACCOUNTS = 256 # can access accounts
+ LOGS = 512 # can see server logs
+
-class ROLE:
- ADMIN = 0 #admin has all permissions implicit
+class ROLE(object):
+ ADMIN = 0 # admin has all permissions implicit
USER = 1
+
def has_permission(userperms, perms):
# bytewise or perms before if needed
return perms == (userperms & perms)
@@ -90,17 +98,16 @@ class Api(Iface):
These can be configured via webinterface.
Admin user have all permissions, and are the only ones who can access the methods with no specific permission.
"""
-
EXTERNAL = Iface # let the json api know which methods are external
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
+ fdata = 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 fdata
def _convertConfigFormat(self, c):
sections = {}
@@ -135,8 +142,7 @@ class Api(Iface):
value = self.core.config[category][option]
else:
value = self.core.config.getPlugin(category, option)
-
- return str(value) if not isinstance(value, basestring) else value
+ return str(value)
@permission(PERMS.SETTINGS)
def setConfigValue(self, category, option, value, section="core"):
@@ -148,13 +154,10 @@ class Api(Iface):
:param section: 'plugin' or 'core
"""
self.core.addonManager.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
+ 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)
@@ -188,7 +191,6 @@ class Api(Iface):
"""
return self.core.config.plugin
-
@permission(PERMS.STATUS)
def pauseServer(self):
"""Pause server: Tt wont start any new downloads, but nothing gets aborted."""
@@ -227,10 +229,8 @@ class Api(Iface):
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
-
+ serverStatus.speed += pyfile.getSpeed() # bytes/s
return serverStatus
@permission(PERMS.STATUS)
@@ -266,7 +266,7 @@ class Api(Iface):
if offset >= len(lines):
return []
return lines[offset:]
- except:
+ except Exception:
return ['No log available']
@permission(PERMS.STATUS)
@@ -299,13 +299,11 @@ class Api(Iface):
for pyfile in self.core.threadManager.getActiveFiles():
if not isinstance(pyfile, PyFile):
continue
-
data.append(DownloadInfo(
pyfile.id, pyfile.name, pyfile.getSpeed(), pyfile.getETA(), pyfile.formatETA(),
pyfile.getBytesLeft(), pyfile.getSize(), pyfile.formatSize(), pyfile.getPercent(),
pyfile.status, pyfile.getStatusName(), pyfile.formatWait(),
pyfile.waitUntil, pyfile.packageid, pyfile.package().name, pyfile.pluginname))
-
return data
@permission(PERMS.ADD)
@@ -342,18 +340,14 @@ class Api(Iface):
:return:
"""
urls = []
-
if html:
urls += [x[0] for x in urlmatcher.findall(html)]
-
if url:
page = getURL(url)
urls += [x[0] for x in urlmatcher.findall(page)]
-
# remove duplicates
return self.checkURLs(set(urls))
-
@permission(PERMS.ADD)
def checkURLs(self, urls):
""" Gets urls and returns pluginname mapped to list of matches urls.
@@ -367,7 +361,7 @@ class Api(Iface):
for url, plugintype, pluginname in data:
try:
plugins[plugintype][pluginname].append(url)
- except:
+ except Exception:
plugins[plugintype][pluginname] = [url]
return plugins
@@ -386,7 +380,6 @@ class Api(Iface):
tmp = [(url, (url, OnlineStatus(url, (plugintype, pluginname), "unknown", 3, 0))) for url, plugintype, pluginname in data]
data = parseNames(tmp)
result = {}
-
for k, v in data.iteritems():
for url, status in v:
status.packagename = k
@@ -406,7 +399,6 @@ 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])
@permission(PERMS.ADD)
@@ -417,14 +409,12 @@ class Api(Iface):
:return: `OnlineCheck`, if rid is -1 then no more data available
"""
result = self.core.threadManager.getInfoResult(rid)
-
if "ALL_INFO_FETCHED" in result:
del result["ALL_INFO_FETCHED"]
return OnlineCheck(-1, result)
else:
return OnlineCheck(rid, result)
-
@permission(PERMS.ADD)
def generatePackages(self, links):
""" Parses links, generates packages names from urls
@@ -432,8 +422,7 @@ class Api(Iface):
:param links: list of urls
:return: package names mapped to urls
"""
- result = parseNames((x, x) for x in links)
- return result
+ return parseNames((x, x) for x in links)
@permission(PERMS.ADD)
def generateAndAddPackages(self, links, dest=Destination.Queue):
@@ -458,7 +447,6 @@ class Api(Iface):
data = self.core.pluginManager.parseUrls(links)
self.core.threadManager.createResultThread(data, True)
-
@permission(PERMS.LIST)
def getPackageData(self, pid):
"""Returns complete information about package, and included files.
@@ -467,15 +455,11 @@ class Api(Iface):
:return: `PackageData` with .links 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"],
- links=[self._convertPyFile(x) for x in data["links"].itervalues()])
-
- return pdata
+ return 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()])
@permission(PERMS.LIST)
def getPackageInfo(self, pid):
@@ -488,12 +472,9 @@ class Api(Iface):
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"]])
-
- return pdata
+ return 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.LIST)
def getFileData(self, fid):
@@ -505,9 +486,7 @@ class Api(Iface):
info = self.core.files.getFileData(int(fid))
if not info:
raise FileDoesNotExists(fid)
-
- fdata = self._convertPyFile(info.values()[0])
- return fdata
+ return self._convertPyFile(info.values()[0])
@permission(PERMS.DELETE)
def deleteFiles(self, fids):
@@ -515,9 +494,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.deleteLink(int(fid))
self.core.files.save()
@permission(PERMS.DELETE)
@@ -526,9 +504,8 @@ 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(int(pid))
self.core.files.save()
@permission(PERMS.LIST)
@@ -581,7 +558,6 @@ class Api(Iface):
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.
@@ -590,7 +566,6 @@ class Api(Iface):
: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()
@@ -651,7 +626,6 @@ class Api(Iface):
:return:
"""
pyfiles = self.core.files.cache.values()
-
for pyfile in pyfiles:
if pyfile.id in fids:
pyfile.abortDownload()
@@ -674,8 +648,8 @@ class Api(Iface):
:param destination: `Destination`
:param pid: package id
"""
- if destination not in (0, 1): return
- self.core.files.setPackageLocation(pid, destination)
+ if destination in (0, 1):
+ self.core.files.setPackageLocation(pid, destination)
@permission(PERMS.MODIFY)
def moveFiles(self, fids, pid):
@@ -685,7 +659,7 @@ class Api(Iface):
:param pid: destination package
:return:
"""
- #TODO: implement
+ # TODO: implement
pass
@@ -699,7 +673,6 @@ class Api(Iface):
th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb")
th.write(str(data))
th.close()
-
self.addPackage(th.name, [th.name], Destination.Queue)
@permission(PERMS.MODIFY)
@@ -727,14 +700,14 @@ class Api(Iface):
:param pid: package id
:param data: dict that maps attribute to desired value
"""
- p = self.core.files.getPackage(pid)
- if not p: raise PackageDoesNotExists(pid)
-
+ package = self.core.files.getPackage(pid)
+ if not package:
+ raise PackageDoesNotExists(pid)
for key, value in data.iteritems():
- if key == "id": continue
- setattr(p, key, value)
-
- p.sync()
+ if key == "id":
+ continue
+ setattr(package, key, value)
+ package.sync()
self.core.files.save()
@permission(PERMS.DELETE)
@@ -757,13 +730,11 @@ class Api(Iface):
: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
+ while pack["order"] in order.keys(): # just in case
pack["order"] += 1
order[pack["order"]] = pack["id"]
return order
@@ -775,10 +746,10 @@ class Api(Iface):
:param pid:
:return: dict mapping order to file id
"""
- rawData = self.core.files.getPackageData(int(pid))
+ rawdata = self.core.files.getPackageData(int(pid))
order = {}
- for id, pyfile in rawData["links"].iteritems():
- while pyfile["order"] in order.keys(): #just in case
+ 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
@@ -806,10 +777,9 @@ class Api(Iface):
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)
+ ctask = CaptchaTask(int(task.id), standard_b64encode(data), type, result)
+ return ctask
+ return CaptchaTask(-1)
@permission(PERMS.STATUS)
def getCaptchaTaskStatus(self, tid):
@@ -819,8 +789,8 @@ class Api(Iface):
:return: string
"""
self.core.lastClientConnected = time()
- t = self.core.captchaManager.getTaskByID(tid)
- return t.getStatus() if t else ""
+ task = self.core.captchaManager.getTaskByID(tid)
+ return task.getStatus() if task else ""
@permission(PERMS.STATUS)
def setCaptchaResult(self, tid, result):
@@ -835,7 +805,6 @@ class Api(Iface):
task.setResult(result)
self.core.captchaManager.removeTask(task)
-
@permission(PERMS.STATUS)
def getEvents(self, uuid):
"""Lists occured events, may be affected to changes in future.
@@ -844,7 +813,7 @@ class Api(Iface):
:return: list of `Events`
"""
events = self.core.pullManager.getEvents(uuid)
- newEvents = []
+ new_events = []
def convDest(d):
return Destination.Queue if d == "queue" else Destination.Collector
@@ -863,8 +832,8 @@ class Api(Iface):
event.destination = convDest(e[3])
elif e[0] == "reload":
event.destination = convDest(e[1])
- newEvents.append(event)
- return newEvents
+ new_events.append(event)
+ return new_events
@permission(PERMS.ACCOUNTS)
def getAccounts(self, refresh):
@@ -874,12 +843,11 @@ class Api(Iface):
:return: list of `AccountInfo`
"""
accs = self.core.accountManager.getAccountInfos(False, 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])
- return accounts
+ accounts = [AccountInfo(acc["validuntil"], acc["login"], acc["options"], acc["valid"],
+ acc["trafficleft"], acc["maxtraffic"], acc["premium"], acc["type"])
+ for acc in group]
+ return accounts or []
@permission(PERMS.ALL)
def getAccountTypes(self):
@@ -890,9 +858,9 @@ class Api(Iface):
return self.core.accountManager.accounts.keys()
@permission(PERMS.ACCOUNTS)
- def updateAccount(self, plugin, account, password=None, options={}):
+ def updateAccount(self, plugin, account, password=None, options=None):
"""Changes pw/options for specific account."""
- self.core.accountManager.updateAccount(plugin, account, password, options)
+ self.core.accountManager.updateAccount(plugin, account, password, options or {})
@permission(PERMS.ACCOUNTS)
def removeAccount(self, plugin, account):
@@ -912,7 +880,7 @@ class Api(Iface):
:param remoteip: Omit this argument, its only used internal
:return: bool indicating login was successful
"""
- return True if self.checkAuth(username, password, remoteip) else False
+ return bool(self.checkAuth(username, password, remoteip))
def checkAuth(self, username, password, remoteip=None):
"""Check authentication and returns details
@@ -941,24 +909,19 @@ class Api(Iface):
else:
return False
-
@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()
-
def getAllUserData(self):
"""returns all known user and info"""
- res = {}
- for user, data in self.core.db.getAllUserData().iteritems():
- res[user] = UserData(user, data["email"], data["role"], data["permission"], data["template"])
-
- return res
+ return dict((user, UserData(user, data["email"], data["role"], data["permission"], data["template"])) for user, data
+ in self.core.db.getAllUserData().iteritems())
@permission(PERMS.STATUS)
def getServices(self):
@@ -966,11 +929,7 @@ class Api(Iface):
:return: dict with this style: {"plugin": {"method": "description"}}
"""
- data = {}
- for plugin, funcs in self.core.addonManager.methods.iteritems():
- data[plugin] = funcs
-
- return data
+ return dict((plugin, funcs) for plugin, funcs in self.core.addonManager.methods.iteritems())
@permission(PERMS.STATUS)
def hasService(self, plugin, func):
@@ -996,13 +955,10 @@ class Api(Iface):
func = info.func
args = info.arguments
parse = info.parseArguments
-
if not self.hasService(plugin, func):
raise ServiceDoesNotExists(plugin, func)
-
try:
ret = self.core.addonManager.callRPC(plugin, func, args, parse)
- return str(ret)
except Exception, e:
raise ServiceException(e.message)
@@ -1027,6 +983,6 @@ class Api(Iface):
""" 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)
+ def setUserPermission(self, user, perm, role):
+ self.core.db.setPermission(user, perm)
self.core.db.setRole(user, role)
diff --git a/pyload/api/types.py b/pyload/api/types.py
index a945e322a..81385bf9f 100644
--- a/pyload/api/types.py
+++ b/pyload/api/types.py
@@ -5,11 +5,11 @@
class BaseObject(object):
__slots__ = []
-class Destination:
+class Destination(object):
Collector = 0
Queue = 1
-class DownloadStatus:
+class DownloadStatus(object):
Aborted = 9
Custom = 11
Decrypting = 10
@@ -26,11 +26,11 @@ class DownloadStatus:
Unknown = 14
Waiting = 5
-class ElementType:
+class ElementType(object):
File = 1
Package = 0
-class Input:
+class Input(object):
BOOL = 4
CHOICE = 6
CLICK = 5
@@ -42,7 +42,7 @@ class Input:
TEXT = 1
TEXTBOX = 2
-class Output:
+class Output(object):
CAPTCHA = 1
NOTIFICATION = 4
QUESTION = 2
@@ -238,7 +238,7 @@ class UserData(BaseObject):
self.permission = permission
self.templateName = templateName
-class Iface:
+class Iface(object):
def addFiles(self, pid, links):
pass
def addPackage(self, name, links, dest):