summaryrefslogtreecommitdiffstats
path: root/module/plugins
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-07-29 12:09:42 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-07-29 12:09:42 +0200
commit2ba07aa53d2af572af2c5a43e77725abd46e1b13 (patch)
tree89ff915a3a476dd9431d38c6e2b39b9de1aeb0f5 /module/plugins
parentAdded tag working for changeset 3cca18acfe7d (diff)
downloadpyload-2ba07aa53d2af572af2c5a43e77725abd46e1b13.tar.xz
many new stuff, some things already working
Diffstat (limited to 'module/plugins')
-rw-r--r--module/plugins/Plugin.py229
-rw-r--r--module/plugins/hooks/ContainerDownload.py40
-rw-r--r--module/plugins/hooks/LinuxFileEvents.py75
-rw-r--r--module/plugins/hoster/BasePlugin.py25
-rw-r--r--module/plugins/hoster/YoutubeCom.py2
5 files changed, 147 insertions, 224 deletions
diff --git a/module/plugins/Plugin.py b/module/plugins/Plugin.py
index 0e04a86e6..51cd78f2d 100644
--- a/module/plugins/Plugin.py
+++ b/module/plugins/Plugin.py
@@ -22,15 +22,35 @@ import re
from os.path import exists
from os.path import join
+from time import time
from time import sleep
+
import sys
from os.path import exists
from os import makedirs
-from module.DownloadThread import CaptchaError
-class Plugin():
+def dec(func):
+ def new(*args):
+ if args[0].pyfile.abort:
+ raise Abort
+ return func(*args)
+ return new
+
+class Abort(Exception):
+ """ raised when aborted """
+
+class Fail(Exception):
+ """ raised when failed """
+
+class Reconnect(Exception):
+ """ raised when reconnected """
+
+class Retry(Exception):
+ """ raised when start again from beginning """
+
+class Plugin(object):
__name__ = "Plugin"
__version__ = "0.4"
__pattern__ = None
@@ -39,107 +59,55 @@ class Plugin():
__author_name__ = ("RaNaN", "spoob", "mkaay")
__author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "mkaay@mkaay.de")
- def __init__(self, parent):
- self.configparser = parent.core.parser_plugins
- self.config = {}
- self.parent = parent
- self.req = parent.core.requestFactory.getRequest(self.__name__)
- self.html = 0
- self.time_plus_wait = 0 #time() + wait in seconds
- self.want_reconnect = False
- self.multi_dl = True
- self.ocr = None #captcha reader instance
- self.logger = logging.getLogger("log")
- self.decryptNow = True
- self.pyfile = self.parent
-
- def prepare(self, thread):
- self.want_reconnect = False
- self.pyfile.status.exists = self.file_exists()
-
- if not self.pyfile.status.exists:
- return False
-
- self.pyfile.status.filename = self.get_file_name()
- self.pyfile.status.waituntil = self.time_plus_wait
- self.pyfile.status.url = self.get_file_url()
- self.pyfile.status.want_reconnect = self.want_reconnect
- thread.wait(self.parent)
-
- return True
-
- def set_parent_status(self):
- """ sets all available Statusinfos about a File in self.parent.status
- """
- pass
-
- def download_html(self):
- """ gets the url from self.parent.url saves html in self.html and parses
- """
- self.html = ""
-
- def file_exists(self):
- """ returns True or False
- """
- if re.search(r"(?!http://).*\.(dlc|ccf|rsdf|txt)", self.parent.url):
- return exists(self.parent.url)
- header = self.load(self.parent.url, just_header=True)
- try:
- if re.search(r"HTTP/1.1 404 Not Found", header):
- return False
- except:
- pass
- return True
-
- def get_file_url(self):
- """ returns the absolute downloadable filepath
- """
- return self.parent.url
-
- def get_file_name(self):
- try:
- return re.findall("([^\/=]+)", self.parent.url)[-1]
- except:
- return self.parent.url[:20]
-
- def wait_until(self):
- if self.html != None:
- self.download_html()
- return self.time_plus_wait
-
- def proceed(self, url, location):
- self.download(url, location)
-
- def set_config(self):
- for k, v in self.config.items():
- self.configparser.set(self.__name__, {"option": k}, v)
-
- def remove_config(self, option):
- self.configparser.remove(self.__name__, option)
-
- def get_config(self, value, default=None):
- self.configparser.loadData()
- return self.configparser.get(self.__name__, value, default=default)
-
- def read_config(self):
- self.configparser.loadData()
- try:
- self.verify_config()
- self.config = self.configparser.getConfig()[self.__name__]
- except:
- pass
-
- def verify_config(self):
- pass
-
- def init_ocr(self):
- captchaClass = self.parent.core.pluginManager.getCaptchaPlugin(self.__name__)
- self.ocr = captchaClass()
+ def __new__(cls, *args, **kws):
+ for f in dir(cls):
+ if not f.startswith("_") and f not in ("checksum"):
+ setattr(cls, f, dec(getattr(cls, f)) )
+
+ o = super(cls.__class__, cls).__new__(cls)
+ #wrap decorator around every method
+ return o
+
+ def __init__(self, pyfile):
+ self.config = pyfile.m.core.config
+
+ self.req = pyfile.m.core.requestFactory.getRequest(self.__name__)
+
+ self.wantReconnect = False
+ self.multiDL = True
+
+ self.waitUntil = 0 # time() + wait in seconds
+ self.premium = False
+
+ self.ocr = None # captcha reader instance
+ self.account = pyfile.m.core.accountManager.getAccount(self.__name__) # account handler instance
+ self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, self.account)
+
+ self.log = logging.getLogger("log")
+
+ self.pyfile = pyfile
+ self.thread = None # holds thread in future
+
def __call__(self):
+ return self.__name__
+
+ def preprocessing(self, thread):
+ """ handles important things to do before starting """
+ self.thread = thread
+
+ if not self.account:
+ self.req.clearCookies()
+
+ return self.process(self.pyfile)
+
+ #----------------------------------------------------------------------
+ def process(self, pyfile):
+ """the 'main' method of every plugin"""
raise NotImplementedError
- def check_file(self, local_file):
+
+ def checksum(self, local_file=None):
"""
return codes:
0 - checksum ok
@@ -148,8 +116,48 @@ class Plugin():
10 - not implemented
20 - unknown error
"""
+ #@TODO checksum check hook
+
return (True, 10)
+
+ def setConf(self, option, value):
+ """ sets a config value """
+ self.config.setPlugin(self.__name__, option, value)
+
+ def removeConf(self, option):
+ """ removes a config value """
+ raise NotImplementedError
+
+ def getConf(self, option):
+ """ gets a config value """
+ return self.config.getPlugin(self.__name__, option)
+
+
+ def setWait(self, seconds):
+ """ set the wait time to specified seconds """
+ self.waitUntil = time() + int(seconds)
+
+ def wait():
+ """ waits the time previously set """
+ pass
+
+ def fail(self, reason):
+ """ fail and give reason """
+ raise Fail(reason)
+
+ def offline(self):
+ """ fail and indicate file is offline """
+ raise Fail("offline")
+
+ def retry(self):
+ """ begin again from the beginning """
+ raise Retry
+
+ def askCaptcha(self, url):
+ """ loads the catpcha and decrypt it or ask the user for input """
+ pass
+
def waitForCaptcha(self, captchaData, imgType):
captchaManager = self.parent.core.captchaManager
task = captchaManager.newTask(self)
@@ -165,16 +173,19 @@ class Plugin():
return result
def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False):
+ """ returns the content loaded """
return self.req.load(url, get, post, ref, cookies, just_header)
- def download(self, url, file_name, get={}, post={}, ref=True, cookies=True):
- download_folder = self.parent.core.config['general']['download_folder']
- if self.pyfile.package.data["package_name"] != (self.parent.core.config['general']['link_file']) and self.parent.core.xmlconfig.get("general", "folder_per_package", False):
- self.pyfile.folder = self.pyfile.package.data["package_name"]
- location = join(download_folder, self.pyfile.folder.decode(sys.getfilesystemencoding()))
- if not exists(location): makedirs(location)
- file_path = join(location.decode(sys.getfilesystemencoding()), self.pyfile.status.filename.decode(sys.getfilesystemencoding()))
- else:
- file_path = join(download_folder, self.pyfile.status.filename.decode(sys.getfilesystemencoding()))
+ def download(self, url, get={}, post={}, ref=True, cookies=True):
+ """ downloads the url content to disk """
+ download_folder = self.config['general']['download_folder']
+
+ location = join(download_folder, self.pyfile.package().folder.decode(sys.getfilesystemencoding()))
+
+ if not exists(location):
+ makedirs(location)
+
+ newname = self.req.download(url, self.pyfile.name, location, get, post, ref, cookies)
- self.pyfile.status.filename = self.req.download(url, file_path, get, post, ref, cookies)
+ if newname:
+ self.pyfile.name = newname
diff --git a/module/plugins/hooks/ContainerDownload.py b/module/plugins/hooks/ContainerDownload.py
deleted file mode 100644
index 673931391..000000000
--- a/module/plugins/hooks/ContainerDownload.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- @author: mkaay
- @interface-version: 0.1
-"""
-
-from module.plugins.Hook import Hook
-
-from os.path import join, abspath
-
-class ContainerDownload(Hook):
- __name__ = "ContainerDownload"
- __version__ = "0.1"
- __description__ = """add the downloaded container to current package"""
- __author_name__ = ("mkaay")
- __author_mail__ = ("mkaay@mkaay.de")
-
- def downloadFinished(self, pyfile):
- filename = pyfile.status.filename
- if not pyfile.url.startswith("http"):
- return
- if filename.endswith(".dlc") or filename.endswith(".ccf") or filename.endswith(".rsdf"):
- self.logger.info("ContainerDownload: adding container file")
- location = abspath(join(pyfile.folder, filename))
- newFile = self.core.file_list.collector.addLink(location)
- self.core.file_list.packager.addFileToPackage(pyfile.package.data["id"], self.core.file_list.collector.popFile(newFile))
diff --git a/module/plugins/hooks/LinuxFileEvents.py b/module/plugins/hooks/LinuxFileEvents.py
deleted file mode 100644
index f4fe12de4..000000000
--- a/module/plugins/hooks/LinuxFileEvents.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- @author: mkaay
- @interface-version: 0.1
-"""
-
-from module.plugins.Hook import Hook
-import os
-
-class LinuxFileEvents(Hook):
- __name__ = "LinuxFileEvents"
- __version__ = "0.1"
- __description__ = """monitors files and directories for changes"""
- __author_name__ = ("mkaay")
- __author_mail__ = ("mkaay@mkaay.de")
-
- def __init__(self, core):
- Hook.__init__(self, core)
-
- return #@TODO remove when working correctly
-
- if not os.name == "posix":
- return
-
- self.core.check_file(self.core.make_path("container"), _("folder for container"), True)
- self.core.check_install("pyinotify", _("pyinotify for LinuxFileEvents"))
-
- try:
- import pyinotify
- except:
- return
- wm = pyinotify.WatchManager()
-
- class FileChangeHandler(pyinotify.ProcessEvent):
- def __init__(self, hook):
- self.hook = hook
-
- def process_default(self, event):
- self.hook.fileChangeEvent(event.path)
-
- notifier = pyinotify.ThreadedNotifier(wm, FileChangeHandler(self))
- notifier.start()
- mask = pyinotify.IN_MODIFY | pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO
- wm.add_watch(os.path.join(self.core.path, "links.txt"), mask)
- wm.add_watch(os.path.join(self.core.path, "container"), mask, rec=True, auto_add=True)
-
- def fileChangeEvent(self, path):
- path = os.path.abspath(path)
- if self.isValidContainer(path):
- self.addNewFile(path)
-
- def isValidContainer(self, path):
- ext = [".txt", ".dlc", ".ccf", ".rsdf"]
- for e in ext:
- if path.endswith(e):
- return True
- return False
-
- def addNewFile(self, path):
- self.core.server_methods.add_package("Container", [path])
-
diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py
new file mode 100644
index 000000000..09545d493
--- /dev/null
+++ b/module/plugins/hoster/BasePlugin.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import re
+from module.plugins.Hoster import Hoster
+
+class BasePlugin(Hoster):
+ __name__ = "BasePlugin"
+ __type__ = "hoster"
+ __pattern__ = r"^unmatchable$"
+ __version__ = "0.1"
+ __description__ = """Base Plugin when any other didnt fit"""
+ __author_name__ = ("RaNaN")
+ __author_mail__ = ("RaNaN@pyload.org")
+
+ def process(self, pyfile):
+ """main function"""
+
+ if pyfile.url.startswith("http://"):
+
+ pyfile.name = re.findall("([^\/=]+)", pyfile.url)[-1]
+ self.download(pyfile.url)
+
+ else:
+ self.fail("No Plugin matched and not a downloadable url.") \ No newline at end of file
diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py
index 6c952e2ba..978d89a37 100644
--- a/module/plugins/hoster/YoutubeCom.py
+++ b/module/plugins/hoster/YoutubeCom.py
@@ -9,6 +9,8 @@ class YoutubeCom(Hoster):
__type__ = "hoster"
__pattern__ = r"http://(www\.)?(de\.)?\youtube\.com/watch\?v=.*"
__version__ = "0.2"
+ __config__ = [ ("int", "quality" , "Quality Setting", "hd;lq"),
+ ("int", "config", "Config Settings" , "default" ) ]
__description__ = """Youtube.com Video Download Hoster"""
__author_name__ = ("spoob")
__author_mail__ = ("spoob@pyload.org")