summaryrefslogtreecommitdiffstats
path: root/module/Api.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/Api.py')
-rw-r--r--module/Api.py621
1 files changed, 3 insertions, 618 deletions
diff --git a/module/Api.py b/module/Api.py
index 9a92da0ec..dfc7b608f 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -17,18 +17,13 @@
###############################################################################
import re
-from os.path import join, isabs
-from itertools import chain
from functools import partial
from types import MethodType, CodeType
from dis import opmap
from remote.ttypes import *
-from utils import compare_time, to_string, bits_set, get_index
-from utils.fs import free_space
-from common.packagetools import parseNames
-from network.RequestFactory import getURL
+from utils import bits_set, get_index
# contains function names mapped to their permissions
# unlisted functions are for admins only
@@ -151,7 +146,7 @@ class Api(Iface):
# but will only work once when they are imported
cls.EXTEND = True
# Import all Api modules, they register themselves.
- from module.api import *
+ import module.api
# they will vanish from the namespace afterwards
@@ -189,522 +184,6 @@ class Api(Iface):
return self.user_apis[uid]
- ##########################
- # Download Preparing
- ##########################
-
- @RequirePerm(Permission.Add)
- def parseURLs(self, html=None, url=None):
- """Parses html content or any arbitrary text for links and returns result of `checkURLs`
-
- :param html: html source
- :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))
-
-
- @RequirePerm(Permission.Add)
- def checkURLs(self, urls):
- """ Gets urls and returns pluginname mapped to list of matching urls.
-
- :param urls:
- :return: {plugin: urls}
- """
- data, crypter = self.core.pluginManager.parseUrls(urls)
- plugins = {}
-
- for url, plugin in chain(data, crypter):
- if plugin in plugins:
- plugins[plugin].append(url)
- else:
- plugins[plugin] = [url]
-
- return plugins
-
- @RequirePerm(Permission.Add)
- def checkOnlineStatus(self, urls):
- """ initiates online status check, will also decrypt files.
-
- :param urls:
- :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, LinkStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data]
- data = parseNames(tmp)
- result = {}
-
- for k, v in data.iteritems():
- for url, status in v:
- 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)
-
- @RequirePerm(Permission.Add)
- def checkOnlineStatusContainer(self, urls, container, data):
- """ checks online status of urls and a submitted container file
-
- :param urls: list of urls
- :param container: container file name
- :param data: file content
- :return: :class:`OnlineCheck`
- """
- th = open(join(self.core.config["general"]["download_folder"], "tmp_" + container), "wb")
- th.write(str(data))
- th.close()
- urls.append(th.name)
- return self.checkOnlineStatus(urls)
-
- @RequirePerm(Permission.Add)
- def pollResults(self, rid):
- """ Polls the result available for ResultID
-
- :param rid: `ResultID`
- :return: `OnlineCheck`, if rid is -1 then there is 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)
-
-
- @RequirePerm(Permission.Add)
- def generatePackages(self, links):
- """ Parses links, generates packages names from urls
-
- :param links: list of urls
- :return: package names mapped to urls
- """
- result = parseNames((x, x) for x in links)
- return result
-
- ##########################
- # Adding/Deleting
- ##########################
-
- @RequirePerm(Permission.Add)
- def generateAndAddPackages(self, links, paused=False):
- """Generates and add packages
-
- :param links: list of urls
- :param paused: paused package
- :return: list of package ids
- """
- return [self.addPackageP(name, urls, "", paused) for name, urls
- in self.generatePackages(links).iteritems()]
-
- @RequirePerm(Permission.Add)
- def createPackage(self, name, folder, root, password="", site="", comment="", paused=False):
- """Create a new package.
-
- :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 separated 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
- """
-
- if isabs(folder):
- folder = folder.replace("/", "_")
-
- folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "")
-
- 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)
-
- return pid
-
-
- @RequirePerm(Permission.Add)
- def addPackage(self, name, links, password=""):
- """Convenient method to add a package to the top-level and for adding links.
-
- :return: package id
- """
- return self.addPackageChild(name, links, password, -1, False)
-
- @RequirePerm(Permission.Add)
- def addPackageP(self, name, links, password, paused):
- """ Same as above with additional paused attribute. """
- return self.addPackageChild(name, links, password, -1, paused)
-
- @RequirePerm(Permission.Add)
- def addPackageChild(self, name, links, password, root, paused):
- """Adds a package, with links to desired package.
-
- :param root: parents package id
- :return: package id of the new package
- """
- if self.core.config['general']['folder_per_package']:
- folder = name
- else:
- folder = ""
-
- pid = self.createPackage(name, folder, root, password)
- self.addLinks(pid, links)
-
- return pid
-
- @RequirePerm(Permission.Add)
- def addLinks(self, pid, links):
- """Adds links to specific package. Initiates 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()
-
- @RequirePerm(Permission.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()
-
- return self.addPackage(th.name, [th.name])
-
- @RequirePerm(Permission.Delete)
- def deleteFiles(self, fids):
- """Deletes several file entries from pyload.
-
- :param fids: list of file ids
- """
- for fid in fids:
- self.core.files.deleteFile(fid)
-
- self.core.files.save()
-
- @RequirePerm(Permission.Delete)
- def deletePackages(self, pids):
- """Deletes packages and containing links.
-
- :param pids: list of package ids
- """
- for pid in pids:
- self.core.files.deletePackage(pid)
-
- self.core.files.save()
-
- ##########################
- # Collector
- ##########################
-
- @RequirePerm(Permission.All)
- def getCollector(self):
- pass
-
- @RequirePerm(Permission.Add)
- def addToCollector(self, links):
- pass
-
- @RequirePerm(Permission.Add)
- def addFromCollector(self, name, new_name):
- pass
-
- @RequirePerm(Permission.Delete)
- def deleteCollPack(self, name):
- pass
-
- @RequirePerm(Permission.Add)
- def renameCollPack(self, name, new_name):
- pass
-
- @RequirePerm(Permission.Delete)
- def deleteCollLink(self, url):
- pass
-
- #############################
- # File Information retrieval
- #############################
-
- @RequirePerm(Permission.All)
- def getAllFiles(self):
- """ same as `getFileTree` for toplevel root and full tree"""
- return self.getFileTree(-1, True)
-
- @RequirePerm(Permission.All)
- def getFilteredFiles(self, state):
- """ same as `getFilteredFileTree` for toplevel root and full tree"""
- return self.getFilteredFileTree(-1, state, True)
-
- @RequirePerm(Permission.All)
- def getFileTree(self, pid, full):
- """ Retrieve data for specific package. full=True will retrieve all data available
- and can result in greater delays.
-
- :param pid: package id
- :param full: go down the complete tree or only the first layer
- :return: :class:`TreeCollection`
- """
- return self.core.files.getTree(pid, full, DownloadState.All)
-
- @RequirePerm(Permission.All)
- def getFilteredFileTree(self, pid, full, state):
- """ Same as `getFileTree` but only contains files with specific download state.
-
- :param pid: package id
- :param full: go down the complete tree or only the first layer
- :param state: :class:`DownloadState`, the attributes used for filtering
- :return: :class:`TreeCollection`
- """
- return self.core.files.getTree(pid, full, state)
-
- @RequirePerm(Permission.All)
- def getPackageContent(self, pid):
- """ Only retrieve content of a specific package. see `getFileTree`"""
- return self.getFileTree(pid, False)
-
- @RequirePerm(Permission.All)
- def getPackageInfo(self, pid):
- """Returns information about package, without detailed information about containing files
-
- :param pid: package id
- :raises PackageDoesNotExists:
- :return: :class:`PackageInfo`
- """
- info = self.core.files.getPackageInfo(pid)
- if not info:
- raise PackageDoesNotExists(pid)
- return info
-
- @RequirePerm(Permission.All)
- def getFileInfo(self, fid):
- """ Info for specific file
-
- :param fid: file id
- :raises FileDoesNotExists:
- :return: :class:`FileInfo`
-
- """
- info = self.core.files.getFileInfo(fid)
- if not info:
- raise FileDoesNotExists(fid)
- return info
-
- @RequirePerm(Permission.All)
- def findFiles(self, pattern):
- pass
-
- @RequirePerm(Permission.All)
- def findPackages(self, tags):
- pass
-
- #############################
- # Modify Downloads
- #############################
-
- @RequirePerm(Permission.Modify)
- def restartPackage(self, pid):
- """Restarts a package, resets every containing files.
-
- :param pid: package id
- """
- self.core.files.restartPackage(pid)
-
- @RequirePerm(Permission.Modify)
- def restartFile(self, fid):
- """Resets file status, so it will be downloaded again.
-
- :param fid: file id
- """
- self.core.files.restartFile(fid)
-
- @RequirePerm(Permission.Modify)
- def recheckPackage(self, pid):
- """Check online status of all files in a package, also a default action when package is added. """
- self.core.files.reCheckPackage(pid)
-
- @RequirePerm(Permission.Modify)
- def restartFailed(self):
- """Restarts all failed failes."""
- self.core.files.restartFailed()
-
- @RequirePerm(Permission.Modify)
- def stopAllDownloads(self):
- """Aborts all running downloads."""
-
- pyfiles = self.core.files.cachedFiles()
- for pyfile in pyfiles:
- pyfile.abortDownload()
-
- @RequirePerm(Permission.Modify)
- def stopDownloads(self, fids):
- """Aborts specific downloads.
-
- :param fids: list of file ids
- :return:
- """
- pyfiles = self.core.files.cachedFiles()
- for pyfile in pyfiles:
- if pyfile.id in fids:
- pyfile.abortDownload()
-
- #############################
- # Modify Files/Packages
- #############################
-
- @RequirePerm(Permission.Modify)
- def updatePackage(self, pack):
- """Allows to modify several package attributes.
-
- :param pid: package id
- :param data: :class:`PackageInfo`
- """
- pid = pack.pid
- p = self.core.files.getPackage(pid)
- if not p: raise PackageDoesNotExists(pid)
-
- #TODO: fix
- for key, value in data.iteritems():
- if key == "id": continue
- setattr(p, key, value)
-
- p.sync()
- self.core.files.save()
-
- @RequirePerm(Permission.Modify)
- def setPackageFolder(self, pid, path):
- pass
-
- @RequirePerm(Permission.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 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
- """
- return self.core.files.movePackage(pid, root)
-
- @RequirePerm(Permission.Modify)
- def moveFiles(self, fids, pid):
- """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: False if files can't be moved
- """
- return self.core.files.moveFiles(fids, pid)
-
- @RequirePerm(Permission.Modify)
- def orderPackage(self, pid, position):
- """Set new position for a package.
-
- :param pid: package id
- :param position: new position, 0 for very beginning
- """
- self.core.files.orderPackage(pid, position)
-
- @RequirePerm(Permission.Modify)
- 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 fids: list of file ids
- :param pid: package id of parent package
- :param position: new position: 0 for very beginning
- """
- self.core.files.orderFiles(fids, pid, position)
-
- #############################
- # User Interaction
- #############################
-
- @RequirePerm(Permission.Interaction)
- def isInteractionWaiting(self, mode):
- """ Check if task is waiting.
-
- :param mode: binary or'ed output type
- :return: boolean
- """
- return self.core.interactionManager.isTaskWaiting(mode)
-
- @RequirePerm(Permission.Interaction)
- def getInteractionTask(self, mode):
- """Retrieve task for specific mode.
-
- :param mode: binary or'ed output type
- :return: :class:`InteractionTask`
- """
- task = self.core.interactionManager.getTask(mode)
- return InteractionTask(-1) if not task else task
-
-
- @RequirePerm(Permission.Interaction)
- def setInteractionResult(self, iid, result):
- """Set Result for a interaction task. It will be immediately removed from task queue afterwards
-
- :param iid: interaction id
- :param result: result as string
- """
- task = self.core.interactionManager.getTaskByID(iid)
- if task:
- task.setResult(result)
-
- @RequirePerm(Permission.Interaction)
- def getNotifications(self):
- """List of all available notifcations. They stay in queue for some time, client should\
- save which notifications it already has seen.
-
- :return: list of :class:`InteractionTask`
- """
- return self.core.interactionManager.getNotifications()
-
- @RequirePerm(Permission.Interaction)
- def getAddonHandler(self):
- pass
-
- @RequirePerm(Permission.Interaction)
- def callAddonHandler(self, plugin, func, pid_or_fid):
- pass
-
- @RequirePerm(Permission.Download)
- def generateDownloadLink(self, fid, timeout):
- pass
-
- #############################
- # Event Handling
- #############################
-
def getEvents(self, uuid):
"""Lists occurred events, may be affected to changes in future.
@@ -716,46 +195,6 @@ class Api(Iface):
pass
#############################
- # Account Methods
- #############################
-
- @RequirePerm(Permission.Accounts)
- def getAccounts(self, refresh):
- """Get information about all entered accounts.
-
- :param refresh: reload account info
- :return: list of `AccountInfo`
- """
- accs = self.core.accountManager.getAllAccounts(refresh)
- accounts = []
- for plugin in accs.itervalues():
- accounts.extend(plugin.values())
-
- return accounts
-
- @RequirePerm(Permission.All)
- def getAccountTypes(self):
- """All available account types.
-
- :return: string list
- """
- return self.core.pluginManager.getPlugins("accounts").keys()
-
- @RequirePerm(Permission.Accounts)
- def updateAccount(self, plugin, account, password=None, options={}):
- """Changes pw/options for specific account."""
- self.core.accountManager.updateAccount(plugin, account, password, options)
-
- @RequirePerm(Permission.Accounts)
- def removeAccount(self, plugin, account):
- """Remove account from pyload.
-
- :param plugin: pluginname
- :param account: accountname
- """
- self.core.accountManager.removeAccount(plugin, account)
-
- #############################
# Auth+User Information
#############################
@@ -777,7 +216,7 @@ class Api(Iface):
:param username:
:param password:
- :param remoteip:
+ :param remoteip:
:return: dict with info, empty when login is incorrect
"""
if self.core.config["remote"]["nolocalauth"] and remoteip == "127.0.0.1":
@@ -823,57 +262,3 @@ class Api(Iface):
self.core.db.setPermission(user, permission)
self.core.db.setRole(user, role)
- #############################
- # RPC Plugin Methods
- #############################
-
- # TODO: obsolete
-
- @RequirePerm(Permission.Interaction)
- def getServices(self):
- """ 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.addonManager.methods.iteritems():
- data[plugin] = funcs
-
- return data
-
- @RequirePerm(Permission.Interaction)
- def hasService(self, plugin, func):
- pass
-
- @RequirePerm(Permission.Interaction)
- def call(self, plugin, func, arguments):
- """Calls a service (a method in addon plugin).
-
- :raises: ServiceDoesNotExists, when its not available
- :raises: ServiceException, when a exception was raised
- """
- if not self.hasService(plugin, func):
- raise ServiceDoesNotExists(plugin, func)
-
- try:
- ret = self.core.addonManager.callRPC(plugin, func, arguments)
- return to_string(ret)
- except Exception, e:
- raise ServiceException(e.message)
-
-
- #TODO: permissions
- def getAllInfo(self):
- """Returns all information stored by addon plugins. Values are always strings
-
- :return: {"plugin": {"name": value } }
- """
- return self.core.addonManager.getAllInfo()
-
- def getInfoByPlugin(self, plugin):
- """Returns information stored by a specific plugin.
-
- :param plugin: pluginname
- :return: dict of attr names mapped to value {"name": value}
- """
- return self.core.addonManager.getInfo(plugin) \ No newline at end of file