diff options
-rw-r--r-- | module/network/HTTPRequest.py | 1 | ||||
-rw-r--r-- | module/plugins/accounts/AlldebridCom.py | 27 | ||||
-rw-r--r-- | module/plugins/accounts/BayfilesCom.py | 17 | ||||
-rw-r--r-- | module/plugins/hooks/AlldebridCom.py | 26 | ||||
-rw-r--r-- | module/plugins/hoster/AlldebridCom.py | 65 | ||||
-rw-r--r-- | module/plugins/hoster/BitshareCom.py | 2 | ||||
-rw-r--r-- | module/plugins/hoster/CramitIn.py | 20 | ||||
-rw-r--r-- | module/plugins/hoster/EasybytezCom.py | 106 | ||||
-rw-r--r-- | module/plugins/hoster/FiledinoCom.py | 18 | ||||
-rw-r--r-- | module/plugins/hoster/FreakshareCom.py | 27 | ||||
-rw-r--r-- | module/plugins/hoster/RarefileNet.py | 26 | ||||
-rw-r--r-- | module/plugins/hoster/XFileSharingPro.py | 224 | ||||
-rw-r--r-- | module/plugins/internal/SimpleHoster.py | 54 |
13 files changed, 482 insertions, 131 deletions
diff --git a/module/network/HTTPRequest.py b/module/network/HTTPRequest.py index 40f18f2a5..d4c33bbff 100644 --- a/module/network/HTTPRequest.py +++ b/module/network/HTTPRequest.py @@ -31,6 +31,7 @@ def myquote(url): return quote(url.encode('utf_8') if isinstance(url, unicode) else url, safe="%/:=&?~#+!$,;'@()*[]") def myurlencode(data): + data = dict(data) return urlencode(dict((x.encode('utf_8') if isinstance(x, unicode) else x, \ y.encode('utf_8') if isinstance(y, unicode) else y ) for x, y in data.iteritems())) diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py new file mode 100644 index 000000000..4968e9bdd --- /dev/null +++ b/module/plugins/accounts/AlldebridCom.py @@ -0,0 +1,27 @@ +from module.plugins.Account import Account
+import xml.dom.minidom as dom
+from time import time
+
+class AlldebridCom(Account):
+ __name__ = "AlldebridCom"
+ __version__ = "0.1"
+ __type__ = "account"
+ __description__ = """AllDebrid.com account plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ def loadAccountInfo(self, user, req):
+ data = self.getAccountData(user)
+ page = req.load("http://www.alldebrid.com/api.php?action=info_user&login=%s&pw=%s" % (user, data["password"]))
+ self.log.debug(page)
+ xml = dom.parseString(page)
+ account_info = {"validuntil": (time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400),
+ "trafficleft": -1}
+
+ return account_info
+
+ def login(self, user, data, req):
+ page = req.load("http://www.alldebrid.com/register/?action=login&login_login=%s&login_password=%s" % (user, data["password"]))
+
+ if "This login doesn't exist" in page:
+ self.wrongPassword()
diff --git a/module/plugins/accounts/BayfilesCom.py b/module/plugins/accounts/BayfilesCom.py index 803e602cb..0d036488b 100644 --- a/module/plugins/accounts/BayfilesCom.py +++ b/module/plugins/accounts/BayfilesCom.py @@ -20,23 +20,28 @@ from module.plugins.Account import Account from module.common.json_layer import json_loads import re -from time import mktime, strptime +from time import time, mktime, strptime class BayfilesCom(Account): __name__ = "BayfilesCom" - __version__ = "0.01" + __version__ = "0.02" __type__ = "account" __description__ = """bayfiles.com account plugin""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") def loadAccountInfo(self, user, req): - response = json_loads(req.load("http://api.bayfiles.com/v1/account/info")) - self.logDebug(response) - + for i in range(2): + response = json_loads(req.load("http://api.bayfiles.com/v1/account/info")) + self.logDebug(response) + if not response["error"]: + break + self.logWarning(response["error"]) + self.relogin() + return {"premium": bool(response['premium']), \ "trafficleft": -1, \ - "validuntil": response['expires'] if response['expires'] > 0 else -1} + "validuntil": response['expires'] if response['expires'] >= int(time()) else -1} def login(self, user, data, req): response = json_loads(req.load("http://api.bayfiles.com/v1/account/login/%s/%s" % (user, data["password"]))) diff --git a/module/plugins/hooks/AlldebridCom.py b/module/plugins/hooks/AlldebridCom.py new file mode 100644 index 000000000..d3d6ff294 --- /dev/null +++ b/module/plugins/hooks/AlldebridCom.py @@ -0,0 +1,26 @@ +# -*- 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.1" + __type__ = "hook" + + __config__ = [("activated", "bool", "Activated", "False"), + ("https", "bool", "Enable HTTPS", "False")] + + __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() + + return[x.strip() for x in page.split(",") if x.strip()] diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py new file mode 100644 index 000000000..56e3a9040 --- /dev/null +++ b/module/plugins/hoster/AlldebridCom.py @@ -0,0 +1,65 @@ +#!/usr/nv python
+# -*- coding: utf-8 -*-
+
+import BeautifulSoup
+from urllib import quote, unquote
+from random import randrange
+
+from module.plugins.Hoster import Hoster
+
+class AlldebridCom(Hoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.1"
+ __type__ = "hoster"
+
+ __pattern__ = r"https?://.*alldebrid\..*"
+ __description__ = """Alldebrid.com hoster plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if name.endswith("..."): #incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100,999)
+ return name
+
+ def init(self):
+ self.tries = 0
+ self.chunkLimit = 3
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ url="http://www.alldebrid.com/service.php?link=%s" %(pyfile.url)
+
+ page = self.load(url)
+
+ soup = BeautifulSoup.BeautifulSoup(page)
+ for link in soup.findAll("a"):
+ new_url = link.get("href")
+
+
+ if self.getConfig("https"):
+ new_url = new_url.replace("http://", "https://")
+ else:
+ new_url = new_url.replace("https://", "http://")
+
+ self.log.debug("AllDebrid: New URL: %s" % new_url)
+
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(new_url)
+
+ self.download(new_url, disposition=True)
+
+ check = self.checkDownload(
+ {"error": "<title>An error occured while processing your request</title>"})
+
+ if check == "error":
+ #usual this download can safely be retried
+ self.retry(reason="An error occured while generating link.", wait_time=60)
+
diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py index 794e978b2..d6288883d 100644 --- a/module/plugins/hoster/BitshareCom.py +++ b/module/plugins/hoster/BitshareCom.py @@ -92,6 +92,8 @@ class BitshareCom(Hoster): self.handleFree() def handleFree(self): + if "Only Premium members can access this file" in self.html: + self.fail("Only Premium members can access this file") # Get download info self.logDebug("Getting download info") diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py new file mode 100644 index 000000000..a7935c744 --- /dev/null +++ b/module/plugins/hoster/CramitIn.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class CramitIn(XFileSharingPro): + __name__ = "CramitIn" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*cramit.in/\w{12}" + __version__ = "0.03" + __description__ = """Cramit.in hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)' + DIRECT_LINK_PATTERN = r'href="(http://cramit.in/file_download/.*?)"' + HOSTER_NAME = "cramit.in" + + def setup(self): + self.multiDL = self.premium + +getInfo = create_getInfo(CramitIn)
\ No newline at end of file diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py index 4fbd08756..25de9b341 100644 --- a/module/plugins/hoster/EasybytezCom.py +++ b/module/plugins/hoster/EasybytezCom.py @@ -16,129 +16,59 @@ @author: zoidberg """ -import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from random import random +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo -class EasybytezCom(SimpleHoster): +class EasybytezCom(XFileSharingPro): __name__ = "EasybytezCom" __type__ = "hoster" __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w+).*" - __version__ = "0.05" + __version__ = "0.06" __description__ = """easybytez.com""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - - # shares code with TurbouploadCom FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"' FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>' FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' - FILE_OFFLINE_PATTERN = r'<h2>File Not Found</h2>' - FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)"[^>]*value="([^"]*)"' - WAIT_PATTERN = r'<span id="countdown_str">[^>]*>(\d+)</span> seconds</span>' DIRECT_LINK_PATTERN = r'(http://(\w+\.easybytez\.com|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)' - - FORM_PATTERN = r'<form name=["\']?%s[^>]*action=["\']?([^"\' ]+)(.*?)</form>' OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' - TEXTAREA_PATTERN = r"<textarea name='([^']+)'>([^<]+)</textarea>" - - HOSTER_URL = "www.easybytez.com" - - def process(self, pyfile): - if not re.match(self.__pattern__, self.pyfile.url): - if self.premium: - self.handleOverriden() - else: - self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_URL) - else: - self.html = self.load(pyfile.url, cookies = False, decode = True) - self.file_info = self.getFileInfo() - - header = self.load(self.pyfile.url, just_header = True, cookies = True) - self.logDebug(header) - - if 'location' in header and re.match(self.DIRECT_LINK_PATTERN, header['location']): - self.downloadLink(header['location']) - elif self.premium: - self.handlePremium() - else: - self.handleFree() - def handleFree(self): - self.download(self.pyfile.url, post = self.getPostParameters(), ref = True, cookies = True) + HOSTER_NAME = "easybytez.com" + def setup(self): + self.resumeDownload = self.multiDL = self.premium + def handlePremium(self): - self.html = self.load(self.pyfile.url, post = self.getPostParameters(premium=True)) + self.html = self.load(self.pyfile.url, post = self.getPostParameters()) found = re.search(self.DIRECT_LINK_PATTERN, self.html) if not found: self.parseError('DIRECT LINK') - self.downloadLink(found.group(1)) - + self.startDownload(found.group(1)) + def handleOverriden(self): self.html = self.load(self.HOSTER_URL) - action, form = re.search(self.FORM_PATTERN % "url", self.html, re.DOTALL).groups() - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) + action, inputs = self.parseHtmlForm('') upload_id = "%012d" % int(random()*10**12) - action += upload_id + "&js_on=1&utype=prem&upload_type=url" + action += upload_id + "&js_on=1&utype=prem&upload_type=url" inputs['tos'] = '1' inputs['url_mass'] = self.pyfile.url - inputs['up1oad_type'] = 'url' - + inputs['up1oad_type'] = 'url' + self.logDebug(action, inputs) self.html = self.load(action, post = inputs) - - found = re.search(self.FORM_PATTERN % "F1", self.html, re.S | re.I) - if not found: - self.logDebug(self.html) - self.fail("upload failed") - action, form = found.groups() - - inputs = dict(re.findall(self.TEXTAREA_PATTERN, form)) + + action, inputs = self.parseHtmlForm('name="F1"') if not inputs: parseError('TEXTAREA') - self.logDebug(inputs) + self.logDebug(inputs) if inputs['st'] == 'OK': self.html = self.load(action, post = inputs) else: self.fail(inputs['st']) - + found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html) if not found: self.parseError('DIRECT LINK (OVR)') self.pyfile.url = found.group(1) self.retry() - - def downloadLink(self, link): - self.logDebug('DIRECT LINK: %s' % link) - self.download(link) - - def getPostParameters(self, premium=False): - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html)) - self.logDebug(inputs) - - if 'op' in inputs and inputs['op'] == 'download2': return inputs - - inputs['referer'] = self.pyfile.url - - if premium: - inputs['method_premium'] = "Premium Download" - if 'method_free' in inputs: del inputs['method_free'] - else: - inputs['method_free'] = "Free Download" - if 'method_premium' in inputs: del inputs['method_premium'] - - self.html = self.load(self.pyfile.url, post = inputs, ref = True, cookies = True) - inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html)) - self.logDebug(inputs) - - if not premium: - found = re.search(self.WAIT_PATTERN, self.html) - self.setWait(int(found.group(1)) + 1 if found else 60) - self.wait() - - return inputs - - def urlParseFileName(self): - return html_unescape(urlparse(self.pyfile.url).path.split("/")[-1]) getInfo = create_getInfo(EasybytezCom)
\ No newline at end of file diff --git a/module/plugins/hoster/FiledinoCom.py b/module/plugins/hoster/FiledinoCom.py new file mode 100644 index 000000000..7d1a82df4 --- /dev/null +++ b/module/plugins/hoster/FiledinoCom.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + +class FiledinoCom(XFileSharingPro): + __name__ = "FiledinoCom" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*filedino.com/\w{12}" + __version__ = "0.01" + __description__ = """FileDino.com hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_SIZE_PATTERN = r'File Size : </span><span class="runninggreysmall">(?P<S>.+?)</span>' + + HOSTER_NAME = "filedino.com" + DIRECT_LINK_PATTERN = r'http://www\.filedino\.com/cgi-bin/dl\.cgi/' + +getInfo = create_getInfo(FiledinoCom)
\ No newline at end of file diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py index 869b8a99e..a36fe7207 100644 --- a/module/plugins/hoster/FreakshareCom.py +++ b/module/plugins/hoster/FreakshareCom.py @@ -9,7 +9,7 @@ class FreakshareCom(Hoster): __name__ = "FreakshareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/"
- __version__ = "0.33"
+ __version__ = "0.34"
__description__ = """Freakshare.com Download Hoster"""
__author_name__ = ("sitacuisses","spoob","mkaay")
__author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de")
@@ -36,10 +36,15 @@ class FreakshareCom(Hoster): self.download(self.pyfile.url, post=self.req_opts)
- check = self.checkDownload({"bad": "bad try"})
+ check = self.checkDownload({"bad": "bad try",
+ "paralell": "> Sorry, you cant download more then 1 files at time. <"})
+
if check == "bad":
self.fail("Bad Try.")
-
+ if check == "paralell":
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
def prepare(self):
pyfile = self.pyfile
@@ -134,10 +139,7 @@ class FreakshareCom(Hoster): def get_download_options(self):
re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>", self.html).group(0) #get the whole request
to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope)
- request_options = []
-
- for item in to_sort: #Name value pairs are output reversed from regex, so we reorder them
- request_options.append((item[1], item[0]))
+ request_options = {n: v for v, n in to_sort}
herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
@@ -146,21 +148,16 @@ class FreakshareCom(Hoster): # fp.write(herewego)
to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
- request_options = []
+ request_options = {n: v for v, n in to_sort}
# comment this in, when it doesnt work as well
#print "\n\n%s\n\n" % ";".join(["%s=%s" % x for x in to_sort])
-
- for item in to_sort: #Same as above
- request_options.append((item[1], item[0]))
challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego)
if challenge:
re_captcha = ReCaptcha(self)
- challenge, result = re_captcha.challenge(challenge.group(1))
-
- request_options.append(("recaptcha_challenge_field", challenge))
- request_options.append(("recaptcha_response_field", result))
+ request_options["recaptcha_challenge_field"], request_options["recaptcha_response_field"] \
+ = re_captcha.challenge(challenge.group(1))
return request_options
diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py new file mode 100644 index 000000000..8339d40eb --- /dev/null +++ b/module/plugins/hoster/RarefileNet.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +import re +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +from module.utils import html_unescape + +class RarefileNet(XFileSharingPro): + __name__ = "RarefileNet" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*rarefile.net/\w{12}" + __version__ = "0.01" + __description__ = """Rarefile.net hoster plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_NAME_PATTERN = r'<td><font color="red">(?P<N>.*?)</font></td>' + FILE_SIZE_PATTERN = r'<td>Size : (?P<S>.+?) ' + + def handleCaptcha(self, inputs): + captcha_div = re.search(r'<b>Enter code.*?<div.*?>(.*?)</div>', self.html, re.S).group(1) + self.logDebug(captcha_div) + numerals = re.findall('<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div)) + inputs['code'] = "".join([a[1] for a in sorted(numerals, key = lambda num: int(num[0]))]) + self.logDebug("CAPTCHA", inputs['code'], numerals) + return 3 + +getInfo = create_getInfo(RarefileNet)
\ No newline at end of file diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py new file mode 100644 index 000000000..c7a59c81e --- /dev/null +++ b/module/plugins/hoster/XFileSharingPro.py @@ -0,0 +1,224 @@ +# -*- 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 random import random +from urllib import unquote +from pycurl import FOLLOWLOCATION +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.ReCaptcha import ReCaptcha + +class XFileSharingPro(SimpleHoster): + """ + Common base for XFileSharingPro hosters like EasybytezCom, CramitIn, FiledinoCom... + Some hosters may work straight away when added to __pattern__ + """ + __name__ = "XFileSharingPro" + __type__ = "hoster" + __pattern__ = r"http://(?:\w*\.)*(boosterking\.com|migahost\.com|fileband\.com|ravishare\.com)/\w{12}" + __version__ = "0.01" + __description__ = """XFileSharingPro common hoster base""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"' + FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>' + FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' + FILE_OFFLINE_PATTERN = r'<(b|h2)>File Not Found</(b|h2)>' + + WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>' + OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' + OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' + CAPTCHA_URL_PATTERN = r'(http://[^"\']+?/captchas/[^"\']+)' + RECAPTCHA_URL_PATTERN = r'http://[^"\']+?recaptcha[^"\']+?\?k=([^"\']+)"' + ERROR_PATTERN = r'class="err">(.*?)<' + + DIRECT_LINK_PATTERN = r'This direct link.*?href=["\'](.*?)["\']' + + def setup(self): + self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1) + self.multiDL = True + + def process(self, pyfile): + self.captcha = self.errmsg = None + self.passwords = self.getPassword().splitlines() + + if not re.match(self.__pattern__, self.pyfile.url): + if self.premium: + self.handleOverriden() + else: + self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_NAME) + else: + self.html = self.load(pyfile.url, cookies = False, decode = True) + self.file_info = self.getFileInfo() + + self.header = self.load(self.pyfile.url, just_header = True, cookies = True) + self.logDebug(self.header) + + if 'location' in self.header and re.match(self.DIRECT_LINK_PATTERN, self.header['location']): + self.startDownload(self.header['location']) + elif self.premium: + self.handlePremium() + else: + self.handleFree() + + def handleFree(self): + for i in range(5): + data = self.getPostParameters() + + self.req.http.c.setopt(FOLLOWLOCATION, 0) + self.html = self.load(self.pyfile.url, post = data, ref = True) + self.header = self.req.http.header + self.req.http.c.setopt(FOLLOWLOCATION, 1) + + found = re.search("Location\s*:\s*(.*)", self.header, re.I) + if found: + break + elif not self.checkErrors(): + found = re.search(self.DIRECT_LINK_PATTERN, self.html, re.S) + if not found: self.parseError('Download Link') + break + + else: self.fail("No valid captcha code entered") + + self.startDownload(found.group(1)) + + def handlePremium(self): + self.html = self.load(self.pyfile.url, post = self.getPostParameters()) + found = re.search(self.DIRECT_LINK_PATTERN, self.html) + if not found: self.parseError('DIRECT LINK') + self.startDownload(found.group(1)) + + def handleOverriden(self): + self.html = self.load("http://www.%s" % self.HOSTER_NAME) + action, inputs = self.parseHtmlForm('') + upload_id = "%012d" % int(random()*10**12) + action += upload_id + "&js_on=1&utype=prem&upload_type=url" + inputs['tos'] = '1' + inputs['url_mass'] = self.pyfile.url + inputs['up1oad_type'] = 'url' + + self.logDebug(action, inputs) + self.html = self.load(action, post = inputs) + + action, inputs = self.parseHtmlForm('name="F1"') + if not inputs: parseError('TEXTAREA') + self.logDebug(inputs) + if inputs['st'] == 'OK': + self.html = self.load(action, post = inputs) + else: + self.fail(inputs['st']) + + found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html) + if not found: self.parseError('DIRECT LINK (OVR)') + self.pyfile.url = found.group(1) + self.retry() + + def startDownload(self, link): + if self.captcha: self.correctCaptcha() + self.logDebug('DIRECT LINK: %s' % link) + self.download(link) + + def checkErrors(self): + found = re.search(self.ERROR_PATTERN, self.html) + if found: + self.errmsg = found.group(1) + self.logWarning(self.errmsg) + + if 'wait' in self.errmsg: + wait_time = sum([int(v) * {"hour": 3600, "minute": 60, "second": 1}[u] for v, u in re.findall('(\d+)\s*(hour|minute|second)?', self.errmsg)]) + self.setWait(wait_time, True) + self.wait() + elif 'captcha' in self.errmsg: + self.invalidCaptcha() + elif 'countdown' in self.errmsg: + self.retry(3) + + else: + self.errmsg = None + + return self.errmsg + + def getPostParameters(self): + for i in range(3): + if not self.errmsg: self.checkErrors() + + action, inputs = self.parseHtmlForm("action=['\"]{2}") + if not inputs: + if self.errmsg: + self.retry() + else: + self.parseError("Form not found") + + self.logDebug(inputs) + + if 'op' in inputs and inputs['op'] == 'download2': + if "password" in inputs: + if self.passwords: + inputs['password'] = self.passwords.pop(0) + else: + self.fail("No or invalid passport") + + if not self.premium: + found = re.search(self.WAIT_PATTERN, self.html) + if found: + wait_time = int(found.group(1)) + 1 + self.setWait(wait_time, False) + else: + wait_time = 0 + + self.captcha = self.handleCaptcha(inputs) + + if wait_time: self.wait() + + return inputs + else: + inputs['referer'] = self.pyfile.url + + if self.premium: + inputs['method_premium'] = "Premium Download" + if 'method_free' in inputs: del inputs['method_free'] + else: + inputs['method_free'] = "Free Download" + if 'method_premium' in inputs: del inputs['method_premium'] + + self.html = self.load(self.pyfile.url, post = inputs, ref = True) + self.errmsg = None + + else: self.parseError('FORM: %s' % (inputs['op'] if 'op' in inputs else 'UNKNOWN')) + + def handleCaptcha(self, inputs): + found = re.search(self.RECAPTCHA_URL_PATTERN, self.html) + if found: + recaptcha_key = unquote(found.group(1)) + self.logDebug("RECAPTCHA KEY: %s" % recaptcha_key) + recaptcha = ReCaptcha(self) + inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key) + return 1 + else: + found = re.search(self.CAPTCHA_URL_PATTERN, self.html) + if found: + captcha_url = found.group(1) + inputs['code'] = self.decryptCaptcha(captcha_url) + return 2 + return 0 + + def urlParseFileName(self): + return html_unescape(urlparse(self.pyfile.url).path.split("/")[-1]) + +getInfo = create_getInfo(XFileSharingPro)
\ No newline at end of file diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 555eefee3..3ae780ba2 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -42,8 +42,11 @@ def parseHtmlTagAttrValue(attr_name, tag): m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^\s\"'][^>\s]+)\1" % attr_name, tag) return m.group(2) if m else '' -def parseFileInfo(self, url = '', html = '', infomode = False): +def parseFileInfo(self, url = '', html = ''): info = {"name" : url, "size" : 0, "status" : 3} + + if hasattr(self, "pyfile"): + url = self.pyfile.url if hasattr(self, "req") and self.req.http.code == '404': info['status'] = 1 @@ -58,9 +61,14 @@ def parseFileInfo(self, url = '', html = '', infomode = False): info['status'] = 1 else: online = False + try: + info.update(re.match(self.__pattern__, url).groupdict()) + except: + pass + for pattern in ("FILE_INFO_PATTERN", "FILE_NAME_PATTERN", "FILE_SIZE_PATTERN"): try: - info = dict(info, **re.search(getattr(self, pattern), html).groupdict()) + info.update(re.search(getattr(self, pattern), html).groupdict()) online = True except AttributeError: continue @@ -77,12 +85,10 @@ def parseFileInfo(self, url = '', html = '', infomode = False): if 'units' in info: info['size'] += info['units'] info['size'] = parseFileSize(info['size']) - if infomode: - if hasattr(self, "pyfile"): - info = dict(info, **re.match(self.__pattern__, self.pyfile.url).groupdict()) - return info - else: - return info['name'], info['size'], info['status'], url + if hasattr(self, "file_info"): + self.file_info = info + + return info['name'], info['size'], info['status'], url def create_getInfo(plugin): def getInfo(urls): @@ -106,7 +112,7 @@ class PluginParseError(Exception): class SimpleHoster(Hoster): __name__ = "SimpleHoster" - __version__ = "0.20" + __version__ = "0.22" __pattern__ = None __type__ = "hoster" __description__ = """Base hoster plugin""" @@ -127,7 +133,10 @@ class SimpleHoster(Hoster): SH_BROKEN_ENCODING = False # Set to True or encoding name if encoding in http header is not correct SH_COOKIES = True # or False or list of tuples [(domain, name, value)] - SH_CHECK_TRAFFIC = False # True = force check traffic left for a premium account + SH_CHECK_TRAFFIC = False # True = force check traffic left for a premium account + + def init(self): + self.file_info = {} def setup(self): self.resumeDownload = self.multiDL = True if self.premium else False @@ -136,7 +145,7 @@ class SimpleHoster(Hoster): def process(self, pyfile): pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) self.html = self.load(pyfile.url, decode = not self.SH_BROKEN_ENCODING, cookies = self.SH_COOKIES) - self.file_info = self.getFileInfo() + self.getFileInfo() if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): self.handlePremium() else: @@ -147,25 +156,26 @@ class SimpleHoster(Hoster): if hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html): self.tempOffline() - file_info = parseFileInfo(self, infomode = True) - if file_info['status'] == 1: + name, size, status = parseFileInfo(self)[:3] + + if status == 1: self.offline() - elif file_info['status'] != 2: - self.logDebug(file_info) + elif status != 2: + self.logDebug(self.file_info) self.parseError('File info') - if file_info['name']: - self.pyfile.name = file_info['name'] + if name: + self.pyfile.name = name else: self.pyfile.name = html_unescape(urlparse(self.pyfile.url).path.split("/")[-1]) - if file_info['size']: - self.pyfile.size = file_info['size'] + if size: + self.pyfile.size = size else: self.logError("File size not parsed") self.logDebug("FILE NAME: %s FILE SIZE: %s" % (self.pyfile.name, self.pyfile.size)) - return file_info + return self.file_info def handleFree(self): self.fail("Free download not implemented") @@ -179,10 +189,10 @@ class SimpleHoster(Hoster): def parseHtmlForm(self, attr_str): inputs = {} action = None - form = re.search(r"(?P<tag><form[^>]*%s[^>]*>)(?P<content>.*?)</form[^>]*>" % attr_str, self.html, re.S) + form = re.search(r"(?P<tag><form[^>]*%s[^>]*>)(?P<content>.*?)</(form|body|html)[^>]*>" % attr_str, self.html, re.S | re.I) if form: action = parseHtmlTagAttrValue("action", form.group('tag')) - for input in re.finditer(r'(<(?:input|textarea)[^>]*>)', form.group('content')): + for input in re.finditer(r'(<(?:input|textarea)[^>]*>)', form.group('content'), re.S | re.I): name = parseHtmlTagAttrValue("name", input.group(1)) if name: inputs[name] = parseHtmlTagAttrValue("value", input.group(1)) |