summaryrefslogtreecommitdiffstats
path: root/module/plugins/addons
diff options
context:
space:
mode:
Diffstat (limited to 'module/plugins/addons')
-rw-r--r--module/plugins/addons/AlldebridCom.py39
-rw-r--r--module/plugins/addons/BypassCaptcha.py143
-rw-r--r--module/plugins/addons/CaptchaBrotherhood.py169
-rw-r--r--module/plugins/addons/CaptchaTrader.py8
-rw-r--r--module/plugins/addons/Checksum.py123
-rw-r--r--module/plugins/addons/DeathByCaptcha.py210
-rw-r--r--module/plugins/addons/DownloadScheduler.py78
-rw-r--r--module/plugins/addons/EasybytezCom.py18
-rw-r--r--module/plugins/addons/ExpertDecoders.py112
-rw-r--r--module/plugins/addons/ImageTyperz.py160
-rw-r--r--module/plugins/addons/LinkdecrypterCom.py54
-rw-r--r--module/plugins/addons/MultishareCz.py26
-rw-r--r--module/plugins/addons/PremiumizeMe.py65
-rw-r--r--module/plugins/addons/RealdebridCom.py36
-rw-r--r--module/plugins/addons/XFileSharingPro.py74
-rw-r--r--module/plugins/addons/ZeveraCom.py33
16 files changed, 1326 insertions, 22 deletions
diff --git a/module/plugins/addons/AlldebridCom.py b/module/plugins/addons/AlldebridCom.py
new file mode 100644
index 000000000..f9657ed8c
--- /dev/null
+++ b/module/plugins/addons/AlldebridCom.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+# should be working
+
+from module.network.RequestFactory import getURL
+from module.plugins.internal.MultiHoster import MultiHoster
+
+class AlldebridCom(MultiHoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.11"
+ __type__ = "hook"
+
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("https", "bool", "Enable HTTPS", "False"),
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "")]
+
+ __description__ = """Real-Debrid.com hook plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ replacements = [("freakshare.net", "freakshare.com")]
+
+ def getHoster(self):
+ https = "https" if self.getConfig("https") else "http"
+ page = getURL(https + "://www.alldebrid.com/api.php?action=get_host").replace("\"","").strip()
+
+ hosters = set([x.strip() for x in page.split(",") if x.strip()])
+
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hosters &= configList
+ else:
+ hosters -= configList
+
+ return list(hosters)
diff --git a/module/plugins/addons/BypassCaptcha.py b/module/plugins/addons/BypassCaptcha.py
new file mode 100644
index 000000000..24ad17dd8
--- /dev/null
+++ b/module/plugins/addons/BypassCaptcha.py
@@ -0,0 +1,143 @@
+# -*- 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, Godofdream, zoidberg
+"""
+
+from thread import start_new_thread
+from pycurl import FORM_FILE, LOW_SPEED_TIME
+
+from module.network.RequestFactory import getURL, getRequest
+from module.network.HTTPRequest import BadHeader
+
+from module.plugins.Hook import Hook
+
+PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32"
+
+class BypassCaptchaException(Exception):
+ def __init__(self, err):
+ self.err = err
+
+ def getCode(self):
+ return self.err
+
+ def __str__(self):
+ return "<BypassCaptchaException %s>" % self.err
+
+ def __repr__(self):
+ return "<BypassCaptchaException %s>" % self.err
+
+class BypassCaptcha(Hook):
+ __name__ = "BypassCaptcha"
+ __version__ = "0.03"
+ __description__ = """send captchas to BypassCaptcha.com"""
+ __config__ = [("activated", "bool", "Activated", True),
+ ("force", "bool", "Force BC even if client is connected", False),
+ ("passkey", "password", "Passkey", "")]
+ __author_name__ = ("RaNaN", "Godofdream", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "soilfcition@gmail.com", "zoidberg@mujmail.cz")
+
+ SUBMIT_URL = "http://bypasscaptcha.com/upload.php"
+ RESPOND_URL = "http://bypasscaptcha.com/check_value.php"
+ GETCREDITS_URL = "http://bypasscaptcha.com/ex_left.php"
+
+ def setup(self):
+ self.info = {}
+
+ def getCredits(self):
+ response = getURL(self.GETCREDITS_URL,
+ post = {"key": self.getConfig("passkey")}
+ )
+
+ data = dict([x.split(' ',1) for x in response.splitlines()])
+ return int(data['Left'])
+
+
+ def submit(self, captcha, captchaType="file", match=None):
+ req = getRequest()
+
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ response = req.load(self.SUBMIT_URL,
+ post={"vendor_key": PYLOAD_KEY,
+ "key": self.getConfig("passkey"),
+ "gen_task_id": "1",
+ "file": (FORM_FILE, captcha)},
+ multipart=True)
+ finally:
+ req.close()
+
+ data = dict([x.split(' ',1) for x in response.splitlines()])
+ if not data or "Value" not in data:
+ raise BypassCaptchaException(response)
+
+ result = data['Value']
+ ticket = data['TaskId']
+ self.logDebug("result %s : %s" % (ticket,result))
+
+ return ticket, result
+
+ def respond(self, ticket, success):
+ try:
+ response = getURL(self.RESPOND_URL,
+ post={"task_id": ticket,
+ "key": self.getConfig("passkey"),
+ "cv": 1 if success else 0}
+ )
+ except BadHeader, e:
+ self.logError("Could not send response.", str(e))
+
+ def newCaptchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ start_new_thread(self.processCaptcha, (task,))
+
+ else:
+ self.logInfo("Your %s account has not enough credits" % self.__name__)
+
+ def captchaCorrect(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ self.respond(task.data["ticket"], True)
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ self.respond(task.data["ticket"], False)
+
+ def processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except BypassCaptchaException, e:
+ task.error = e.getCode()
+ return
+
+ task.data["ticket"] = ticket
+ task.setResult(result) \ No newline at end of file
diff --git a/module/plugins/addons/CaptchaBrotherhood.py b/module/plugins/addons/CaptchaBrotherhood.py
new file mode 100644
index 000000000..a22a5ee1d
--- /dev/null
+++ b/module/plugins/addons/CaptchaBrotherhood.py
@@ -0,0 +1,169 @@
+# -*- 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, RaNaN, zoidberg
+"""
+from __future__ import with_statement
+
+from thread import start_new_thread
+
+import pycurl
+import StringIO
+from urllib import urlencode
+from time import sleep
+import Image
+
+from module.network.RequestFactory import getURL, getRequest
+from module.network.HTTPRequest import BadHeader
+from module.plugins.Hook import Hook
+
+class CaptchaBrotherhoodException(Exception):
+ def __init__(self, err):
+ self.err = err
+
+ def getCode(self):
+ return self.err
+
+ def __str__(self):
+ return "<CaptchaBrotherhoodException %s>" % self.err
+
+ def __repr__(self):
+ return "<CaptchaBrotherhoodException %s>" % self.err
+
+class CaptchaBrotherhood(Hook):
+ __name__ = "CaptchaBrotherhood"
+ __version__ = "0.03"
+ __description__ = """send captchas to CaptchaBrotherhood.com"""
+ __config__ = [("activated", "bool", "Activated", False),
+ ("username", "str", "Username", ""),
+ ("force", "bool", "Force CT even if client is connected", False),
+ ("passkey", "password", "Password", ""),]
+ __author_name__ = ("RaNaN", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
+
+ API_URL = "http://ocrhood.gazcad.com/"
+
+ def setup(self):
+ self.info = {}
+
+ def getCredits(self):
+ response = getURL(self.API_URL + "askCredits.aspx",
+ get = {"username": self.getConfig("username"),
+ "password": self.getConfig("passkey")})
+ if not response.startswith("OK"):
+ raise CaptchaBrotherhoodException(response)
+ else:
+ credits = int(response[3:])
+ self.logInfo(_("%d credits left") % credits)
+ self.info["credits"] = credits
+ return credits
+
+ def submit(self, captcha, captchaType="file", match=None):
+ try:
+ img = Image.open(captcha)
+ output = StringIO.StringIO()
+ self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode)
+ if img.format in ("GIF", "JPEG"):
+ img.save(output, img.format)
+ else:
+ if img.mode != "RGB":
+ img = img.convert("RGB")
+ img.save(output, "JPEG")
+ data = output.getvalue()
+ output.close()
+ except Exception, e:
+ raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e)
+
+ req = getRequest()
+
+ url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL,
+ urlencode({"username": self.getConfig("username"),
+ "password": self.getConfig("passkey"),
+ "captchaSource": "pyLoad",
+ "timeout": "80"})
+ )
+
+ req.c.setopt(pycurl.URL, url)
+ req.c.setopt(pycurl.POST, 1)
+ req.c.setopt(pycurl.POSTFIELDS, data)
+ req.c.setopt(pycurl.HTTPHEADER, [ "Content-Type: text/html" ])
+
+ try:
+ req.c.perform()
+ response = req.getResponse()
+ except Exception, e:
+ raise CaptchaBrotherhoodException("Submit captcha image failed")
+
+ req.close()
+
+ if not response.startswith("OK"):
+ raise CaptchaBrotherhoodException(response[1])
+
+ ticket = response[3:]
+
+ for i in range(15):
+ sleep(5)
+ response = self.get_api("askCaptchaResult", ticket)
+ if response.startswith("OK-answered"):
+ return ticket, response[12:]
+
+ raise CaptchaBrotherhoodException("No solution received in time")
+
+ def get_api(self, api, ticket):
+ response = getURL("%s%s.aspx" % (self.API_URL, api),
+ get={"username": self.getConfig("username"),
+ "password": self.getConfig("passkey"),
+ "captchaID": ticket}
+ )
+ if not response.startswith("OK"):
+ raise CaptchaBrotherhoodException("Unknown response: %s" % response)
+
+ return response
+
+ def newCaptchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 10:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ start_new_thread(self.processCaptcha, (task,))
+ else:
+ self.logInfo("Your CaptchaBrotherhood Account has not enough credits")
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ response = self.get_api("complainCaptcha", task.data['ticket'])
+
+ def processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except CaptchaBrotherhoodException, e:
+ task.error = e.getCode()
+ return
+
+ task.data["ticket"] = ticket
+ task.setResult(result) \ No newline at end of file
diff --git a/module/plugins/addons/CaptchaTrader.py b/module/plugins/addons/CaptchaTrader.py
index b3374ec1d..889fa38ef 100644
--- a/module/plugins/addons/CaptchaTrader.py
+++ b/module/plugins/addons/CaptchaTrader.py
@@ -46,7 +46,7 @@ class CaptchaTraderException(Exception):
class CaptchaTrader(Addon):
__name__ = "CaptchaTrader"
- __version__ = "0.13"
+ __version__ = "0.14"
__description__ = """send captchas to captchatrader.com"""
__config__ = [("activated", "bool", "Activated", True),
("username", "str", "Username", ""),
@@ -55,9 +55,9 @@ class CaptchaTrader(Addon):
__author_name__ = ("RaNaN")
__author_mail__ = ("RaNaN@pyload.org")
- SUBMIT_URL = "http://captchatrader.com/api/submit"
- RESPOND_URL = "http://captchatrader.com/api/respond"
- GETCREDITS_URL = "http://captchatrader.com/api/get_credits/username:%(user)s/password:%(password)s/"
+ SUBMIT_URL = "http://api.captchatrader.com/submit"
+ RESPOND_URL = "http://api.captchatrader.com/respond"
+ GETCREDITS_URL = "http://api.captchatrader.com/get_credits/username:%(user)s/password:%(password)s/"
def setup(self):
self.info = {}
diff --git a/module/plugins/addons/Checksum.py b/module/plugins/addons/Checksum.py
new file mode 100644
index 000000000..cb6f4bfe8
--- /dev/null
+++ b/module/plugins/addons/Checksum.py
@@ -0,0 +1,123 @@
+# -*- 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: zoidberg
+"""
+from __future__ import with_statement
+import hashlib, zlib
+from os.path import getsize, isfile
+
+from module.utils import save_join, fs_encode
+from module.plugins.Hook import Hook
+
+def computeChecksum(local_file, algorithm):
+ if algorithm in getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")):
+ h = getattr(hashlib, algorithm)()
+ chunk_size = 128 * h.block_size
+
+ with open(local_file, 'rb') as f:
+ for chunk in iter(lambda: f.read(chunk_size), ''):
+ h.update(chunk)
+
+ return h.hexdigest()
+
+ elif algorithm in ("adler32", "crc32"):
+ hf = getattr(zlib, algorithm)
+ last = 0
+
+ with open(local_file, 'rb') as f:
+ for chunk in iter(lambda: f.read(8192), ''):
+ last = hf(chunk, last)
+
+ return "%x" % last
+
+ else:
+ return None
+
+class Checksum(Hook):
+ __name__ = "Checksum"
+ __version__ = "0.05"
+ __description__ = "Verify downloaded file size and checksum (enable in general preferences)"
+ __config__ = [("activated", "bool", "Activated", True),
+ ("action", "fail;retry;nothing", "What to do if check fails?", "retry"),
+ ("max_tries", "int", "Number of retries", 2)]
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ def setup(self):
+ self.algorithms = sorted(getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")), reverse = True)
+ self.algorithms.extend(["crc32", "adler32"])
+
+ if not self.config['general']['checksum']:
+ self.logInfo("Checksum validation is disabled in general configuration")
+
+ def downloadFinished(self, pyfile):
+ """
+ Compute checksum for the downloaded file and compare it with the hash provided by the hoster.
+ pyfile.plugin.check_data should be a dictionary which can contain:
+ a) if known, the exact filesize in bytes (e.g. "size": 123456789)
+ b) hexadecimal hash string with algorithm name as key (e.g. "md5": "d76505d0869f9f928a17d42d66326307")
+ """
+ if hasattr(pyfile.plugin, "check_data") and (isinstance(pyfile.plugin.check_data, dict)):
+ data = pyfile.plugin.check_data.copy()
+ elif hasattr(pyfile.plugin, "api_data") and (isinstance(pyfile.plugin.api_data, dict)):
+ data = pyfile.plugin.api_data.copy()
+ else:
+ return
+
+ self.logDebug(data)
+
+ download_folder = self.config['general']['download_folder']
+ local_file = fs_encode(save_join(download_folder, pyfile.package().folder, pyfile.name))
+
+ if not isfile(local_file):
+ self.checkFailed(pyfile, "File does not exist")
+
+ # validate file size
+ if "size" in data:
+ api_size = int(data['size'])
+ file_size = getsize(local_file)
+ if api_size != file_size:
+ self.logWarning("File %s has incorrect size: %d B (%d expected)" % (pyfile.name, file_size, api_size))
+ self.checkFailed(pyfile, "Incorrect file size")
+ del data['size']
+
+ # validate checksum
+ if data and self.config['general']['checksum']:
+ if "checksum" in data:
+ data['md5'] = data['checksum']
+
+ for key in self.algorithms:
+ if key in data:
+ checksum = computeChecksum(local_file, key.replace("-","").lower())
+ if checksum:
+ if checksum == data[key]:
+ self.logInfo('File integrity of "%s" verified by %s checksum (%s).' % (pyfile.name, key.upper(), checksum))
+ return
+ else:
+ self.logWarning("%s checksum for file %s does not match (%s != %s)" % (key.upper(), pyfile.name, checksum, data[key]))
+ self.checkFailed(pyfile, "Checksums do not match")
+ else:
+ self.logWarning("Unsupported hashing algorithm: %s" % key.upper())
+ else:
+ self.logWarning("Unable to validate checksum for file %s" % (pyfile.name))
+
+ def checkFailed(self, pyfile, msg):
+ action = self.getConfig("action")
+ if action == "fail":
+ pyfile.plugin.fail(reason = msg)
+ elif action == "retry":
+ pyfile.plugin.retry(reason = msg, max_tries = self.getConfig("max_tries")) \ No newline at end of file
diff --git a/module/plugins/addons/DeathByCaptcha.py b/module/plugins/addons/DeathByCaptcha.py
new file mode 100644
index 000000000..59ff40ded
--- /dev/null
+++ b/module/plugins/addons/DeathByCaptcha.py
@@ -0,0 +1,210 @@
+# -*- 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, RaNaN, zoidberg
+"""
+from __future__ import with_statement
+
+from thread import start_new_thread
+from pycurl import FORM_FILE, HTTPHEADER, RESPONSE_CODE
+from time import sleep
+from base64 import b64encode
+import re
+
+from module.network.RequestFactory import getURL, getRequest
+from module.network.HTTPRequest import BadHeader
+from module.plugins.Hook import Hook
+from module.common.json_layer import json_loads
+
+class DeathByCaptchaException(Exception):
+ DBC_ERRORS = {'not-logged-in': 'Access denied, check your credentials',
+ 'invalid-credentials': 'Access denied, check your credentials',
+ 'banned': 'Access denied, account is suspended',
+ 'insufficient-funds': 'Insufficient account balance to decrypt CAPTCHA',
+ 'invalid-captcha': 'CAPTCHA is not a valid image',
+ 'service-overload': 'CAPTCHA was rejected due to service overload, try again later',
+ 'invalid-request': 'Invalid request',
+ 'timed-out': 'No CAPTCHA solution received in time' }
+
+ def __init__(self, err):
+ self.err = err
+
+ def getCode(self):
+ return self.err
+
+ def getDesc(self):
+ if self.err in self.DBC_ERRORS.keys():
+ return self.DBC_ERRORS[self.err]
+ else:
+ return self.err
+
+ def __str__(self):
+ return "<DeathByCaptchaException %s>" % self.err
+
+ def __repr__(self):
+ return "<DeathByCaptchaException %s>" % self.err
+
+class DeathByCaptcha(Hook):
+ __name__ = "DeathByCaptcha"
+ __version__ = "0.03"
+ __description__ = """send captchas to DeathByCaptcha.com"""
+ __config__ = [("activated", "bool", "Activated", False),
+ ("username", "str", "Username", ""),
+ ("passkey", "password", "Password", ""),
+ ("force", "bool", "Force DBC even if client is connected", False)]
+ __author_name__ = ("RaNaN", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
+
+ API_URL = "http://api.dbcapi.me/api/"
+
+ def setup(self):
+ self.info = {}
+
+ def call_api(self, api="captcha", post=False, multipart=False):
+ req = getRequest()
+ req.c.setopt(HTTPHEADER, ["Accept: application/json",
+ "User-Agent: pyLoad %s" % self.core.version])
+
+ if post:
+ if not isinstance(post, dict):
+ post = {}
+ post.update({"username": self.getConfig("username"),
+ "password": self.getConfig("passkey")})
+
+ response = None
+ try:
+ json = req.load("%s%s" % (self.API_URL, api),
+ post = post,
+ multipart=multipart)
+ self.logDebug(json)
+ response = json_loads(json)
+
+ if "error" in response:
+ raise DeathByCaptchaException(response['error'])
+ elif "status" not in response:
+ raise DeathByCaptchaException(str(response))
+
+ except BadHeader, e:
+ if 403 == e.code:
+ raise DeathByCaptchaException('not-logged-in')
+ elif 413 == e.code:
+ raise DeathByCaptchaException('invalid-captcha')
+ elif 503 == e.code:
+ raise DeathByCaptchaException('service-overload')
+ elif e.code in (400, 405):
+ raise DeathByCaptchaException('invalid-request')
+ else:
+ raise
+
+ finally:
+ req.close()
+
+ return response
+
+ def getCredits(self):
+ response = self.call_api("user", True)
+
+ if 'is_banned' in response and response['is_banned']:
+ raise DeathByCaptchaException('banned')
+ elif 'balance' in response and 'rate' in response:
+ self.info.update(response)
+ else:
+ raise DeathByCaptchaException(response)
+
+ def getStatus(self):
+ response = self.call_api("status", False)
+
+ if 'is_service_overloaded' in response and response['is_service_overloaded']:
+ raise DeathByCaptchaException('service-overload')
+
+ def submit(self, captcha, captchaType="file", match=None):
+ #workaround multipart-post bug in HTTPRequest.py
+ if re.match("^[A-Za-z0-9]*$", self.getConfig("passkey")):
+ multipart = True
+ data = (FORM_FILE, captcha)
+ else:
+ multipart = False
+ with open(captcha, 'rb') as f:
+ data = f.read()
+ data = "base64:" + b64encode(data)
+
+ response = self.call_api("captcha", {"captchafile": data}, multipart)
+
+ if "captcha" not in response:
+ raise DeathByCaptchaException(response)
+ ticket = response['captcha']
+
+ for i in range(24):
+ sleep(5)
+ response = self.call_api("captcha/%d" % ticket, False)
+ if response['text'] and response['is_correct']:
+ break
+ else:
+ raise DeathByCaptchaException('timed-out')
+
+ result = response['text']
+ self.logDebug("result %s : %s" % (ticket,result))
+
+ return ticket, result
+
+ def newCaptchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ try:
+ self.getStatus()
+ self.getCredits()
+ except DeathByCaptchaException, e:
+ self.logError(e.getDesc())
+ return False
+
+ balance, rate = self.info["balance"], self.info["rate"]
+ self.logInfo("Account balance: US$%.3f (%d captchas left at %.2f cents each)" % (balance / 100, balance // rate, rate))
+
+ if balance > rate:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(180)
+ start_new_thread(self.processCaptcha, (task,))
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ try:
+ response = self.call_api("captcha/%d/report" % task.data["ticket"], True)
+ except DeathByCaptchaException, e:
+ self.logError(e.getDesc())
+ except Exception, e:
+ self.logError(e)
+
+ def processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except DeathByCaptchaException, e:
+ task.error = e.getCode()
+ self.logError(e.getDesc())
+ return
+
+ task.data["ticket"] = ticket
+ task.setResult(result) \ No newline at end of file
diff --git a/module/plugins/addons/DownloadScheduler.py b/module/plugins/addons/DownloadScheduler.py
new file mode 100644
index 000000000..7cadede38
--- /dev/null
+++ b/module/plugins/addons/DownloadScheduler.py
@@ -0,0 +1,78 @@
+# -*- 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.
+ 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: zoidberg
+ Original idea by new.cze
+"""
+
+import re
+from time import localtime
+from module.plugins.Hook import Hook
+
+class DownloadScheduler(Hook):
+ __name__ = "DownloadScheduler"
+ __version__ = "0.20"
+ __description__ = """Download Scheduler"""
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("timetable", "str", "List time periods as hh:mm full or number(kB/s)", "0:00 full, 7:00 250, 10:00 0, 17:00 150")]
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ def setup(self):
+ self.cb = None # callback to scheduler job; will be by removed hookmanager when hook unloaded
+
+ def coreReady(self):
+ self.updateSchedule()
+
+ def updateSchedule(self, schedule = None):
+ if schedule is None:
+ schedule = self.getConfig("timetable")
+
+ schedule = re.findall("(\d{1,2}):(\d{2})[\s]*(-?\d+)", schedule.lower().replace("full", "-1").replace("none", "0"))
+ if not schedule:
+ self.logError("Invalid schedule")
+ return
+
+ t0 = localtime()
+ now = (t0.tm_hour, t0.tm_min, t0.tm_sec, "X")
+ schedule = sorted([(int(x[0]), int(x[1]), 0, int(x[2])) for x in schedule] + [now])
+
+ self.logDebug("Schedule", schedule)
+
+ for i, v in enumerate(schedule):
+ if v[3] == "X":
+ last, next = schedule[i-1], schedule[(i+1) % len(schedule)]
+ self.logDebug("Now/Last/Next", now, last, next)
+
+ self.setDownloadSpeed(last[3])
+
+ next_time = (((24 + next[0] - now[0])* 60 + next[1] - now[1]) * 60 + next[2] - now[2]) % 86400
+ self.core.scheduler.removeJob(self.cb)
+ self.cb = self.core.scheduler.addJob(next_time, self.updateSchedule, threaded=False)
+
+ def setDownloadSpeed(self, speed):
+ if speed == 0:
+ self.logInfo("Stopping download server. (Running downloads will not be aborted.)")
+ self.core.api.pauseServer()
+ else:
+ self.core.api.unpauseServer()
+
+ if speed > 0:
+ self.logInfo("Setting download speed to %d kB/s" % speed)
+ self.core.api.setConfigValue("download","limit_speed",1)
+ self.core.api.setConfigValue("download","max_speed",speed)
+ else:
+ self.logInfo("Setting download speed to FULL")
+ self.core.api.setConfigValue("download","limit_speed",0)
+ self.core.api.setConfigValue("download","max_speed",-1) \ No newline at end of file
diff --git a/module/plugins/addons/EasybytezCom.py b/module/plugins/addons/EasybytezCom.py
index 4dd39cca6..21a988555 100644
--- a/module/plugins/addons/EasybytezCom.py
+++ b/module/plugins/addons/EasybytezCom.py
@@ -11,11 +11,11 @@ def getConfigSet(option):
class EasybytezCom(MultiHoster):
__name__ = "EasybytezCom"
- __version__ = "0.01"
+ __version__ = "0.02"
__type__ = "hook"
__config__ = [("activated", "bool", "Activated", "False"),
- ("includeHoster", "str", "Use only for downloads from (comma-separated hosters)", ""),
- ("excludeHoster", "str", "Do not use for downloads from (comma-separated hosters)", "")]
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "")]
__description__ = """EasyBytez.com hook plugin"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -24,9 +24,13 @@ class EasybytezCom(MultiHoster):
hoster = set(['2shared.com', 'easy-share.com', 'filefactory.com', 'fileserve.com', 'filesonic.com', 'hotfile.com', 'mediafire.com', 'megaupload.com', 'netload.in', 'rapidshare.com', 'uploading.com', 'wupload.com', 'oron.com', 'uploadstation.com', 'ul.to', 'uploaded.to'])
- option = self.getConfig('includeHoster').strip()
- if option: hoster &= getConfigSet(option)
- option = self.getConfig('excludeHoster').strip()
- if option: hoster -= getConfigSet(option)
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hoster &= configList
+ else:
+ hoster -= configList
return list(hoster) \ No newline at end of file
diff --git a/module/plugins/addons/ExpertDecoders.py b/module/plugins/addons/ExpertDecoders.py
new file mode 100644
index 000000000..2e66e49ca
--- /dev/null
+++ b/module/plugins/addons/ExpertDecoders.py
@@ -0,0 +1,112 @@
+# -*- 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, RaNaN, zoidberg
+"""
+from __future__ import with_statement
+
+from thread import start_new_thread
+from pycurl import FORM_FILE, LOW_SPEED_TIME
+from uuid import uuid4
+from base64 import b64encode
+
+from module.network.RequestFactory import getURL, getRequest
+from module.network.HTTPRequest import BadHeader
+
+from module.plugins.Hook import Hook
+
+class ExpertDecoders(Hook):
+ __name__ = "ExpertDecoders"
+ __version__ = "0.01"
+ __description__ = """send captchas to expertdecoders.com"""
+ __config__ = [("activated", "bool", "Activated", False),
+ ("force", "bool", "Force CT even if client is connected", False),
+ ("passkey", "password", "Access key", ""),]
+ __author_name__ = ("RaNaN", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
+
+ API_URL = "http://www.fasttypers.org/imagepost.ashx"
+
+ def setup(self):
+ self.info = {}
+
+ def getCredits(self):
+ response = getURL(self.API_URL, post = { "key": self.getConfig("passkey"), "action": "balance" })
+
+ if response.isdigit():
+ self.logInfo(_("%s credits left") % response)
+ self.info["credits"] = credits = int(response)
+ return credits
+ else:
+ self.logError(response)
+ return 0
+
+ def processCaptcha(self, task):
+ task.data["ticket"] = ticket = uuid4()
+ result = None
+
+ with open(task.captchaFile, 'rb') as f:
+ data = f.read()
+ data = b64encode(data)
+ #self.logDebug("%s: %s : %s" % (ticket, task.captchaFile, data))
+
+ req = getRequest()
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ result = req.load(self.API_URL,
+ post={ "action": "upload",
+ "key": self.getConfig("passkey"),
+ "file": data,
+ "gen_task_id": ticket }
+ )
+ finally:
+ req.close()
+
+ self.logDebug("result %s : %s" % (ticket, result))
+ task.setResult(result)
+
+ def newCaptchaTask(self, task):
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.setWaiting(100)
+ start_new_thread(self.processCaptcha, (task,))
+
+ else:
+ self.logInfo(_("Your ExpertDecoders Account has not enough credits"))
+
+ def captchaInvalid(self, task):
+ if "ticket" in task.data:
+
+ try:
+ response = getURL(self.API_URL,
+ post={ "action": "refund",
+ "key": self.getConfig("passkey"),
+ "gen_task_id": task.data["ticket"] }
+ )
+ self.logInfo("Request refund: %s" % response)
+
+ except BadHeader, e:
+ self.logError("Could not send refund request.", str(e)) \ No newline at end of file
diff --git a/module/plugins/addons/ImageTyperz.py b/module/plugins/addons/ImageTyperz.py
new file mode 100644
index 000000000..59b6334a7
--- /dev/null
+++ b/module/plugins/addons/ImageTyperz.py
@@ -0,0 +1,160 @@
+# -*- 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, RaNaN, zoidberg
+"""
+from __future__ import with_statement
+
+from thread import start_new_thread
+from pycurl import FORM_FILE, LOW_SPEED_TIME
+
+from module.network.RequestFactory import getURL, getRequest
+from module.network.HTTPRequest import BadHeader
+
+from module.plugins.Hook import Hook
+import re
+from base64 import b64encode
+
+class ImageTyperzException(Exception):
+ def __init__(self, err):
+ self.err = err
+
+ def getCode(self):
+ return self.err
+
+ def __str__(self):
+ return "<ImageTyperzException %s>" % self.err
+
+ def __repr__(self):
+ return "<ImageTyperzException %s>" % self.err
+
+class ImageTyperz(Hook):
+ __name__ = "ImageTyperz"
+ __version__ = "0.03"
+ __description__ = """send captchas to ImageTyperz.com"""
+ __config__ = [("activated", "bool", "Activated", True),
+ ("username", "str", "Username", ""),
+ ("passkey", "password", "Password", ""),
+ ("force", "bool", "Force IT even if client is connected", False)]
+ __author_name__ = ("RaNaN", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
+
+ SUBMIT_URL = "http://captchatypers.com/Forms/UploadFileAndGetTextNEW.ashx"
+ RESPOND_URL = "http://captchatypers.com/Forms/SetBadImage.ashx"
+ GETCREDITS_URL = "http://captchatypers.com/Forms/RequestBalance.ashx"
+
+ def setup(self):
+ self.info = {}
+
+ def getCredits(self):
+ response = getURL(self.GETCREDITS_URL,
+ post = {"action": "REQUESTBALANCE",
+ "username": self.getConfig("username"),
+ "password": self.getConfig("passkey")}
+ )
+
+ if response.startswith('ERROR'):
+ raise ImageTyperzException(response)
+
+ try:
+ balance = float(response)
+ except:
+ raise ImageTyperzException("invalid response")
+
+ self.logInfo("Account balance: $%s left" % response)
+ return balance
+
+ def submit(self, captcha, captchaType="file", match=None):
+ req = getRequest()
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ #workaround multipart-post bug in HTTPRequest.py
+ if re.match("^[A-Za-z0-9]*$", self.getConfig("passkey")):
+ multipart = True
+ data = (FORM_FILE, captcha)
+ else:
+ multipart = False
+ with open(captcha, 'rb') as f:
+ data = f.read()
+ data = b64encode(data)
+
+ response = req.load(self.SUBMIT_URL,
+ post={ "action": "UPLOADCAPTCHA",
+ "username": self.getConfig("username"),
+ "password": self.getConfig("passkey"),
+ "file": data},
+ multipart = multipart)
+ finally:
+ req.close()
+
+ if response.startswith("ERROR"):
+ raise ImageTyperzException(response)
+ else:
+ data = response.split('|')
+ if len(data) == 2:
+ ticket, result = data
+ else:
+ raise ImageTyperzException("Unknown response %s" % response)
+
+ return ticket, result
+
+ def newCaptchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ start_new_thread(self.processCaptcha, (task,))
+
+ else:
+ self.logInfo("Your %s account has not enough credits" % self.__name__)
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ response = getURL(self.RESPOND_URL,
+ post={"action": "SETBADIMAGE",
+ "username": self.getConfig("username"),
+ "password": self.getConfig("passkey"),
+ "imageid": task.data["ticket"]}
+ )
+
+ if response == "SUCCESS":
+ self.logInfo("Bad captcha solution received, requested refund")
+ else:
+ self.logError("Bad captcha solution received, refund request failed", response)
+
+ def processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except ImageTyperzException, e:
+ task.error = e.getCode()
+ return
+
+ task.data["ticket"] = ticket
+ task.setResult(result) \ No newline at end of file
diff --git a/module/plugins/addons/LinkdecrypterCom.py b/module/plugins/addons/LinkdecrypterCom.py
new file mode 100644
index 000000000..ac939afd9
--- /dev/null
+++ b/module/plugins/addons/LinkdecrypterCom.py
@@ -0,0 +1,54 @@
+# -*- 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: zoidberg
+"""
+
+import re
+
+from module.plugins.Hook import Hook
+from module.network.RequestFactory import getURL
+from module.utils import remove_chars
+
+class LinkdecrypterCom(Hook):
+ __name__ = "LinkdecrypterCom"
+ __version__ = "0.14"
+ __description__ = """linkdecrypter.com - regexp loader"""
+ __config__ = [ ("activated", "bool", "Activated" , "True") ]
+ __author_name__ = ("zoidberg")
+
+ def coreReady(self):
+ page = getURL("http://linkdecrypter.com/")
+ m = re.search(r'<b>Supported</b>: <i>([^+<]*)', page)
+ if not m:
+ self.logError(_("Crypter list not found"))
+ return
+
+ online = m.group(1).split(', ')
+ builtin = [ name.lower() for name in self.core.pluginManager.crypterPlugins.keys() ]
+ builtin.extend([ "downloadserienjunkiesorg" ])
+
+ online = [ crypter.replace(".", "\\.") for crypter in online if remove_chars(crypter, "-.") not in builtin ]
+ if not online:
+ self.logError(_("Crypter list is empty"))
+ return
+
+ regexp = r"https?://([^.]+\.)*?(%s)/.*" % "|".join(online)
+
+ dict = self.core.pluginManager.crypterPlugins[self.__name__]
+ dict["pattern"] = regexp
+ dict["re"] = re.compile(regexp)
+
+ self.logDebug("REGEXP: " + regexp) \ No newline at end of file
diff --git a/module/plugins/addons/MultishareCz.py b/module/plugins/addons/MultishareCz.py
index a934f43ef..a00c6cb2b 100644
--- a/module/plugins/addons/MultishareCz.py
+++ b/module/plugins/addons/MultishareCz.py
@@ -11,26 +11,30 @@ def getConfigSet(option):
class MultishareCz(MultiHoster):
__name__ = "MultishareCz"
- __version__ = "0.01"
+ __version__ = "0.03"
__type__ = "hook"
__config__ = [("activated", "bool", "Activated", "False"),
- ("includeHoster", "str", "Use only for downloads from (bar-separated hosters)", ""),
- ("excludeHoster", "str", "Do not use for downloads from (bar-separated hosters)", "rapidshare.com|uloz.to")]
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "uloz.to")]
__description__ = """MultiShare.cz hook plugin"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
- #replacements = [("freakshare.net", "freakshare.com")]
- HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*alt="([^"]+)"></td>\s*<td class="stav"><img src="/img/loga/ok.png" alt="OK">'
+ replacements = [("share-rapid.cz", "sharerapid.com")]
+ HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="([^"]+)"></td>\s*<td class="stav">[^>]*?alt="OK"'
def getHoster(self):
page = getURL("http://www.multishare.cz/monitoring/")
- hoster = set(m.group(1).lower() for m in re.finditer(self.HOSTER_PATTERN, page))
+ hosters = set(h.lower().strip() for h in re.findall(self.HOSTER_PATTERN, page))
- option = self.getConfig('includeHoster').strip()
- if option: hoster &= getConfigSet(option)
- option = self.getConfig('excludeHoster').strip()
- if option: hoster -= getConfigSet(option)
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hosters &= configList
+ elif configMode == "unlisted":
+ hosters -= configList
- return list(hoster) \ No newline at end of file
+ return list(hosters) \ No newline at end of file
diff --git a/module/plugins/addons/PremiumizeMe.py b/module/plugins/addons/PremiumizeMe.py
new file mode 100644
index 000000000..3825e9219
--- /dev/null
+++ b/module/plugins/addons/PremiumizeMe.py
@@ -0,0 +1,65 @@
+from module.plugins.internal.MultiHoster import MultiHoster
+
+from module.common.json_layer import json_loads
+from module.network.RequestFactory import getURL
+
+class PremiumizeMe(MultiHoster):
+ __name__ = "PremiumizeMe"
+ __version__ = "0.1"
+ __type__ = "hook"
+ __description__ = """Premiumize.Me hook plugin"""
+
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "")]
+
+ __author_name__ = ("Florian Franzen")
+ __author_mail__ = ("FlorianFranzen@gmail.com")
+
+ replacements = [("freakshare.net", "freakshare.com")]
+
+ interval = 0 # Disable periodic calls, we dont use them anyway
+
+ def getHoster(self):
+ # If no accounts are available there will be no hosters available
+ if not self.account or not self.account.canUse():
+ return []
+
+ # Get account data
+ (user, data) = self.account.selectAccount()
+
+ # Get supported hosters list from premiumize.me using the json API v1 (see https://secure.premiumize.me/?show=api)
+ answer = getURL("https://api.premiumize.me/pm-api/v1.php?method=hosterlist&params[login]=%s&params[pass]=%s" % (user, data['password']))
+ data = json_loads(answer)
+
+
+ # If account is not valid thera are no hosters available
+ if data['status'] != 200:
+ return []
+
+ # Extract hosters from json file
+ hosters = set(data['result']['hosterlist'])
+
+
+ # Read config to check if certain hosters should not be handled
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hosters &= configList
+ else:
+ hosters -= configList
+
+ return list(hosters)
+
+ def coreReady(self):
+ # Get account plugin and check if there is a valid account available
+ self.account = self.core.accountManager.getAccountPlugin("PremiumizeMe")
+ if not self.account.canUse():
+ self.account = None
+ self.logError(_("Please add a valid premiumize.me account first and restart pyLoad."))
+ return
+
+ # Run the overwriten core ready which actually enables the multihoster hook
+ return MultiHoster.coreReady(self) \ No newline at end of file
diff --git a/module/plugins/addons/RealdebridCom.py b/module/plugins/addons/RealdebridCom.py
new file mode 100644
index 000000000..bd3179673
--- /dev/null
+++ b/module/plugins/addons/RealdebridCom.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+from module.network.RequestFactory import getURL
+from module.plugins.internal.MultiHoster import MultiHoster
+
+class RealdebridCom(MultiHoster):
+ __name__ = "RealdebridCom"
+ __version__ = "0.41"
+ __type__ = "hook"
+
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("https", "bool", "Enable HTTPS", "False"),
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "")]
+ __description__ = """Real-Debrid.com hook plugin"""
+ __author_name__ = ("Devirex, Hazzard")
+ __author_mail__ = ("naibaf_11@yahoo.de")
+
+ replacements = [("freakshare.net", "freakshare.com")]
+
+ def getHoster(self):
+ https = "https" if self.getConfig("https") else "http"
+ page = getURL(https + "://real-debrid.com/api/hosters.php").replace("\"","").strip()
+
+ hosters = set([x.strip() for x in page.split(",") if x.strip()])
+
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hosters &= configList
+ else:
+ hosters -= configList
+
+ return list(hosters)
diff --git a/module/plugins/addons/XFileSharingPro.py b/module/plugins/addons/XFileSharingPro.py
new file mode 100644
index 000000000..3981db2d0
--- /dev/null
+++ b/module/plugins/addons/XFileSharingPro.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+
+from module.plugins.Hook import Hook
+import re
+
+class XFileSharingPro(Hook):
+ __name__ = "XFileSharingPro"
+ __version__ = "0.03"
+ __type__ = "hook"
+ __config__ = [ ("activated" , "bool" , "Activated" , "True"),
+ ("loadDefault", "bool", "Include default (built-in) hoster list" , "True"),
+ ("includeList", "str", "Include hosters (comma separated)", ""),
+ ("excludeList", "str", "Exclude hosters (comma separated)", "") ]
+ __description__ = """Hoster URL pattern loader for the generic XFileSharingPro plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ def coreReady(self):
+ self.loadPattern()
+
+ def loadPattern(self):
+ hosterList = self.getConfigSet('includeList')
+ excludeList = self.getConfigSet('excludeList')
+
+ if self.getConfig('loadDefault'):
+ hosterList |= set((
+ #WORKING HOSTERS:
+ "azsharing.com", "banashare.com", "fileband.com", "kingsupload.com", "migahost.com", "ryushare.com", "xfileshare.eu",
+ #NOT TESTED:
+ "aieshare.com", "amonshare.com", "asixfiles.com",
+ "bebasupload.com", "boosterking.com", "buckshare.com", "bulletupload.com", "crocshare.com", "ddlanime.com", "divxme.com",
+ "dopeshare.com", "downupload.com", "eyesfile.com", "eyvx.com", "fik1.com", "file4safe.com", "file4sharing.com",
+ "fileforth.com", "filemade.com", "filemak.com", "fileplaygroud.com", "filerace.com", "filestrack.com",
+ "fileupper.com", "filevelocity.com", "fooget.com", "4bytez.com", "freefilessharing.com", "glumbouploads.com", "grupload.com",
+ "heftyfile.com", "hipfile.com", "host4desi.com", "hulkshare.com", "idupin.com", "imageporter.com", "isharefast.com",
+ "jalurcepat.com", "laoupload.com", "linkzhost.com", "loombo.com", "maknyos.com",
+ "mlfat4arab.com", "movreel.com", "netuploaded.com", "ok2upload.com", "180upload.com", "1hostclick.com", "ovfile.com",
+ "putshare.com", "pyramidfiles.com", "q4share.com", "queenshare.com", "ravishare.com", "rockdizfile.com", "sendmyway.com",
+ "share76.com", "sharebeast.com", "sharehut.com", "sharerun.com", "shareswift.com", "sharingonline.com", "6ybh-upload.com",
+ "skipfile.com", "spaadyshare.com", "space4file.com", "speedoshare.com", "uploadbaz.com", "uploadboost.com", "uploadc.com",
+ "uploaddot.com", "uploadfloor.com", "uploadic.com", "uploadville.com", "uptobox.com", "vidbull.com", "zalaa.com",
+ "zomgupload.com", "kupload.org", "movbay.org", "multishare.org", "omegave.org", "toucansharing.org", "uflinq.org",
+ "banicrazy.info", "flowhot.info", "upbrasil.info", "shareyourfilez.biz", "bzlink.us", "cloudcache.cc", "fileserver.cc"
+ "farshare.to", "kingshare.to", "filemaze.ws", "filehost.ws", "goldfile.eu", "filestock.ru", "moidisk.ru"
+ "4up.me", "kfiles.kz", "odsiebie.pl", "upchi.co.il", "upit.in", "verzend.be"
+ ))
+
+ #NOT WORKING:
+ """
+ """
+
+ hosterList -= (excludeList)
+ hosterList -= set(('', u''))
+
+ if not hosterList:
+ self.unload()
+ return
+
+ regexp = r"http://(?:[^/]*\.)?(%s)/\w{12}" % ("|".join(sorted(hosterList)).replace('.','\.'))
+ #self.logDebug(regexp)
+
+ dict = self.core.pluginManager.hosterPlugins['XFileSharingPro']
+ dict["pattern"] = regexp
+ dict["re"] = re.compile(regexp)
+ self.logDebug("Pattern loaded - handling %d hosters" % len(hosterList))
+
+ def getConfigSet(self, option):
+ s = self.getConfig(option).lower().replace('|',',').replace(';',',')
+ return set([x.strip() for x in s.split(',')])
+
+ def unload(self):
+ dict = self.core.pluginManager.hosterPlugins['XFileSharingPro']
+ dict["pattern"] = r"^unmatchable$"
+ dict["re"] = re.compile(r"^unmatchable$") \ No newline at end of file
diff --git a/module/plugins/addons/ZeveraCom.py b/module/plugins/addons/ZeveraCom.py
new file mode 100644
index 000000000..46c752c21
--- /dev/null
+++ b/module/plugins/addons/ZeveraCom.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+from module.network.RequestFactory import getURL
+from module.plugins.internal.MultiHoster import MultiHoster
+
+class ZeveraCom(MultiHoster):
+ __name__ = "ZeveraCom"
+ __version__ = "0.01"
+ __type__ = "hook"
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"),
+ ("hosterList", "str", "Hoster list (comma separated)", "")]
+ __description__ = """Real-Debrid.com hook plugin"""
+ __author_name__ = ("Devirex, Hazzard")
+ __author_mail__ = ("naibaf_11@yahoo.de")
+
+ replacements = [("freakshare.net", "freakshare.com"), ("2shared.com", "twoshared.com"), ("4shared.com", "fourshared.com"),
+ ("easy-share.com", "crocko.com"), ("hellshare.com", "hellshare.cz")]
+
+ def getHoster(self):
+ page = getURL("http://www.zevera.com/jDownloader.ashx?cmd=gethosters")
+ hosters = set([x.strip() for x in page.replace("\"", "").split(",")])
+
+ configMode = self.getConfig('hosterListMode')
+ if configMode in ("listed", "unlisted"):
+ configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(','))
+ configList.discard(u'')
+ if configMode == "listed":
+ hosters &= configList
+ else:
+ hosters -= configList
+
+ return list(hosters) \ No newline at end of file