diff options
Diffstat (limited to 'module/plugins/Plugin.py')
-rw-r--r-- | module/plugins/Plugin.py | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/module/plugins/Plugin.py b/module/plugins/Plugin.py new file mode 100644 index 000000000..1f680032a --- /dev/null +++ b/module/plugins/Plugin.py @@ -0,0 +1,268 @@ +# -*- 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: RaNaN, spoob, mkaay +""" + +import logging +from os.path import exists +from os.path import join + +from time import time +from time import sleep + +from random import randint + +import sys +from os.path import exists + +from os import remove +from os import makedirs + +from tempfile import NamedTemporaryFile +from mimetypes import guess_type + +from itertools import islice + +def chunks(iterable, size): + it = iter(iterable) + item = list(islice(it, size)) + while item: + yield item + item = list(islice(it, size)) + +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 + __type__ = "hoster" + __config__ = [ ("name", "type", "desc" , "default") ] + __description__ = """Base Plugin""" + __author_name__ = ("RaNaN", "spoob", "mkaay") + __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "mkaay@mkaay.de") + + + def __init__(self, pyfile): + self.config = pyfile.m.core.config + self.core = pyfile.m.core + + self.wantReconnect = False + self.multiDL = True + + self.waitUntil = 0 # time() + wait in seconds + self.waiting = False + + self.premium = False + + self.ocr = None # captcha reader instance + self.account = pyfile.m.core.accountManager.getAccountPlugin(self.__name__) # account handler instance + if self.account and not self.account.canUse(): self.account = None + if self.account: + self.req = self.account.getAccountRequest(self) + else: + self.req = pyfile.m.core.requestFactory.getRequest(self.__name__) + + self.log = logging.getLogger("log") + + self.pyfile = pyfile + self.thread = None # holds thread in future + + self.setup() + + def __call__(self): + return self.__name__ + + def setup(self): + """ more init stuff if needed """ + pass + + def preprocessing(self, thread): + """ handles important things to do before starting """ + self.thread = thread + + if not self.account: + self.req.clearCookies() + + self.pyfile.setStatus("starting") + + return self.process(self.pyfile) + + #---------------------------------------------------------------------- + def process(self, pyfile): + """the 'main' method of every plugin""" + raise NotImplementedError + + def resetAccount(self): + self.account = None + self.req = self.core.requestFactory.getRequest(self.__name__) + + def checksum(self, local_file=None): + """ + return codes: + 0 - checksum ok + 1 - checksum wrong + 5 - can't get checksum + 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 setConfig(self, option, value): + """ sets a config value """ + self.setConf(option, value) + + def getConfig(self, option): + """ gets a config value """ + return self.getConf(option) + + + def setWait(self, seconds, reconnect=False): + """ set the wait time to specified seconds """ + if reconnect: + self.wantReconnect = True + self.pyfile.waitUntil = time() + int(seconds) + + def wait(self): + """ waits the time previously set """ + self.waiting = True + self.pyfile.setStatus("waiting") + + while self.pyfile.waitUntil > time(): + self.thread.m.reconnecting.wait(2) + + if self.pyfile.abort: raise Abort + if self.thread.m.reconnecting.isSet(): + self.waiting = False + self.wantReconnect = False + raise Reconnect + + self.waiting = False + self.pyfile.setStatus("starting") + + 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 decryptCaptcha(self, url, get={}, post={}, cookies=False, forceUser=False): + """ loads the catpcha and decrypt it or ask the user for input """ + + content = self.load(url, get=get, post=post, cookies=cookies) + + temp = NamedTemporaryFile() + temp = open(join("tmp","tmpCaptcha_%s" % self.__name__ ), "wb") + + temp.write(content) + temp.close() + + + Ocr = self.core.pluginManager.getCaptchaPlugin(self.__name__) + if Ocr and not forceUser: + sleep(randint(3000, 5000) / 1000.0) + if self.pyfile.abort: raise Abort + + ocr = Ocr() + result = ocr.get_captcha(temp.name) + else: + captchaManager = self.core.captchaManager + mime = guess_type(temp.name) + task = captchaManager.newTask(self) + task.setCaptcha(content, mime[0]) + task.setWaiting() + while not task.getStatus() == "done": + if not self.core.isClientConnected(): + task.removeTask() + #temp.unlink(temp.name) + self.fail(_("No Client connected for captcha decrypting.")) + if self.pyfile.abort: raise Abort + sleep(1) + result = task.getResult() + task.removeTask() + + if not self.core.debug: + try: + remove(temp.name) + except: + pass + + return result + + + def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False): + """ returns the content loaded """ + if self.pyfile.abort: raise Abort + + return self.req.load(url, get, post, ref, cookies, just_header) + + def download(self, url, get={}, post={}, ref=True, cookies=True): + """ downloads the url content to disk """ + + self.pyfile.setStatus("downloading") + + download_folder = self.config['general']['download_folder'] + + location = join(download_folder, self.pyfile.package().folder.decode(sys.getfilesystemencoding().replace(":", ""))) # remove : for win compability + + if not exists(location): + makedirs(location) + + newname = self.req.download(url, self.pyfile.name, location, get, post, ref, cookies) + + self.pyfile.size = self.req.dl_size + + if newname: + self.pyfile.name = newname |