summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/plugins/accounts/AlldebridCom.py26
-rw-r--r--module/plugins/accounts/CyberlockerCh.py31
-rw-r--r--module/plugins/accounts/DebridItaliaCom.py35
-rw-r--r--module/plugins/crypter/FourChanOrg.py38
-rw-r--r--module/plugins/crypter/LixIn.py19
-rw-r--r--module/plugins/crypter/TrailerzoneInfo.py4
-rwxr-xr-xmodule/plugins/hooks/Captcha9kw.py52
-rw-r--r--module/plugins/hooks/DebridItaliaCom.py25
-rw-r--r--module/plugins/hooks/ExtractArchive.py2
-rw-r--r--module/plugins/hoster/AlldebridCom.py37
-rw-r--r--module/plugins/hoster/DebridItaliaCom.py43
-rw-r--r--module/plugins/hoster/EgoFilesCom.py19
-rw-r--r--module/plugins/hoster/FilebeerInfo.py93
-rw-r--r--module/plugins/hoster/LuckyShareNet.py72
-rw-r--r--module/plugins/hoster/NetloadIn.py4
-rw-r--r--module/plugins/hoster/RapidgatorNet.py4
-rw-r--r--module/plugins/hoster/RyushareCom.py14
-rw-r--r--module/plugins/hoster/X7To.py2
-rw-r--r--module/plugins/hoster/YoutubeCom.py52
-rw-r--r--module/plugins/hoster/ZDF.py46
-rw-r--r--module/plugins/internal/CaptchaService.py8
21 files changed, 401 insertions, 225 deletions
diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py
index 7d4d245ba..beaddeac9 100644
--- a/module/plugins/accounts/AlldebridCom.py
+++ b/module/plugins/accounts/AlldebridCom.py
@@ -17,20 +17,20 @@ class AlldebridCom(Account):
data = self.getAccountData(user)
page = req.load("http://www.alldebrid.com/account/")
soup=BeautifulSoup(page)
- #Try to parse expiration date directly from the control panel page (better accuracy)
+ #Try to parse expiration date directly from the control panel page (better accuracy)
try:
- time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string
- self.log.debug("Account expires in: %s" % time_text)
- p = re.compile('\d+')
- exp_data=p.findall(time_text)
- exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60
- #Get expiration date from API
+ time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string
+ self.log.debug("Account expires in: %s" % time_text)
+ p = re.compile('\d+')
+ exp_data=p.findall(time_text)
+ exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60
+ #Get expiration date from API
except:
- 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)
- exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400
+ 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)
+ exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400
account_info = {"validuntil": exp_time, "trafficleft": -1}
return account_info
@@ -40,7 +40,7 @@ class AlldebridCom(Account):
page = req.load("http://www.alldebrid.com/register/?%s" % (urlparams))
if "This login doesn't exist" in page:
- self.wrongPassword()
+ self.wrongPassword()
if "The password is not valid" in page:
self.wrongPassword()
diff --git a/module/plugins/accounts/CyberlockerCh.py b/module/plugins/accounts/CyberlockerCh.py
new file mode 100644
index 000000000..31e0c3e24
--- /dev/null
+++ b/module/plugins/accounts/CyberlockerCh.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+from module.plugins.internal.XFSPAccount import XFSPAccount
+from module.plugins.internal.SimpleHoster import parseHtmlForm
+
+class CyberlockerCh(XFSPAccount):
+ __name__ = "CyberlockerCh"
+ __version__ = "0.01"
+ __type__ = "account"
+ __description__ = """CyberlockerCh account plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ MAIN_PAGE = "http://cyberlocker.ch/"
+
+ def login(self, user, data, req):
+ html = req.load(self.MAIN_PAGE + 'login.html', decode = True)
+
+ action, inputs = parseHtmlForm('name="FL"', html)
+ if not inputs:
+ inputs = {"op": "login",
+ "redirect": self.MAIN_PAGE}
+
+ inputs.update({"login": user,
+ "password": data['password']})
+
+ # Without this a 403 Forbidden is returned
+ req.http.lastURL = self.MAIN_PAGE + 'login.html'
+ html = req.load(self.MAIN_PAGE, post = inputs, decode = True)
+
+ if 'Incorrect Login or Password' in html or '>Error<' in html:
+ self.wrongPassword()
diff --git a/module/plugins/accounts/DebridItaliaCom.py b/module/plugins/accounts/DebridItaliaCom.py
new file mode 100644
index 000000000..d68f1c8a8
--- /dev/null
+++ b/module/plugins/accounts/DebridItaliaCom.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+import re
+import _strptime
+import time
+
+from module.plugins.Account import Account
+
+
+class DebridItaliaCom(Account):
+ __name__ = "DebridItaliaCom"
+ __version__ = "0.1"
+ __type__ = "account"
+ __description__ = """debriditalia.com account plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ WALID_UNTIL_PATTERN = r"Premium valid till: (?P<D>[^|]+) \|"
+
+ def loadAccountInfo(self, user, req):
+ if 'Account premium not activated' in self.html:
+ return {"premium": False, "validuntil": None, "trafficleft": None}
+
+ m = re.search(self.WALID_UNTIL_PATTERN, self.html)
+ if m:
+ validuntil = int(time.mktime(time.strptime(m.group('D'), "%d/%m/%Y %H:%M")))
+ return {"premium": True, "validuntil": validuntil, "trafficleft": -1}
+ else:
+ self.logError('Unable to retrieve account information - Plugin may be out of date')
+
+ def login(self, user, data, req):
+ self.html = req.load("http://debriditalia.com/login.php",
+ get={"u": user, "p": data["password"]})
+ if 'NO' in self.html:
+ self.wrongPassword()
diff --git a/module/plugins/crypter/FourChanOrg.py b/module/plugins/crypter/FourChanOrg.py
index cbcdd920c..5c96e723d 100644
--- a/module/plugins/crypter/FourChanOrg.py
+++ b/module/plugins/crypter/FourChanOrg.py
@@ -6,34 +6,20 @@ import re
from module.plugins.Crypter import Crypter
class FourChanOrg(Crypter):
+ # Based on 4chandl by Roland Beermann
+ # https://gist.github.com/enkore/3492599
__name__ = "FourChanOrg"
__type__ = "container"
- __pattern__ = r"http://(www\.)?(img\.)?(zip\.)?4chan.org/\w+/(res/|imgboard\.html)"
- __version__ = "0.1"
- __description__ = """4chan.org Thread Download Plugin"""
- __author_name__ = ("Spoob")
- __author_mail__ = ("Spoob@pyload.org")
+ __version__ = "0.3"
+ __pattern__ = r"http://boards\.4chan.org/\w+/res/(\d+)"
+ __description__ = "Downloader for entire 4chan threads"
- def __init__(self, parent):
- Crypter.__init__(self, parent)
- self.parent = parent
- self.html = None
+ def decrypt(self, pyfile):
+ pagehtml = self.load(pyfile.url)
- def file_exists(self):
- """ returns True or False
- """
- return True
+ images = set(re.findall(r'(images\.4chan\.org/[^/]*/src/[^"<]*)', pagehtml))
+ urls = []
+ for image in images:
+ urls.append("http://" + image)
- def proceed(self, url, location):
- url = self.parent.url
- html = self.req.load(url)
- link_pattern = ""
- temp_links = []
- if "imagebord.html" in url:
- link_pattern = '[<a href="(res/\d*\.html)">Reply</a>]'
- temp_links = re.findall(link_pattern, html)
- for link in re.findall(link_pattern, html):
- temp_links.append(link)
- else:
- temp_links = re.findall('File : <a href="(http://(?:img\.)?(?:zip\.)?4chan\.org/\w{,3}/src/\d*\..{3})"', html)
- self.links = temp_links
+ self.core.files.addLinks(urls, self.pyfile.package().id)
diff --git a/module/plugins/crypter/LixIn.py b/module/plugins/crypter/LixIn.py
index 1ed5510fd..e2ee30731 100644
--- a/module/plugins/crypter/LixIn.py
+++ b/module/plugins/crypter/LixIn.py
@@ -33,7 +33,7 @@ class LixIn(Crypter):
matches = re.search(self.SUBMIT_PATTERN,self.html)
if not matches:
- self.fail("link doesn't seem valid")
+ self.fail("link doesn't seem valid")
matches = re.search(self.CAPTCHA_PATTERN, self.html)
if matches:
@@ -42,20 +42,19 @@ class LixIn(Crypter):
if matches:
self.logDebug("trying captcha")
captcharesult = self.decryptCaptcha("http://lix.in/"+matches.group("image"))
- self.html = self.req.load(url, decode=True, post={"capt" : captcharesult, "submit":"submit","tiny":id})
- else:
- self.logDebug("no captcha/captcha solved")
- break
- else:
+ self.html = self.req.load(url, decode=True, post={"capt" : captcharesult, "submit":"submit","tiny":id})
+ else:
+ self.logDebug("no captcha/captcha solved")
+ break
+ else:
self.html = self.req.load(url, decode=True, post={"submit" : "submit",
- "tiny" : id})
-
+ "tiny" : id})
+
matches = re.search(self.LINK_PATTERN, self.html)
if not matches:
- self.fail("can't find destination url")
+ self.fail("can't find destination url")
new_link = matches.group("link")
self.logDebug("Found link %s, adding to package" % new_link)
self.packages.append((self.pyfile.package().name, [new_link], self.pyfile.package().name))
- \ No newline at end of file
diff --git a/module/plugins/crypter/TrailerzoneInfo.py b/module/plugins/crypter/TrailerzoneInfo.py
index 2683c2429..43a4fcce5 100644
--- a/module/plugins/crypter/TrailerzoneInfo.py
+++ b/module/plugins/crypter/TrailerzoneInfo.py
@@ -22,10 +22,10 @@ class TrailerzoneInfo(Crypter):
self.handleProtect(url)
elif goPattern.match(url):
self.handleGo(url)
-
+
def handleProtect(self, url):
self.handleGo("http://trailerzone.info/go.html#:::" + url.split("#:::",1)[1])
-
+
def handleGo(self, url):
src = self.req.load(str(url))
diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9kw.py
index b34ffeb05..a01ce9576 100755
--- a/module/plugins/hooks/Captcha9kw.py
+++ b/module/plugins/hooks/Captcha9kw.py
@@ -62,40 +62,40 @@ class Captcha9kw(Hook):
data = b64encode(data)
self.logDebug("%s : %s" % (task.captchaFile, data))
if task.isPositional():
- mouse = 1
+ mouse = 1
else:
- mouse = 0
+ mouse = 0
response = getURL(self.API_URL, post = {
- "apikey": self.getConfig("passkey"),
- "pyload": "1",
- "source": "pyload",
- "base64": "1",
- "mouse": mouse,
- "file-upload-01": data,
- "action": "usercaptchaupload" })
+ "apikey": self.getConfig("passkey"),
+ "pyload": "1",
+ "source": "pyload",
+ "base64": "1",
+ "mouse": mouse,
+ "file-upload-01": data,
+ "action": "usercaptchaupload" })
- if response.isdigit():
- self.logInfo(_("NewCaptchaID from upload: %s : %s" % (response,task.captchaFile)))
+ if response.isdigit():
+ self.logInfo(_("NewCaptchaID from upload: %s : %s" % (response,task.captchaFile)))
- for i in range(1, 200, 2):
- response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
+ for i in range(1, 200, 2):
+ response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
- if(response2 != ""):
- break;
+ if(response2 != ""):
+ break;
- time.sleep(1)
+ time.sleep(1)
- result = response2
- task.data["ticket"] = response
- self.logInfo("result %s : %s" % (response, result))
- task.setResult(result)
- else:
- self.logError("Bad upload: %s" % response)
- return False
+ result = response2
+ task.data["ticket"] = response
+ self.logInfo("result %s : %s" % (response, result))
+ task.setResult(result)
+ else:
+ self.logError("Bad upload: %s" % response)
+ return False
def newCaptchaTask(self, task):
- if not task.isTextual() and not task.isPositional():
+ if not task.isTextual() and not task.isPositional():
return False
if not self.getConfig("passkey"):
@@ -130,7 +130,7 @@ class Captcha9kw(Hook):
except BadHeader, e:
self.logError("Could not send correct request.", str(e))
else:
- self.logError("No CaptchaID for correct request (task %s) found." % task)
+ self.logError("No CaptchaID for correct request (task %s) found." % task)
def captchaInvalid(self, task):
if "ticket" in task.data:
@@ -150,4 +150,4 @@ class Captcha9kw(Hook):
except BadHeader, e:
self.logError("Could not send refund request.", str(e))
else:
- self.logError("No CaptchaID for not correct request (task %s) found." % task) \ No newline at end of file
+ self.logError("No CaptchaID for not correct request (task %s) found." % task)
diff --git a/module/plugins/hooks/DebridItaliaCom.py b/module/plugins/hooks/DebridItaliaCom.py
new file mode 100644
index 000000000..8cd997f4d
--- /dev/null
+++ b/module/plugins/hooks/DebridItaliaCom.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+from module.plugins.internal.MultiHoster import MultiHoster
+
+
+class DebridItaliaCom(MultiHoster):
+ __name__ = "DebridItaliaCom"
+ __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)", ""),
+ ("unloadFailing", "bool", "Revert to standard download if download fails", "False"),
+ ("interval", "int", "Reload interval in hours (0 to disable)", "24")]
+
+ __description__ = """Debriditalia.com hook plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ def getHoster(self):
+ return ["netload.in", "hotfile.com", "rapidshare.com", "multiupload.com",
+ "uploading.com", "megashares.com", "crocko.com", "filepost.com",
+ "bitshare.com", "share-links.biz", "putlocker.com", "uploaded.to",
+ "speedload.org", "rapidgator.net", "likeupload.net", "cyberlocker.ch",
+ "depositfiles.com", "extabit.com", "filefactory.com", "sharefiles.co"]
diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py
index c789495ca..a5a973b7f 100644
--- a/module/plugins/hooks/ExtractArchive.py
+++ b/module/plugins/hooks/ExtractArchive.py
@@ -196,8 +196,6 @@ class ExtractArchive(Hook):
files_ids = new_files_ids # also check extracted files
if not matched: self.logInfo(_("No files found to extract"))
-
-
def startExtracting(self, plugin, fid, passwords, thread):
pyfile = self.core.files.getFile(fid)
diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py
index fe58ff0a7..efc96ff28 100644
--- a/module/plugins/hoster/AlldebridCom.py
+++ b/module/plugins/hoster/AlldebridCom.py
@@ -1,19 +1,16 @@
-#!/usr/nv python
# -*- coding: utf-8 -*-
import re
-from urllib import quote, unquote
+from urllib import unquote
from random import randrange
-from os import stat
-
from module.plugins.Hoster import Hoster
from module.common.json_layer import json_loads
-from module.utils import parseFileSize, fs_encode
+from module.utils import parseFileSize
class AlldebridCom(Hoster):
__name__ = "AlldebridCom"
- __version__ = "0.3"
+ __version__ = "0.31"
__type__ = "hoster"
__pattern__ = r"https?://.*alldebrid\..*"
@@ -27,7 +24,7 @@ class AlldebridCom(Hoster):
except IndexError:
name = "Unknown_Filename..."
if name.endswith("..."): #incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100,999)
+ name += "%s.tmp" % randrange(100, 999)
return name
def init(self):
@@ -35,10 +32,9 @@ class AlldebridCom(Hoster):
self.chunkLimit = 3
self.resumeDownload = True
-
- def process(self, pyfile):
+ def process(self, pyfile):
if not self.account:
- self.logError(_("Please enter your AllDebrid account or deactivate this plugin"))
+ self.logError("Please enter your AllDebrid account or deactivate this plugin")
self.fail("No AllDebrid account provided")
self.log.debug("AllDebrid: Old URL: %s" % pyfile.url)
@@ -46,14 +42,13 @@ class AlldebridCom(Hoster):
new_url = pyfile.url
else:
password = self.getPassword().splitlines()
- if not password: password = ""
- else: password = password[0]
+ password = "" if not password else password[0]
- url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" %(pyfile.url, password)
+ url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" % (pyfile.url, password)
page = self.load(url)
data = json_loads(page)
-
- self.log.debug("Json data: %s" % str(data))
+
+ self.logDebug("Json data: %s" % str(data))
if data["error"]:
if data["error"] == "This link isn't available on the hoster website.":
@@ -72,7 +67,7 @@ class AlldebridCom(Hoster):
else:
new_url = new_url.replace("https://", "http://")
- self.log.debug("AllDebrid: New URL: %s" % new_url)
+ self.logDebug("AllDebrid: New URL: %s" % new_url)
if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
#only use when name wasnt already set
@@ -80,12 +75,10 @@ class AlldebridCom(Hoster):
self.download(new_url, disposition=True)
- check = self.checkDownload(
- {"error": "<title>An error occured while processing your request</title>","empty": re.compile(r"^$")})
+ check = self.checkDownload({"error": "<title>An error occured while processing your request</title>",
+ "empty": re.compile(r"^$")})
if check == "error":
self.retry(reason="An error occured while generating link.", wait_time=60)
- else:
- if check == "empty":
- self.retry(reason="Downloaded File was empty.", wait_time=60)
-
+ elif check == "empty":
+ self.retry(reason="Downloaded File was empty.", wait_time=60)
diff --git a/module/plugins/hoster/DebridItaliaCom.py b/module/plugins/hoster/DebridItaliaCom.py
new file mode 100644
index 000000000..a8f7dd57e
--- /dev/null
+++ b/module/plugins/hoster/DebridItaliaCom.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from module.plugins.Hoster import Hoster
+
+
+class DebridItaliaCom(Hoster):
+ __name__ = "DebridItaliaCom"
+ __version__ = "0.02"
+ __type__ = "hoster"
+ __pattern__ = r"https?://.*debriditalia\.com"
+ __description__ = """Debriditalia.com hoster plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ def init(self):
+ self.chunkLimit = -1
+ self.resumeDownload = True
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError("Please enter your DebridItalia account or deactivate this plugin")
+ self.fail("No DebridItalia account provided")
+
+ self.logDebug("Old URL: %s" % pyfile.url)
+ if re.match(self.__pattern__, pyfile.url):
+ new_url = pyfile.url
+ else:
+ url = "http://debriditalia.com/linkgen2.php?xjxfun=convertiLink&xjxargs[]=S<![CDATA[%s]]>" % pyfile.url
+ page = self.load(url)
+ self.logDebug("XML data: %s" % page)
+
+ new_url = re.search(r'<a href="(?:[^"]+)">(?P<direct>[^<]+)</a>', page).group('direct')
+
+ self.logDebug("New URL: %s" % new_url)
+
+ self.download(new_url, disposition=True)
+
+ check = self.checkDownload({"empty": re.compile(r"^$")})
+
+ if check == "empty":
+ self.retry(5, 120, 'Empty file downloaded')
diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py
index 24e26c7f5..b27abb416 100644
--- a/module/plugins/hoster/EgoFilesCom.py
+++ b/module/plugins/hoster/EgoFilesCom.py
@@ -4,22 +4,18 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
from module.plugins.ReCaptcha import ReCaptcha
import re
-def to_seconds(m):
- minutes = int(m['m']) if m['m'] else 0
- seconds = int(m['s']) if m['s'] else 0
- return minutes * 60 + seconds
class EgoFilesCom(SimpleHoster):
__name__ = "EgoFilesCom"
__type__ = "hoster"
__pattern__ = r"https?://(www\.)?egofiles.com/(\w+)"
- __version__ = "0.07"
+ __version__ = "0.10"
__description__ = """Egofiles.com Download Hoster"""
__author_name__ = ("stickell")
__author_mail__ = ("l.stickell@yahoo.it")
FILE_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>\S+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|'
- FILE_OFFLINE_PATTERN = r'File size: 0 KB'
+ FILE_OFFLINE_PATTERN = r'(File size|Rozmiar): 0 KB'
WAIT_TIME_PATTERN = r'For next free download you have to wait <strong>((?P<m>\d*)m)? ?((?P<s>\d+)s)?</strong>'
DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">Download ></a>'
RECAPTCHA_KEY = '6LeXatQSAAAAAHezcjXyWAni-4t302TeYe7_gfvX'
@@ -29,19 +25,14 @@ class EgoFilesCom(SimpleHoster):
# Set English language
self.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True)
- def process(self, pyfile):
- if self.premium:
- self.handlePremium()
- else:
- self.handleFree()
-
def handleFree(self):
self.html = self.load(self.pyfile.url, decode=True)
# Wait time between free downloads
if 'For next free download you have to wait' in self.html:
- m = re.search(self.WAIT_TIME_PATTERN, self.html)
- self.setWait(to_seconds(m.groupdict()), True)
+ m = re.search(self.WAIT_TIME_PATTERN, self.html).groupdict('0')
+ waittime = int(m['m']) * 60 + int(m['s'])
+ self.setWait(waittime, True)
self.wait()
downloadURL = ''
diff --git a/module/plugins/hoster/FilebeerInfo.py b/module/plugins/hoster/FilebeerInfo.py
index a51f70a09..216ecfbca 100644
--- a/module/plugins/hoster/FilebeerInfo.py
+++ b/module/plugins/hoster/FilebeerInfo.py
@@ -1,100 +1,15 @@
# -*- 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.
+from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo
- 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.internal.SimpleHoster import SimpleHoster, create_getInfo
-from module.plugins.ReCaptcha import ReCaptcha
-from pycurl import FOLLOWLOCATION
-
-class FilebeerInfo(SimpleHoster):
+class FilebeerInfo(DeadHoster):
__name__ = "FilebeerInfo"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+).*"
- __version__ = "0.02"
+ __version__ = "0.03"
__description__ = """Filebeer.info plugin"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
- FILE_NAME_PATTERN = r'Filename:\s*</td>\s*<td>\s*(?P<N>.+?)&nbsp;&nbsp;'
- FILE_SIZE_PATTERN = r'Filesize:\s*</td>\s*<td>\s*(?P<S>[0-9.]+) (?P<U>[kKMG])i?B'
- FILE_INFO_PATTERN = r'<strong>\s*(?P<N>.+?) \((?P<S>[0-9.]+) (?P<U>[kKMG])i?B\)(<br/>\s*)?</strong>'
- FILE_OFFLINE_PATTERN = r'<title>Upload Files - FileBeer.info</title>'
-
- FILE_URL_REPLACEMENTS = [(__pattern__, 'http://filebeer.info/\g<ID>~i')]
-
- RECAPTCHA_KEY_PATTERN = r'http://www.google.com/recaptcha/api/(?:challenge|noscript)?k=(\w+)'
- DOWNLOAD_URL_PATTERN = r"\[url\](.+?)\[/url\]"
- WAIT_TIME_PATTERN = r"\(\'\.download-timer-seconds\'\)\.html\((\d+)\)"
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = self.premium
-
- def handleFree(self):
- url = self.getDownloadUrl()
-
- for i in range(5):
- self.html = self.load(url)
- if i == 4 or 'id="form-join"' in self.html:
- break
- else:
- found = re.search(self.WAIT_TIME_PATTERN, self.html)
- self.setWait(int(found.group(1)) +1 if found else 61)
- self.wait()
-
- action, inputs = self.parseHtmlForm('form-join')
- if not action:
- self.fail('Form not found')
-
- found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html)
- recaptcha_key = found.group(1) if found else '6LeuAc4SAAAAAOSry8eo2xW64K1sjHEKsQ5CaS10'
-
- recaptcha = ReCaptcha(self)
- for i in range(5):
- inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key)
-
- self.req.http.c.setopt(FOLLOWLOCATION, 0)
- self.html = self.load(action, post = inputs)
- 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:
- download_url = found.group(1).strip()
- self.correctCaptcha()
- break
- elif 'Captcha confirmation text is invalid' in self.html:
- self.invalidCaptcha()
- else:
- self.parseError('download url')
-
- else: self.fail("No valid captcha solution received")
-
- self.multiDL = True
-
- self.req.http.lastURL = action
- self.download(download_url)
-
- def handlePremium(self):
- self.download(self.getDownloadUrl())
-
- def getDownloadUrl(self):
- found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
- return ("%s?d=1" % found.group(1)) if found else ("http://filebeer.info/%s?d=1" % self.file_info['ID'])
-
+
getInfo = create_getInfo(FilebeerInfo) \ No newline at end of file
diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py
new file mode 100644
index 000000000..a1e866089
--- /dev/null
+++ b/module/plugins/hoster/LuckyShareNet.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+
+import re
+from module.lib.bottle import json_loads
+
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.ReCaptcha import ReCaptcha
+
+
+class LuckyShareNet(SimpleHoster):
+ __name__ = "LuckyShareNet"
+ __type__ = "hoster"
+ __pattern__ = r"https?://(www\.)?luckyshare.net/(?P<ID>\d{10,})"
+ __version__ = "0.02"
+ __description__ = """LuckyShare.net Download Hoster"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ FILE_INFO_PATTERN = r"<h1 class='file_name'>(?P<N>\S+)</h1>\s*<span class='file_size'>Filesize: (?P<S>[\d.]+)(?P<U>\w+)</span>"
+ FILE_OFFLINE_PATTERN = 'There is no such file available'
+ RECAPTCHA_KEY = '6LdivsgSAAAAANWh-d7rPE1mus4yVWuSQIJKIYNw'
+
+ def parseJson(self, rep):
+ if 'AJAX Error' in rep:
+ html = self.load(self.pyfile.url, decode=True)
+ m = re.search(r"waitingtime = (\d+);", html)
+ if m:
+ waittime = int(m.group(1))
+ self.logDebug('You have to wait %d seconds between free downloads' % waittime)
+ self.retry(wait_time=waittime)
+ else:
+ self.parseError('Unable to detect wait time between free downloads')
+ elif 'Hash expired' in rep:
+ self.retry(reason='Hash expired')
+ return json_loads(rep)
+
+ # TODO: There should be a filesize limit for free downloads
+ # TODO: Some files could not be downloaded in free mode
+ def handleFree(self):
+ file_id = re.search(self.__pattern__, self.pyfile.url).group('ID')
+ self.logDebug('File ID: ' + file_id)
+ rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True)
+ self.logDebug('JSON: ' + rep)
+ json = self.parseJson(rep)
+
+ self.setWait(int(json['time']))
+ self.wait()
+
+ recaptcha = ReCaptcha(self)
+ for i in xrange(5):
+ challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY)
+ rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" %
+ (challenge, response, json['hash']), decode=True)
+ self.logDebug('JSON: ' + rep)
+ if 'link' in rep:
+ json.update(self.parseJson(rep))
+ self.correctCaptcha()
+ break
+ elif 'Verification failed' in rep:
+ self.logInfo('Wrong captcha')
+ self.invalidCaptcha()
+ else:
+ self.parseError('Unable to get downlaod link')
+
+ if not json['link']:
+ self.fail("No Download url retrieved/all captcha attempts failed")
+
+ self.logDebug('Direct URL: ' + json['link'])
+ self.download(json['link'])
+
+
+getInfo = create_getInfo(LuckyShareNet)
diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py
index d2bf37d70..e616badc2 100644
--- a/module/plugins/hoster/NetloadIn.py
+++ b/module/plugins/hoster/NetloadIn.py
@@ -54,8 +54,8 @@ def getInfo(urls):
class NetloadIn(Hoster):
__name__ = "NetloadIn"
__type__ = "hoster"
- __pattern__ = r"http://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)"
- __version__ = "0.41"
+ __pattern__ = r"https?://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)"
+ __version__ = "0.42"
__description__ = """Netload.in Download Hoster"""
__author_name__ = ("spoob", "RaNaN", "Gregy")
__author_mail__ = ("spoob@pyload.org", "ranan@pyload.org", "gregy@gregy.cz")
diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py
index 6c1c231fe..1cc3ff8ae 100644
--- a/module/plugins/hoster/RapidgatorNet.py
+++ b/module/plugins/hoster/RapidgatorNet.py
@@ -28,8 +28,8 @@ from module.network.HTTPRequest import BadHeader
class RapidgatorNet(SimpleHoster):
__name__ = "RapidgatorNet"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\d+)"
- __version__ = "0.15"
+ __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\w+)"
+ __version__ = "0.16"
__description__ = """rapidgator.net"""
__author_name__ = ("zoidberg","chrox")
diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py
index 19f17b531..c2ff54e0c 100644
--- a/module/plugins/hoster/RyushareCom.py
+++ b/module/plugins/hoster/RyushareCom.py
@@ -2,16 +2,12 @@
from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
import re
-def to_seconds(m):
- minutes = int(m['min']) if m['min'] else 0
- seconds = int(m['sec']) if m['sec'] else 0
- return minutes * 60 + seconds
class RyushareCom(XFileSharingPro):
__name__ = "RyushareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{11,}"
- __version__ = "0.07"
+ __version__ = "0.10"
__description__ = """ryushare.com hoster plugin"""
__author_name__ = ("zoidberg", "stickell")
__author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
@@ -19,6 +15,7 @@ class RyushareCom(XFileSharingPro):
HOSTER_NAME = "ryushare.com"
WAIT_PATTERN = r'(?:You have to|Please) wait (?:(?P<min>\d+) minutes, )?(?:<span id="[^"]+">)?(?P<sec>\d+)(?:</span>)? seconds'
+ DIRECT_LINK_PATTERN = r'<a href="([^"]+)">Click here to download</a>'
def setup(self):
self.resumeDownload = self.multiDL = self.premium
@@ -41,13 +38,14 @@ class RyushareCom(XFileSharingPro):
if 'You have reached the download-limit!!!' in self.html:
self.setWait(3600, True)
else:
- m = re.search(self.WAIT_PATTERN, self.html)
- self.setWait(to_seconds(m.groupdict()))
+ m = re.search(self.WAIT_PATTERN, self.html).groupdict('0')
+ waittime = int(m['min']) * 60 + int(m['sec'])
+ self.setWait(waittime)
self.wait()
self.html = self.load(self.pyfile.url, post = inputs)
if 'Click here to download' in self.html:
- m = re.search(r'<a href="([^"]+)">Click here to download</a>', self.html)
+ m = re.search(self.DIRECT_LINK_PATTERN, self.html)
return m.group(1)
self.parseError('No direct link within 10 retries')
diff --git a/module/plugins/hoster/X7To.py b/module/plugins/hoster/X7To.py
index 51f8e6cd4..79adf2a3f 100644
--- a/module/plugins/hoster/X7To.py
+++ b/module/plugins/hoster/X7To.py
@@ -55,7 +55,7 @@ class X7To(Hoster):
file_id = re.search(r"var dlID = '(.*?)'", self.html)
if not file_id:
self.fail("Free download id not found")
-
+
file_url = "http://x7.to/james/ticket/dl/" + file_id.group(1)
self.logDebug("download id %s" % file_id.group(1))
diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py
index a9fed5638..8b8764367 100644
--- a/module/plugins/hoster/YoutubeCom.py
+++ b/module/plugins/hoster/YoutubeCom.py
@@ -2,11 +2,34 @@
# -*- coding: utf-8 -*-
import re
+import subprocess
+import os
+import os.path
from urllib import unquote
from module.utils import html_unescape
from module.plugins.Hoster import Hoster
+def which(program):
+ """Works exactly like the unix command which
+
+ Courtesy of http://stackoverflow.com/a/377028/675646"""
+ def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+ fpath, fname = os.path.split(program)
+ if fpath:
+ if is_exe(program):
+ return program
+ else:
+ for path in os.environ["PATH"].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if is_exe(exe_file):
+ return exe_file
+
+ return None
+
class YoutubeCom(Hoster):
__name__ = "YoutubeCom"
__type__ = "hoster"
@@ -112,7 +135,30 @@ class YoutubeCom(Hoster):
#set file name
file_suffix = self.formats[fmt][0] if fmt in self.formats else ".flv"
file_name_pattern = '<meta name="title" content="(.+?)">'
- name = re.search(file_name_pattern, html).group(1).replace("/", "") + file_suffix
+ name = re.search(file_name_pattern, html).group(1).replace("/", "")
pyfile.name = html_unescape(name)
-
- self.download(url) \ No newline at end of file
+
+ time = re.search(r"t=((\d+)m)?(\d+)s", pyfile.url)
+ ffmpeg = which("ffmpeg")
+ if ffmpeg and time:
+ m, s = time.groups()[1:]
+ if not m:
+ m = "0"
+
+ pyfile.name += " (starting at %s:%s)" % (m, s)
+ pyfile.name += file_suffix
+
+ filename = self.download(url)
+
+ if ffmpeg and time:
+ inputfile = filename + "_"
+ os.rename(filename, inputfile)
+
+ subprocess.call([
+ ffmpeg,
+ "-ss", "00:%s:%s" % (m, s),
+ "-i", inputfile,
+ "-vcodec", "copy",
+ "-acodec", "copy",
+ filename])
+ os.remove(inputfile)
diff --git a/module/plugins/hoster/ZDF.py b/module/plugins/hoster/ZDF.py
new file mode 100644
index 000000000..ea45f4fd8
--- /dev/null
+++ b/module/plugins/hoster/ZDF.py
@@ -0,0 +1,46 @@
+
+import re
+from xml.etree.ElementTree import fromstring
+
+from module.plugins.Hoster import Hoster
+
+XML_API = "http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?id=%i"
+
+class ZDF(Hoster):
+ # Based on zdfm by Roland Beermann
+ # http://github.com/enkore/zdfm/
+ __name__ = "ZDF Mediathek"
+ __version__ = "0.7"
+ __pattern__ = r"http://www\.zdf\.de/ZDFmediathek/[^0-9]*([0-9]+)[^0-9]*"
+ __config__ = []
+
+ @staticmethod
+ def video_key(video):
+ return (
+ int(video.findtext("videoBitrate", "0")),
+ any(f.text == "progressive" for f in video.iter("facet")),
+ )
+
+ @staticmethod
+ def video_valid(video):
+ return (video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4"))
+
+ @staticmethod
+ def get_id(url):
+ return int(re.search(r"[^0-9]*([0-9]+)[^0-9]*", url).group(1))
+
+ def process(self, pyfile):
+ xml = fromstring(self.load(XML_API % self.get_id(pyfile.url)))
+
+ status = xml.findtext("./status/statuscode")
+ if status != "ok":
+ self.fail("Error retrieving manifest.")
+
+ video = xml.find("video")
+ title = video.findtext("information/title")
+
+ pyfile.name = title
+
+ target_url = sorted((v for v in video.iter("formitaet") if self.video_valid(v)), key=self.video_key)[-1].findtext("url")
+
+ self.download(target_url)
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py
index f2de00732..b912436a7 100644
--- a/module/plugins/internal/CaptchaService.py
+++ b/module/plugins/internal/CaptchaService.py
@@ -19,7 +19,7 @@
import re
class CaptchaService():
- __version__ = "0.01"
+ __version__ = "0.02"
def __init__(self, plugin):
self.plugin = plugin
@@ -64,11 +64,9 @@ class SolveMedia(CaptchaService):
self.plugin = plugin
def challenge(self, src):
- html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.script?k=%s" % src, cookies=True)
+ html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript?k=%s" % src, cookies=True)
try:
- ckey = re.search("ckey:.*?'(.*?)',",html).group(1)
- html = self.plugin.req.load("http://api.solvemedia.com/papi/_challenge.js?k=%s" % ckey, cookies=True)
- challenge = re.search('"chid".*?: "(.*?)"',html).group(1)
+ challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">', html).group(1)
except:
self.plugin.fail("solvmedia error")
result = self.result(challenge)