summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Stefano <l.stickell@yahoo.it> 2013-05-20 20:19:00 +0200
committerGravatar Stefano <l.stickell@yahoo.it> 2013-05-20 20:19:00 +0200
commitd4451312d80b0443cf7a48142c00dcc7bf3be65a (patch)
treeb152f6dc0e5a98b4e944648590e34f2f12282a45
parentsmaller footer (diff)
parentCloudzerNet: reconnect support (diff)
downloadpyload-d4451312d80b0443cf7a48142c00dcc7bf3be65a.tar.xz
Merge branch 'stable'
-rw-r--r--module/plugins/accounts/CzshareCom.py41
-rw-r--r--module/plugins/accounts/FastshareCz.py28
-rw-r--r--module/plugins/accounts/FilefactoryCom.py10
-rw-r--r--module/plugins/accounts/MultiDebridCom.py47
-rw-r--r--module/plugins/accounts/RapidgatorNet.py6
-rw-r--r--module/plugins/addons/DebridItaliaCom.py4
-rw-r--r--module/plugins/addons/DeleteFinished.py86
-rw-r--r--module/plugins/addons/DownloadScheduler.py72
-rw-r--r--module/plugins/addons/MultiDebridCom.py42
-rw-r--r--module/plugins/addons/RestartFailed.py124
-rw-r--r--module/plugins/crypter/DownloadVimeoCom.py30
-rw-r--r--module/plugins/crypter/EasybytezComFolder.py60
-rw-r--r--module/plugins/crypter/GooGl.py15
-rw-r--r--module/plugins/crypter/MBLinkInfo.py27
-rw-r--r--module/plugins/crypter/Movie2kTo.py54
-rw-r--r--module/plugins/crypter/NCryptIn.py33
-rw-r--r--module/plugins/crypter/NetfolderIn.py48
-rw-r--r--module/plugins/crypter/SerienjunkiesOrg.py6
-rw-r--r--module/plugins/crypter/SpeedLoadOrgFolder.py15
-rw-r--r--module/plugins/crypter/UploadedToFolder.py37
-rw-r--r--module/plugins/crypter/YoutubeBatch.py37
-rwxr-xr-xmodule/plugins/hooks/Captcha9kw.py15
-rw-r--r--module/plugins/hoster/ARD.py80
-rw-r--r--module/plugins/hoster/CloudzerNet.py4
-rw-r--r--module/plugins/hoster/CzshareCom.py7
-rw-r--r--module/plugins/hoster/DebridItaliaCom.py2
-rw-r--r--module/plugins/hoster/EasybytezCom.py53
-rw-r--r--module/plugins/hoster/EgoFilesCom.py4
-rw-r--r--module/plugins/hoster/ExtabitCom.py33
-rw-r--r--module/plugins/hoster/FastshareCz.py43
-rw-r--r--module/plugins/hoster/FilefactoryCom.py226
-rw-r--r--module/plugins/hoster/MediafireCom.py96
-rw-r--r--module/plugins/hoster/MegaNz.py6
-rw-r--r--module/plugins/hoster/MovReelCom.py106
-rw-r--r--module/plugins/hoster/MultiDebridCom.py57
-rw-r--r--module/plugins/hoster/OneFichierCom.py4
-rw-r--r--module/plugins/hoster/Premium4Me.py45
-rw-r--r--module/plugins/hoster/PutlockerCom.py4
-rw-r--r--module/plugins/hoster/RapidgatorNet.py6
-rw-r--r--module/plugins/hoster/RyushareCom.py6
-rw-r--r--module/plugins/hoster/UploadedTo.py24
-rw-r--r--module/plugins/hoster/UploadheroCom.py6
-rw-r--r--module/plugins/hoster/XVideosCom.py19
-rw-r--r--module/plugins/hoster/XvidstageCom.py187
-rw-r--r--module/plugins/hoster/YoutubeCom.py52
-rw-r--r--module/plugins/internal/SimpleCrypter.py3
46 files changed, 1329 insertions, 581 deletions
diff --git a/module/plugins/accounts/CzshareCom.py b/module/plugins/accounts/CzshareCom.py
index e68248aa8..7b1a8edc5 100644
--- a/module/plugins/accounts/CzshareCom.py
+++ b/module/plugins/accounts/CzshareCom.py
@@ -17,42 +17,41 @@
@author: zoidberg
"""
-from module.plugins.Account import Account
from time import mktime, strptime
-from string import replace
import re
+from module.plugins.Account import Account
+
+
class CzshareCom(Account):
__name__ = "CzshareCom"
- __version__ = "0.11"
+ __version__ = "0.13"
__type__ = "account"
__description__ = """czshare.com account plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
-
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
+
CREDIT_LEFT_PATTERN = r'<tr class="active">\s*<td>([0-9 ,]+) (KiB|MiB|GiB)</td>\s*<td>([^<]*)</td>\s*</tr>'
def loadAccountInfo(self, user, req):
- self.relogin(user)
html = req.load("http://czshare.com/prehled_kreditu/")
-
+
found = re.search(self.CREDIT_LEFT_PATTERN, html)
- if found is None:
- credits, validuntil = 0, 0
+ if not found:
+ return {"validuntil": 0, "trafficleft": 0}
else:
- credits = float(found.group(1).replace(' ', '').replace(',','.'))
- credits = credits * 1024**{'KiB' : 0, 'MiB' : 1, 'GiB' : 2}[found.group(2)]
+ credits = float(found.group(1).replace(' ', '').replace(',', '.'))
+ credits = credits * 1024 ** {'KiB': 0, 'MiB': 1, 'GiB': 2}[found.group(2)]
validuntil = mktime(strptime(found.group(3), '%d.%m.%y %H:%M'))
-
- return {"validuntil": validuntil, "trafficleft": credits}
-
+ return {"validuntil": validuntil, "trafficleft": credits}
+
def login(self, user, data, req):
-
+
html = req.load('https://czshare.com/index.php', post={
- "Prihlasit": "Prihlasit",
- "login-password": data["password"],
- "login-name": user
- })
-
+ "Prihlasit": "Prihlasit",
+ "login-password": data["password"],
+ "login-name": user
+ })
+
if '<div class="login' in html:
self.wrongPassword()
diff --git a/module/plugins/accounts/FastshareCz.py b/module/plugins/accounts/FastshareCz.py
index 333ee3761..69bbb0827 100644
--- a/module/plugins/accounts/FastshareCz.py
+++ b/module/plugins/accounts/FastshareCz.py
@@ -21,32 +21,34 @@ import re
from module.plugins.Account import Account
from module.utils import parseFileSize
+
class FastshareCz(Account):
__name__ = "FastshareCz"
- __version__ = "0.01"
+ __version__ = "0.02"
__type__ = "account"
__description__ = """fastshare.cz account plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
-
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
+
def loadAccountInfo(self, user, req):
- html = req.load("http://www.fastshare.cz/user", decode = True)
-
- found = re.search(r'Kredit: </td><td>(.+?)&nbsp;', html)
+ html = req.load("http://www.fastshare.cz/user", decode=True)
+
+ found = re.search(r'(?:Kredit|Credit)\s*: </td><td>(.+?)&nbsp;', html)
if found:
- trafficleft = parseFileSize(found.group(1)) / 1024
+ trafficleft = parseFileSize(found.group(1)) / 1024
premium = True if trafficleft else False
else:
trafficleft = None
- premium = False
+ premium = False
return {"validuntil": -1, "trafficleft": trafficleft, "premium": premium}
-
+
def login(self, user, data, req):
- html = req.load('http://www.fastshare.cz/sql.php', post = {
+ req.load('http://www.fastshare.cz/login') # Do not remove or it will not login
+ html = req.load('http://www.fastshare.cz/sql.php', post={
"heslo": data['password'],
"login": user
- }, decode = True)
-
+ }, decode=True)
+
if u'>Špatné uživatelské jméno nebo heslo.<' in html:
self.wrongPassword() \ No newline at end of file
diff --git a/module/plugins/accounts/FilefactoryCom.py b/module/plugins/accounts/FilefactoryCom.py
index 356c5d22a..8e163e2f6 100644
--- a/module/plugins/accounts/FilefactoryCom.py
+++ b/module/plugins/accounts/FilefactoryCom.py
@@ -23,13 +23,13 @@ from time import mktime, strptime
class FilefactoryCom(Account):
__name__ = "FilefactoryCom"
- __version__ = "0.12"
+ __version__ = "0.13"
__type__ = "account"
__description__ = """filefactory.com account plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
- ACCOUNT_INFO_PATTERN = r'<a href="/premium/">.*?datetime="(.*?)"'
+ ACCOUNT_INFO_PATTERN = r'<time datetime="([\d-]+)">'
def loadAccountInfo(self, user, req):
html = req.load("http://www.filefactory.com/member/")
@@ -37,7 +37,7 @@ class FilefactoryCom(Account):
found = re.search(self.ACCOUNT_INFO_PATTERN, html)
if found:
premium = True
- validuntil = mktime(strptime(re.sub(r"(\d)[a-z]{2} ", r"\1 ", found.group(1)),"%d %B, %Y"))
+ validuntil = mktime(strptime(found.group(1),"%Y-%m-%d"))
else:
premium = False
validuntil = -1
diff --git a/module/plugins/accounts/MultiDebridCom.py b/module/plugins/accounts/MultiDebridCom.py
new file mode 100644
index 000000000..904be5ee7
--- /dev/null
+++ b/module/plugins/accounts/MultiDebridCom.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
+from time import time
+
+from module.plugins.Account import Account
+from module.common.json_layer import json_loads
+
+
+class MultiDebridCom(Account):
+ __name__ = "MultiDebridCom"
+ __version__ = "0.01"
+ __type__ = "account"
+ __description__ = """Multi-debrid.com account plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ def loadAccountInfo(self, user, req):
+ if 'days_left' in self.json_data:
+ validuntil = int(time() + self.json_data['days_left'] * 86400)
+ return {"premium": True, "validuntil": validuntil, "trafficleft": -1}
+ else:
+ self.logError('Unable to get account information')
+
+ def login(self, user, data, req):
+ # Password to use is the API-Password written in http://multi-debrid.com/myaccount
+ self.html = req.load("http://multi-debrid.com/api.php",
+ get={"user": user, "pass": data["password"]})
+ self.logDebug('JSON data: ' + self.html)
+ self.json_data = json_loads(self.html)
+ if self.json_data['status'] != 'ok':
+ self.logError('Invalid login. The password to use is the API-Password you find in your "My Account" page')
+ self.wrongPassword()
diff --git a/module/plugins/accounts/RapidgatorNet.py b/module/plugins/accounts/RapidgatorNet.py
index 74825a0f9..85adc71a3 100644
--- a/module/plugins/accounts/RapidgatorNet.py
+++ b/module/plugins/accounts/RapidgatorNet.py
@@ -24,7 +24,7 @@ from module.common.json_layer import json_loads
class RapidgatorNet(Account):
__name__ = "RapidgatorNet"
- __version__ = "0.03"
+ __version__ = "0.04"
__type__ = "account"
__description__ = """rapidgator.net account plugin"""
__author_name__ = ("zoidberg")
@@ -46,7 +46,7 @@ class RapidgatorNet(Account):
self.scheduleRefresh(user, json['response']['reset_in'])
return {"validuntil": json['response']['expire_date'],
- "trafficleft": json['response']['traffic_left'] / 1024,
+ "trafficleft": int(json['response']['traffic_left']) / 1024,
"premium": True}
else:
self.logError(json['response_details'])
@@ -71,4 +71,4 @@ class RapidgatorNet(Account):
except Exception, e:
self.logError(e)
- self.wrongPassword() \ No newline at end of file
+ self.wrongPassword()
diff --git a/module/plugins/addons/DebridItaliaCom.py b/module/plugins/addons/DebridItaliaCom.py
index d570eebe3..80cdc45f6 100644
--- a/module/plugins/addons/DebridItaliaCom.py
+++ b/module/plugins/addons/DebridItaliaCom.py
@@ -20,7 +20,7 @@ from module.plugins.internal.MultiHoster import MultiHoster
class DebridItaliaCom(MultiHoster):
__name__ = "DebridItaliaCom"
- __version__ = "0.03"
+ __version__ = "0.05"
__type__ = "hook"
__config__ = [("activated", "bool", "Activated", "False"),
("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"),
@@ -38,4 +38,4 @@ class DebridItaliaCom(MultiHoster):
"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",
- "ryushare.com", "tusfiles.net", "nowvideo.co"]
+ "ryushare.com", "tusfiles.net", "nowvideo.co", "cloudzer.net", "letitbit.net"]
diff --git a/module/plugins/addons/DeleteFinished.py b/module/plugins/addons/DeleteFinished.py
new file mode 100644
index 000000000..e0df69eef
--- /dev/null
+++ b/module/plugins/addons/DeleteFinished.py
@@ -0,0 +1,86 @@
+ # -*- 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: Walter Purcaro
+"""
+
+from module.plugins.Hook import Hook
+from time import time
+
+
+class DeleteFinished(Hook):
+ __name__ = "DeleteFinished"
+ __version__ = "0.5"
+ __description__ = "Automatically delete finished packages from queue"
+ __config__ = [
+ ("activated", "bool", "Activated", "False"),
+ ("interval", "int", "Delete every (hours)", "72")
+ ]
+ __author_name__ = ("Walter Purcaro")
+ __author_mail__ = ("vuolter@gmail.com")
+
+ def wakeup(self, pypack):
+ # self.logDebug("self.wakeup")
+ self.removeEvent("packageFinished", self.wakeup)
+ self.info["sleep"] = False
+
+ def periodical(self):
+ # self.logDebug("self.periodical")
+ if not self.info["sleep"]:
+ self.core.api.deleteFinished()
+ self.logDebug("called self.core.api.deleteFinished")
+ self.info["sleep"] = True
+ self.addEvent("packageFinished", self.wakeup)
+
+ def addEvent(self, event, handler):
+ if event in self.manager.events:
+ if handler not in self.manager.events[event]:
+ self.manager.events[event].append(handler)
+ # self.logDebug("self.addEvent: " + event + ": added handler")
+ else:
+ # self.logDebug("self.addEvent: " + event + ": NOT added handler")
+ return False
+ else:
+ self.manager.events[event] = [handler]
+ # self.logDebug("self.addEvent: " + event + ": added event and handler")
+ return True
+
+ def removeEvent(self, event, handler):
+ if event in self.manager.events and handler in self.manager.events[event]:
+ self.manager.events[event].remove(handler)
+ # self.logDebug("self.removeEvent: " + event + ": removed handler")
+ return True
+ else:
+ # self.logDebug("self.removeEvent: " + event + ": NOT removed handler")
+ return False
+
+ def configEvents(self, plugin=None, name=None, value=None):
+ # self.logDebug("self.configEvents")
+ interval = self.getConfig("interval") * 3600
+ if interval != self.interval:
+ self.interval = interval
+
+ def unload(self):
+ # self.logDebug("self.unload")
+ self.removeEvent("pluginConfigChanged", self.configEvents)
+ self.removeEvent("packageFinished", self.wakeup)
+
+ def coreReady(self):
+ # self.logDebug("self.coreReady")
+ self.info = {"sleep": True}
+ self.addEvent("pluginConfigChanged", self.configEvents)
+ self.configEvents()
+ self.addEvent("packageFinished", self.wakeup)
diff --git a/module/plugins/addons/DownloadScheduler.py b/module/plugins/addons/DownloadScheduler.py
index 7cadede38..4049d71c5 100644
--- a/module/plugins/addons/DownloadScheduler.py
+++ b/module/plugins/addons/DownloadScheduler.py
@@ -18,61 +18,69 @@
import re
from time import localtime
+
from module.plugins.Hook import Hook
+
class DownloadScheduler(Hook):
__name__ = "DownloadScheduler"
- __version__ = "0.20"
+ __version__ = "0.21"
__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")
-
+ __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"),
+ ("abort", "bool", "Abort active downloads when start period with speed 0", "False")]
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
+
def setup(self):
- self.cb = None # callback to scheduler job; will be by removed hookmanager when hook unloaded
-
+ 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"))
+
+ 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)
-
+
+ self.logDebug("Schedule", schedule)
+
for i, v in enumerate(schedule):
if v[3] == "X":
- last, next = schedule[i-1], schedule[(i+1) % len(schedule)]
+ 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.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):
+ 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.)")
+ abort = self.getConfig("abort")
+ self.logInfo("Stopping download server. (Running downloads will %sbe aborted.)" % ('' if abort else 'not '))
self.core.api.pauseServer()
+ if abort:
+ self.core.api.stopAllDownloads()
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)
+ 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
+ self.core.api.setConfigValue("download", "limit_speed", 0)
+ self.core.api.setConfigValue("download", "max_speed", -1)
diff --git a/module/plugins/addons/MultiDebridCom.py b/module/plugins/addons/MultiDebridCom.py
new file mode 100644
index 000000000..c95138648
--- /dev/null
+++ b/module/plugins/addons/MultiDebridCom.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
+from module.plugins.internal.MultiHoster import MultiHoster
+from module.network.RequestFactory import getURL
+from module.common.json_layer import json_loads
+
+
+class MultiDebridCom(MultiHoster):
+ __name__ = "MultiDebridCom"
+ __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__ = """Multi-debrid.com hook plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ def getHoster(self):
+ json_data = getURL('http://multi-debrid.com/api.php?hosts', decode=True)
+ self.logDebug('JSON data: ' + json_data)
+ json_data = json_loads(json_data)
+
+ return json_data['hosts']
diff --git a/module/plugins/addons/RestartFailed.py b/module/plugins/addons/RestartFailed.py
new file mode 100644
index 000000000..7ee53deb9
--- /dev/null
+++ b/module/plugins/addons/RestartFailed.py
@@ -0,0 +1,124 @@
+ # -*- 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: Walter Purcaro
+"""
+
+from module.plugins.Hook import Hook
+from time import time
+
+
+class RestartFailed(Hook):
+ __name__ = "RestartFailed"
+ __version__ = "1.5"
+ __description__ = "Automatically restart failed/aborted downloads"
+ __config__ = [
+ ("activated", "bool", "Activated", "True"),
+ ("dlFail", "bool", "Restart when download fail", "True"),
+ ("dlFail_n", "int", "Only when failed downloads are at least", "5"),
+ ("dlFail_i", "int", "Only when elapsed time since last restart is (min)", "10"),
+ ("dlPrcs", "bool", "Restart after all downloads are processed", "True"),
+ ("recnt", "bool", "Restart after reconnecting", "True"),
+ ("rsLoad", "bool", "Restart on plugin activation", "False")
+ ]
+ __author_name__ = ("Walter Purcaro")
+ __author_mail__ = ("vuolter@gmail.com")
+
+ def restart(self, arg=None):
+ # self.logDebug("self.restart")
+ self.info["timerflag"] = False
+ self.info["dlfailed"] = 0
+ self.core.api.restartFailed()
+ self.logDebug("self.restart: self.core.api.restartFailed")
+ self.info["lastrstime"] = time()
+
+ def periodical(self):
+ # self.logDebug("self.periodical")
+ if self.info["timerflag"]:
+ self.restart()
+
+ def checkInterval(self, arg=None):
+ # self.logDebug("self.checkInterval")
+ now = time()
+ lastrstime = self.info["lastrstime"]
+ interval = self.getConfig("dlFail_i") * 60
+ if now < lastrstime + interval:
+ self.info["timerflag"] = True
+ else:
+ self.restart()
+
+ def checkFailed(self, pyfile):
+ # self.logDebug("self.checkFailed")
+ self.info["dlfailed"] += 1
+ curr = self.info["dlfailed"]
+ max = self.getConfig("dlFail_n")
+ if curr >= max:
+ self.checkInterval()
+
+ def addEvent(self, event, handler):
+ if event in self.manager.events:
+ if handler not in self.manager.events[event]:
+ self.manager.events[event].append(handler)
+ # self.logDebug("self.addEvent: " + event + ": added handler")
+ else:
+ # self.logDebug("self.addEvent: " + event + ": NOT added handler")
+ return False
+ else:
+ self.manager.events[event] = [handler]
+ # self.logDebug("self.addEvent: " + event + ": added event and handler")
+ return True
+
+ def removeEvent(self, event, handler):
+ if event in self.manager.events and handler in self.manager.events[event]:
+ self.manager.events[event].remove(handler)
+ # self.logDebug("self.removeEvent: " + event + ": removed handler")
+ return True
+ else:
+ # self.logDebug("self.removeEvent: " + event + ": NOT removed handler")
+ return False
+
+ def configEvents(self, plugin=None, name=None, value=None):
+ # self.logDebug("self.configEvents")
+ self.interval = self.getConfig("dlFail_i") * 60
+ dlFail = self.getConfig("dlFail")
+ dlPrcs = self.getConfig("dlPrcs")
+ recnt = self.getConfig("recnt")
+ if dlPrcs:
+ self.addEvent("allDownloadsProcessed", self.checkInterval)
+ else:
+ self.removeEvent("allDownloadsProcessed", self.checkInterval)
+ if not dlFail:
+ self.info["timerflag"] = False
+ if recnt:
+ self.addEvent("afterReconnecting", self.restart)
+ else:
+ self.removeEvent("afterReconnecting", self.restart)
+
+ def unload(self):
+ # self.logDebug("self.unload")
+ self.removeEvent("pluginConfigChanged", self.configEvents)
+ self.removeEvent("downloadFailed", self.checkFailed)
+ self.removeEvent("allDownloadsProcessed", self.checkInterval)
+ self.removeEvent("afterReconnecting", self.restart)
+
+ def coreReady(self):
+ # self.logDebug("self.coreReady")
+ self.info = {"dlfailed": 0, "lastrstime": 0, "timerflag": False}
+ if self.getConfig("rsLoad"):
+ self.restart()
+ self.addEvent("downloadFailed", self.checkFailed)
+ self.addEvent("pluginConfigChanged", self.configEvents)
+ self.configEvents()
diff --git a/module/plugins/crypter/DownloadVimeoCom.py b/module/plugins/crypter/DownloadVimeoCom.py
new file mode 100644
index 000000000..88310915b
--- /dev/null
+++ b/module/plugins/crypter/DownloadVimeoCom.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import re
+import HTMLParser
+from module.plugins.Crypter import Crypter
+
+class DownloadVimeoCom(Crypter):
+ __name__ = 'DownloadVimeoCom'
+ __type__ = 'crypter'
+ __pattern__ = r'(?:http://vimeo\.com/\d*|http://smotri\.com/video/view/\?id=.*)'
+ ## The download from dailymotion failed with a 403
+ __version__ = '0.1'
+ __description__ = """Video Download Plugin based on downloadvimeo.com"""
+ __author_name__ = ('4Christopher')
+ __author_mail__ = ('4Christopher@gmx.de')
+ BASE_URL = 'http://downloadvimeo.com'
+
+ def decrypt(self, pyfile):
+ self.package = pyfile.package()
+ html = self.load('%s/generate?url=%s' % (self.BASE_URL, pyfile.url))
+ h = HTMLParser.HTMLParser()
+ try:
+ f = re.search(r'cmd quality="(?P<quality>[^"]+?)">\s*?(?P<URL>[^<]*?)</cmd>', html)
+ except:
+ self.logDebug('Failed to find the URL')
+ else:
+ url = h.unescape(f.group('URL'))
+ self.logDebug('Quality: %s, URL: %s' % (f.group('quality'), url))
+ self.packages.append((self.package.name, [url], self.package.folder))
diff --git a/module/plugins/crypter/EasybytezComFolder.py b/module/plugins/crypter/EasybytezComFolder.py
new file mode 100644
index 000000000..1b887e421
--- /dev/null
+++ b/module/plugins/crypter/EasybytezComFolder.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
+import re
+
+from module.plugins.internal.SimpleCrypter import SimpleCrypter
+
+
+class EasybytezComFolder(SimpleCrypter):
+ __name__ = "EasybytezComFolder"
+ __type__ = "crypter"
+ __pattern__ = r"https?://(www\.)?easybytez\.com/users/\w+/\w+"
+ __version__ = "0.01"
+ __description__ = """Easybytez Crypter Plugin"""
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ LINK_PATTERN = r'<div class="link"><a href="(http://www\.easybytez\.com/\w+)" target="_blank">.+</a></div>'
+ TITLE_PATTERN = r'<Title>Files of (?P<title>.+) folder</Title>'
+ PAGES_PATTERN = r"<a href='[^']+'>(\d+)</a><a href='[^']+'>Next &#187;</a><br><small>\(\d+ total\)</small></div>"
+
+ def decrypt(self, pyfile):
+ self.html = self.load(pyfile.url, decode=True)
+
+ package_name, folder_name = self.getPackageNameAndFolder()
+
+ package_links = re.findall(self.LINK_PATTERN, self.html)
+
+ pages = re.search(self.PAGES_PATTERN, self.html)
+ if pages:
+ pages = int(pages.group(1))
+ else:
+ pages = 1
+
+ p = 2
+ while p <= pages:
+ self.html = self.load(pyfile.url, get={'page': p}, decode=True)
+ package_links += re.findall(self.LINK_PATTERN, self.html)
+ p += 1
+
+ self.logDebug('Package has %d links' % len(package_links))
+
+ if package_links:
+ self.packages = [(package_name, package_links, folder_name)]
+ else:
+ self.fail('Could not extract any links') \ No newline at end of file
diff --git a/module/plugins/crypter/GooGl.py b/module/plugins/crypter/GooGl.py
index 07de5e008..bcb1d7494 100644
--- a/module/plugins/crypter/GooGl.py
+++ b/module/plugins/crypter/GooGl.py
@@ -1,5 +1,20 @@
# -*- coding: utf-8 -*-
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
from module.plugins.Crypter import Crypter
from module.common.json_layer import json_loads
diff --git a/module/plugins/crypter/MBLinkInfo.py b/module/plugins/crypter/MBLinkInfo.py
new file mode 100644
index 000000000..e266c7722
--- /dev/null
+++ b/module/plugins/crypter/MBLinkInfo.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from module.plugins.Crypter import Crypter
+
+
+class MBLinkInfo(Crypter):
+ __name__ = "MBLinkInfo"
+ __type__ = "container"
+ __pattern__ = r"http://(?:www\.)?mblink\.info/?\?id=(\d+)"
+ __version__ = "0.02"
+ __description__ = """MBLink.Info Container Plugin"""
+ __author_name__ = ("Gummibaer", "stickell")
+ __author_mail__ = ("Gummibaer@wiki-bierkiste.de", "l.stickell@yahoo.it")
+
+ URL_PATTERN = r'<meta[^;]+; URL=(.*)["\']>'
+
+ def decrypt(self, pyfile):
+ src = self.load(pyfile.url)
+ found = re.search(self.URL_PATTERN, src)
+ if found:
+ link = found.group(1)
+ self.logDebug("Redirected to " + link)
+ self.core.files.addLinks([link], self.pyfile.package().id)
+ else:
+ self.fail('Unable to detect valid link')
diff --git a/module/plugins/crypter/Movie2kTo.py b/module/plugins/crypter/Movie2kTo.py
index f5800b498..097cb702e 100644
--- a/module/plugins/crypter/Movie2kTo.py
+++ b/module/plugins/crypter/Movie2kTo.py
@@ -9,11 +9,12 @@ class Movie2kTo(Crypter):
__name__ = 'Movie2kTo'
__type__ = 'container'
__pattern__ = r'http://(?:www\.)?movie2k\.to/(.*)\.html'
- __version__ = '0.3'
- __config__ = [('accepted_hosters', 'str', 'List of accepted hosters', 'Xvidstage, '),
+ __version__ = '0.5'
+ __config__ = [('accepted_hosters', 'str', 'List of accepted hosters', 'Xvidstage, Putlocker, '),
+ ('dir_quality', 'bool', 'Show the quality of the footage in the folder name', 'True'),
('whole_season', 'bool', 'Download whole season', 'False'),
('everything', 'bool', 'Download everything', 'False'),
- ('firstN', 'int', 'Download the first N files for each episode. The first file is probably all you will need.', '1')]
+ ('firstN', 'int', 'Download the first N files for each episode (the first file is probably all you will need)', '1')]
__description__ = """Movie2k.to Container Plugin"""
__author_name__ = ('4Christopher')
__author_mail__ = ('4Christopher@gmx.de')
@@ -47,21 +48,26 @@ class Movie2kTo(Crypter):
season_links += self.getInfoAndLinks('%s/%s' % (self.BASE_URL, url_path))
self.logDebug(season_links)
- self.packages.append(('%s: Season %s (%s)'
- % (self.name, season, self.qStat()), season_links, 'Season %s' % season))
+ folder = '%s: Season %s' % (self.name, season)
+ name = '%s%s' % (folder, self.qStat())
+ self.packages.append((name, season_links, folder))
self.qStatReset()
else:
links = self.getLinks()
- self.package.name = '%s%s' % (self.package.name, self.qStat())
- self.packages.append((self.package.name, links , self.package.folder))
+ name = '%s%s' % (self.package.name, self.qStat())
+ self.packages.append((name, links , self.package.folder))
def qStat(self):
if len(self.q) == 0: return ''
+ if not self.getConfig('dir_quality'): return ''
+ if len(self.q) == 1: return (' (Quality: %d, max (all hosters): %d)' % (self.q[0], self.max_q))
return (' (Average quality: %d, min: %d, max: %d, %s, max (all hosters): %d)'
% (sum(self.q) / float(len(self.q)), min(self.q), max(self.q), self.q, self.max_q))
+
def qStatReset(self):
- self.q = [] ## to calculate the average, min and max of the quality
- self.max_q = None
+ self.q = [] ## to calculate the average, min and max of the quality
+ self.max_q = None ## maximum quality of all hosters
+
def tvshow_number(self, number):
if int(number) < 10:
return '0%s' % number
@@ -81,8 +87,6 @@ class Movie2kTo(Crypter):
elif re.search(self.FILM_URL_PATH_PATTERN, self.url_path):
self.format = 'film'
pattern_re = re.search(self.FILM_URL_PATH_PATTERN, self.url_path)
-
-
self.name = pattern_re.group('name')
self.id = pattern_re.group('id')
self.logDebug('URL Path: %s (ID: %s, Name: %s, Format: %s)'
@@ -100,8 +104,8 @@ class Movie2kTo(Crypter):
re_quality = re.compile(r'.+?Quality:.+?smileys/(\d)\.gif')
## The quality is one digit. 0 is the worst and 5 is the best.
## Is not always there …
- re_hoster_id_html = re.compile(r'(?:<td height|<tr id).+?<a href=".*?(\d{7}).*?".+?&nbsp;([^<>]+?)</a>(.+?)</tr>')
re_hoster_id_js = re.compile(r'links\[(\d+?)\].+&nbsp;(.+?)</a>(.+?)</tr>')
+ re_hoster_id_html = re.compile(r'(?:<td height|<tr id).+?<a href=".*?(\d{7}).*?".+?&nbsp;([^<>]+?)</a>(.+?)</tr>')
## I assume that the ID is 7 digits longs
count = defaultdict(int)
matches = re_hoster_id_html.findall(self.html)
@@ -112,10 +116,10 @@ class Movie2kTo(Crypter):
match_q = re_quality.search(q_html)
if match_q:
quality = int(match_q.group(1))
- if self.max_q:
- if self.max_q < quality: self.max_q = quality
- else: ## was None before
+ if self.max_q == None:
self.max_q = quality
+ else:
+ if self.max_q < quality: self.max_q = quality
q_s = ', Quality: %d' % quality
else:
q_s = ', unknown quality'
@@ -128,14 +132,20 @@ class Movie2kTo(Crypter):
self.html = self.load('%s/tvshows-%s-%s.html' % (self.BASE_URL, h_id, self.name))
else:
self.logDebug('This is already the right ID')
- try:
- url = re.search(r'<a target="_blank" href="(http://.*?)"', self.html).group(1)
- self.logDebug('id: %s, %s: %s' % (h_id, hoster, url))
- links.append(url)
- except:
- self.logDebug('Failed to find the URL')
+ # The iframe tag must continue with a width. There where
+ # two iframes in the site and I try to make sure that it
+ # matches the right one. This is not (yet) nessesary
+ # because the right iframe happens to be the first iframe.
+ for pattern in (r'<a target="_blank" href="(http://[^"]*?)"', r'<iframe src="(http://[^"]*?)" width'):
+ try:
+ url = re.search(pattern, self.html).group(1)
+ except:
+ self.logDebug('Failed to find the URL (pattern %s)' % pattern)
+ else:
+ self.logDebug('id: %s, %s: %s' % (h_id, hoster, url))
+ links.append(url)
+ break
else:
self.logDebug('Not accepted: %s, ID: %s%s' % (hoster, h_id, q_s))
-
# self.logDebug(links)
return links
diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py
index a8eaac631..5e1ea347c 100644
--- a/module/plugins/crypter/NCryptIn.py
+++ b/module/plugins/crypter/NCryptIn.py
@@ -50,7 +50,8 @@ class NCryptIn(Crypter):
package_links = []
package_links.extend(self.handleWebLinks())
package_links.extend(self.handleContainers())
- package_links.extend(self.handleCNL2())
+ package_links.extend(self.handleCNL2())
+ package_links = self.removeContainers(package_links)
package_links = set(package_links)
# Pack
@@ -65,7 +66,20 @@ class NCryptIn(Crypter):
rexpr = re.compile(pattern, re.DOTALL)
content = re.sub(rexpr, "", content)
return content
-
+
+ def removeContainers(self,package_links):
+ tmp_package_links = package_links[:]
+ for link in tmp_package_links:
+ self.logDebug(link)
+ if ".dlc" in link or ".ccf" in link or ".rsdf" in link:
+ self.logDebug("Removing [%s] from package_links" % link)
+ package_links.remove(link)
+
+ if len(package_links) > 0:
+ return package_links
+ else:
+ return tmp_package_links
+
def isOnline(self):
if "Your folder does not exist" in self.cleanedHtml:
self.logDebug("File not found")
@@ -121,6 +135,19 @@ class NCryptIn(Crypter):
challenge, code = recaptcha.challenge(id)
postData['recaptcha_challenge_field'] = challenge
postData['recaptcha_response_field'] = code
+
+ # Resolve circlecaptcha
+ if "circlecaptcha" in form:
+ self.captcha = True
+ self.logDebug("Captcha protected")
+ captcha_img_url = "http://ncrypt.in/classes/captcha/circlecaptcha.php"
+ coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional')
+ self.logDebug("Captcha resolved, coords [%s]" % str(coords))
+ self.captcha_post_url = self.pyfile.url
+
+ postData['circle.x'] = coords[0]
+ postData['circle.y'] = coords[1]
+
# Unlock protection
postData['submit_protected'] = 'Continue to folder '
@@ -221,4 +248,4 @@ class NCryptIn(Crypter):
# Log and return
self.logDebug("Block has %d links" % len(links))
- return links \ No newline at end of file
+ return links
diff --git a/module/plugins/crypter/NetfolderIn.py b/module/plugins/crypter/NetfolderIn.py
index d71a73d0a..c5c602c27 100644
--- a/module/plugins/crypter/NetfolderIn.py
+++ b/module/plugins/crypter/NetfolderIn.py
@@ -1,22 +1,25 @@
# -*- coding: utf-8 -*-
-from module.plugins.Crypter import Crypter
import re
-class NetfolderIn(Crypter):
+from module.plugins.internal.SimpleCrypter import SimpleCrypter
+
+
+class NetfolderIn(SimpleCrypter):
__name__ = "NetfolderIn"
__type__ = "crypter"
__pattern__ = r"http://(?:www\.)?netfolder.in/((?P<id1>\w+)/\w+|folder.php\?folder_id=(?P<id2>\w+))"
- __version__ = "0.4"
+ __version__ = "0.6"
__description__ = """NetFolder Crypter Plugin"""
__author_name__ = ("RaNaN", "fragonib")
__author_mail__ = ("RaNaN@pyload.org", "fragonib[AT]yahoo[DOT]es")
+ TITLE_PATTERN = r'<div class="Text">Inhalt des Ordners <span(.*)>(?P<title>.+)</span></div>'
+
def decrypt(self, pyfile):
-
# Request package
self.html = self.load(pyfile.url)
-
+
# Check for password protection
if self.isPasswordProtected():
self.html = self.submitPassword()
@@ -31,54 +34,37 @@ class NetfolderIn(Crypter):
# Set package
self.packages = [(package_name, package_links, folder_name)]
-
-
+
def isPasswordProtected(self):
-
+
if '<input type="password" name="password"' in self.html:
self.logDebug("Links are password protected")
return True
return False
-
def submitPassword(self):
# Gather data
try:
m = re.match(self.__pattern__, self.pyfile.url)
- id = max(m.group('id1'), m.group('id2'))
+ id = max(m.group('id1'), m.group('id2'))
except AttributeError:
self.logDebug("Unable to get package id from url [%s]" % self.pyfile.url)
return
url = "http://netfolder.in/folder.php?folder_id=" + id
password = self.getPassword()
-
+
# Submit package password
- post = { 'password' : password, 'save' : 'Absenden' }
+ post = {'password': password, 'save': 'Absenden'}
self.logDebug("Submitting password [%s] for protected links with id [%s]" % (password, id))
html = self.load(url, {}, post)
-
+
# Check for invalid password
if '<div class="InPage_Error">' in html:
self.logDebug("Incorrect password, please set right password on Edit package form and retry")
return None
-
- return html
-
-
- def getPackageNameAndFolder(self):
- title_re = r'<div class="Text">Inhalt des Ordners <span(.*)>(?P<title>.+)</span></div>'
- m = re.search(title_re, self.html)
- if m is not None:
- name = folder = m.group('title')
- self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
- return name, folder
- else:
- name = self.pyfile.package().name
- folder = self.pyfile.package().folder
- self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
- return name, folder
-
-
+
+ return html
+
def getLinks(self):
links = re.search(r'name="list" value="(.*?)"', self.html).group(1).split(",")
self.logDebug("Package has %d links" % len(links))
diff --git a/module/plugins/crypter/SerienjunkiesOrg.py b/module/plugins/crypter/SerienjunkiesOrg.py
index dfe34ff6e..3fcc12e36 100644
--- a/module/plugins/crypter/SerienjunkiesOrg.py
+++ b/module/plugins/crypter/SerienjunkiesOrg.py
@@ -11,13 +11,13 @@ class SerienjunkiesOrg(Crypter):
__name__ = "SerienjunkiesOrg"
__type__ = "container"
__pattern__ = r"http://.*?(serienjunkies.org|dokujunkies.org)/.*?"
- __version__ = "0.36"
+ __version__ = "0.38"
__config__ = [
("changeNameSJ", "Packagename;Show;Season;Format;Episode", "Take SJ.org name", "Show"),
("changeNameDJ", "Packagename;Show;Format;Episode", "Take DJ.org name", "Show"),
("randomPreferred", "bool", "Randomize Preferred-List", False),
("hosterListMode", "OnlyOne;OnlyPreferred(One);OnlyPreferred(All);All", "Use for hosters (if supported)", "All"),
- ("hosterList", "str", "Preferred Hoster list (comma separated)", "RapidshareCom,UploadedTo,NetloadIn,FilefactoryCom,FreakshareNet,FilebaseTo,MegauploadCom,HotfileCom,DepositfilesCom,EasyshareCom,KickloadCom"),
+ ("hosterList", "str", "Preferred Hoster list (comma separated)", "RapidshareCom,UploadedTo,NetloadIn,FilefactoryCom,FreakshareNet,FilebaseTo,HotfileCom,DepositfilesCom,EasyshareCom,KickloadCom"),
("ignoreList", "str", "Ignored Hoster list (comma separated)", "MegauploadCom")
]
__description__ = """serienjunkies.org Container Plugin"""
@@ -30,6 +30,8 @@ class SerienjunkiesOrg(Crypter):
def getSJSrc(self, url):
src = self.req.load(str(url))
+ if "This website is not available in your country" in src:
+ self.fail("Not available in your country")
if not src.find("Enter Serienjunkies") == -1:
sleep(1)
src = self.req.load(str(url))
diff --git a/module/plugins/crypter/SpeedLoadOrgFolder.py b/module/plugins/crypter/SpeedLoadOrgFolder.py
index 5b350787f..f85ede6f3 100644
--- a/module/plugins/crypter/SpeedLoadOrgFolder.py
+++ b/module/plugins/crypter/SpeedLoadOrgFolder.py
@@ -1,5 +1,20 @@
# -*- coding: utf-8 -*-
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
from module.plugins.internal.SimpleCrypter import SimpleCrypter
class SpeedLoadOrgFolder(SimpleCrypter):
diff --git a/module/plugins/crypter/UploadedToFolder.py b/module/plugins/crypter/UploadedToFolder.py
index d4534297e..c514f23d0 100644
--- a/module/plugins/crypter/UploadedToFolder.py
+++ b/module/plugins/crypter/UploadedToFolder.py
@@ -1,13 +1,30 @@
# -*- coding: utf-8 -*-
-from module.plugins.Crypter import Crypter
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
import re
-class UploadedToFolder(Crypter):
+from module.plugins.internal.SimpleCrypter import SimpleCrypter
+
+
+class UploadedToFolder(SimpleCrypter):
__name__ = "UploadedToFolder"
__type__ = "crypter"
- __pattern__ = r"http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|list)/(?P<id>\w+)"
- __version__ = "0.1"
+ __pattern__ = r"http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<id>\w+)"
+ __version__ = "0.3"
__description__ = """UploadedTo Crypter Plugin"""
__author_name__ = ("stickell")
__author_mail__ = ("l.stickell@yahoo.it")
@@ -31,15 +48,3 @@ class UploadedToFolder(Crypter):
self.logDebug('Package has %d links' % len(package_links))
self.packages = [(package_name, package_links, folder_name)]
-
- def getPackageNameAndFolder(self):
- m = re.search(self.TITLE_PATTERN, self.html)
- if m:
- name = folder = m.group('title')
- self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
- return name, folder
- else:
- name = self.pyfile.package().name
- folder = self.pyfile.package().folder
- self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
- return name, folder
diff --git a/module/plugins/crypter/YoutubeBatch.py b/module/plugins/crypter/YoutubeBatch.py
index 2e68dfe02..72b72aab7 100644
--- a/module/plugins/crypter/YoutubeBatch.py
+++ b/module/plugins/crypter/YoutubeBatch.py
@@ -2,26 +2,41 @@
# -*- coding: utf-8 -*-
import re
+import json
from module.plugins.Crypter import Crypter
+API_KEY = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0"
+
class YoutubeBatch(Crypter):
__name__ = "YoutubeBatch"
__type__ = "container"
- __pattern__ = r"http://(?:[^/]*?)youtube\.com/((?:view_play_list|playlist|.*?feature=PlayList).*?[\?&](?:list|p)=|user/)(\w+)"
- __version__ = "0.92"
+ __pattern__ = r"https?://(?:[^/]*?)youtube\.com/(?:(?:view_play_list|playlist|.*?feature=PlayList).*?[?&](?:list|p)=)([a-zA-Z0-9-_]+)"
+ __version__ = "0.93"
__description__ = """Youtube.com Channel Download Plugin"""
- __author_name__ = ("RaNaN", "Spoob", "zoidberg")
- __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "zoidberg@mujmail.cz")
+ __author_name__ = ("RaNaN", "Spoob", "zoidberg", "roland")
+ __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "zoidberg@mujmail.cz", "roland@enkore.de")
+
+ def get_videos(self, playlist_id, token=None):
+ url = "https://www.googleapis.com/youtube/v3/playlistItems?playlistId=%s&part=snippet&key=%s&maxResults=50" % (playlist_id, API_KEY)
+ if token:
+ url += "&pageToken=" + token
+
+ response = json.loads(self.load(url))
+
+ for item in response["items"]:
+ if item["kind"] == "youtube#playlistItem" and item["snippet"]["resourceId"]["kind"] == "youtube#video":
+ yield "http://youtube.com/watch?v=" + item["snippet"]["resourceId"]["videoId"]
+
+ if "nextPageToken" in response:
+ for item in self.get_videos(playlist_id, response["nextPageToken"]):
+ yield item
def decrypt(self, pyfile):
match_id = re.match(self.__pattern__, self.pyfile.url)
- if match_id.group(1) == "user/":
- url = "http://gdata.youtube.com/feeds/api/users/%s/uploads?v=2" % match_id.group(2)
- else:
- url = "http://gdata.youtube.com/feeds/api/playlists/%s?v=2" % match_id.group(2)
-
- rep = self.load(url)
new_links = []
- new_links.extend(re.findall(r"href\='(http:\/\/www.youtube.com\/watch\?v\=[^']+)&", rep))
+ playlist_id = match_id.group(1)
+
+ new_links.extend(self.get_videos(playlist_id))
+
self.packages.append((self.pyfile.package().name, new_links, self.pyfile.package().name))
diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9kw.py
index a01ce9576..bb2b8c862 100755
--- a/module/plugins/hooks/Captcha9kw.py
+++ b/module/plugins/hooks/Captcha9kw.py
@@ -30,17 +30,22 @@ from module.plugins.Hook import Hook
class Captcha9kw(Hook):
__name__ = "Captcha9kw"
- __version__ = "0.03"
+ __version__ = "0.04"
__description__ = """send captchas to 9kw.eu"""
__config__ = [("activated", "bool", "Activated", True),
("force", "bool", "Force CT even if client is connected", True),
+ ("https", "bool", "Enable HTTPS", "False"),
+ ("confirm", "bool", "Confirm Captcha", "False"),
+ ("captchaperhour", "int", "Captcha per hour", "9999"),
+ ("prio", "int", "Prio (1-10)", "0"),
("passkey", "password", "API key", ""),]
__author_name__ = ("RaNaN")
__author_mail__ = ("RaNaN@pyload.org")
- API_URL = "http://www.9kw.eu/index.cgi"
+ API_URL = "://www.9kw.eu/index.cgi"
def setup(self):
+ self.API_URL = "https"+self.API_URL if self.getConfig("https") else "http"+self.API_URL
self.info = {}
def getCredits(self):
@@ -68,6 +73,10 @@ class Captcha9kw(Hook):
response = getURL(self.API_URL, post = {
"apikey": self.getConfig("passkey"),
+ "prio": self.getConfig("prio"),
+ "confirm": self.getConfig("confirm"),
+ "captchaperhour": self.getConfig("captchaperhour"),
+ "maxtimeout": "220",
"pyload": "1",
"source": "pyload",
"base64": "1",
@@ -78,7 +87,7 @@ class Captcha9kw(Hook):
if response.isdigit():
self.logInfo(_("NewCaptchaID from upload: %s : %s" % (response,task.captchaFile)))
- for i in range(1, 200, 2):
+ for i in range(1, 220, 1):
response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
if(response2 != ""):
diff --git a/module/plugins/hoster/ARD.py b/module/plugins/hoster/ARD.py
new file mode 100644
index 000000000..5ab65cd4b
--- /dev/null
+++ b/module/plugins/hoster/ARD.py
@@ -0,0 +1,80 @@
+
+import subprocess
+import re
+import os.path
+import os
+
+from module.utils import save_join, save_path
+from module.plugins.Hoster import Hoster
+
+# Requires rtmpdump
+# by Roland Beermann
+
+class RTMP:
+ # TODO: Port to some RTMP-library like rtmpy or similar
+ # TODO?: Integrate properly into the API of pyLoad
+
+ command = "rtmpdump"
+
+ @classmethod
+ def download_rtmp_stream(cls, url, output_file, playpath=None):
+ opts = [
+ "-r", url,
+ "-o", output_file,
+ ]
+ if playpath:
+ opts.append("--playpath")
+ opts.append(playpath)
+
+ cls._invoke_rtmpdump(opts)
+
+ @classmethod
+ def _invoke_rtmpdump(cls, opts):
+ args = [
+ cls.command
+ ]
+ args.extend(opts)
+
+ return subprocess.check_call(args)
+
+class ARD(Hoster):
+ __name__ = "ARD Mediathek"
+ __version__ = "0.1"
+ __pattern__ = r"http://www\.ardmediathek\.de/.*"
+ __config__ = []
+
+ def process(self, pyfile):
+ site = self.load(pyfile.url)
+
+ avail_videos = re.findall(r"""mediaCollection.addMediaStream\(0, ([0-9]*), "([^\"]*)", "([^\"]*)", "[^\"]*"\);""", site)
+ avail_videos.sort(key=lambda videodesc: int(videodesc[0]), reverse=True) # The higher the number, the better the quality
+
+ quality, url, playpath = avail_videos[0]
+
+ pyfile.name = re.search(r"<h1>([^<]*)</h1>", site).group(1)
+
+ if url.startswith("http"):
+ # Best quality is available over HTTP. Very rare.
+ self.download(url)
+ else:
+ pyfile.setStatus("downloading")
+
+ download_folder = self.config['general']['download_folder']
+
+ location = save_join(download_folder, pyfile.package().folder)
+
+ if not os.path.exists(location):
+ os.makedirs(location, int(self.core.config["permission"]["folder"], 8))
+
+ if self.core.config["permission"]["change_dl"] and os.name != "nt":
+ try:
+ uid = getpwnam(self.config["permission"]["user"])[2]
+ gid = getgrnam(self.config["permission"]["group"])[2]
+
+ chown(location, uid, gid)
+ except Exception, e:
+ self.log.warning(_("Setting User and Group failed: %s") % str(e))
+
+ output_file = save_join(location, save_path(pyfile.name)) + os.path.splitext(playpath)[1]
+
+ RTMP.download_rtmp_stream(url, playpath=playpath, output_file=output_file)
diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py
index 08a54d509..7608b193d 100644
--- a/module/plugins/hoster/CloudzerNet.py
+++ b/module/plugins/hoster/CloudzerNet.py
@@ -20,7 +20,7 @@ class CloudzerNet(SimpleHoster):
__name__ = "CloudzerNet"
__type__ = "hoster"
__pattern__ = r"http://(www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)(?P<ID>\w+).*"
- __version__ = "0.01"
+ __version__ = "0.02"
__description__ = """Cloudzer.net hoster plugin"""
__author_name__ = ("gs", "z00nx")
__author_mail__ = ("I-_-I-_-I@web.de", "z00nx0@gmail.com")
@@ -56,7 +56,7 @@ class CloudzerNet(SimpleHoster):
self.retry()
elif "Sie haben die max" in response["err"] or "You have reached the max" in response["err"]:
self.logDebug("Download limit reached, waiting an hour")
- self.setWait(3600)
+ self.setWait(3600, True)
self.wait()
if "type" in response:
if response["type"] == "download":
diff --git a/module/plugins/hoster/CzshareCom.py b/module/plugins/hoster/CzshareCom.py
index a4a811e82..347427586 100644
--- a/module/plugins/hoster/CzshareCom.py
+++ b/module/plugins/hoster/CzshareCom.py
@@ -16,6 +16,9 @@
@author: zoidberg
"""
+# Test links (random.bin):
+# http://czshare.com/5278880/random.bin
+
import re
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError
from module.utils import parseFileSize
@@ -24,7 +27,7 @@ class CzshareCom(SimpleHoster):
__name__ = "CzshareCom"
__type__ = "hoster"
__pattern__ = r"http://(\w*\.)*czshare\.(com|cz)/(\d+/|download.php\?).*"
- __version__ = "0.92"
+ __version__ = "0.93"
__description__ = """CZshare.com"""
__author_name__ = ("zoidberg")
@@ -80,7 +83,7 @@ class CzshareCom(SimpleHoster):
self.resetAccount()
# download the file, destination is determined by pyLoad
- self.download("http://czshare.com/profi_down.php", cookies=True, post=inputs)
+ self.download("http://czshare.com/profi_down.php", post=inputs, disposition=True)
self.checkDownloadedFile()
def handleFree(self):
diff --git a/module/plugins/hoster/DebridItaliaCom.py b/module/plugins/hoster/DebridItaliaCom.py
index 121a141b3..470c4ae5d 100644
--- a/module/plugins/hoster/DebridItaliaCom.py
+++ b/module/plugins/hoster/DebridItaliaCom.py
@@ -47,7 +47,7 @@ class DebridItaliaCom(Hoster):
self.logDebug("XML data: %s" % page)
if 'File not available' in page:
- self.offline()
+ self.fail('File not available')
else:
new_url = re.search(r'<a href="(?:[^"]+)">(?P<direct>[^<]+)</a>', page).group('direct')
diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py
index 0deaa782e..96e3d93d2 100644
--- a/module/plugins/hoster/EasybytezCom.py
+++ b/module/plugins/hoster/EasybytezCom.py
@@ -16,16 +16,14 @@
@author: zoidberg
"""
-import re
-from random import random
-from pycurl import LOW_SPEED_TIME
from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
class EasybytezCom(XFileSharingPro):
__name__ = "EasybytezCom"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w+).*"
- __version__ = "0.12"
+ __version__ = "0.14"
__description__ = """easybytez.com"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -33,52 +31,17 @@ class EasybytezCom(XFileSharingPro):
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'<h1>File not available</h1>'
-
- DIRECT_LINK_PATTERN = r'(http://(\w+\.easybytez\.com|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)'
+ FILE_OFFLINE_PATTERN = r'<h1>File not available</h1>'
+
+ DIRECT_LINK_PATTERN = r'(http://(\w+\.(easybytez|zingload)\.com|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)'
OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)'
ERROR_PATTERN = r'(?:class=["\']err["\'][^>]*>|<Center><b>)(.*?)</'
-
+
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())
- 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)
- #wait for file to upload to easybytez.com
- self.req.http.c.setopt(LOW_SPEED_TIME, 600)
- self.html = self.load(action, post = inputs)
-
- action, inputs = self.parseHtmlForm('F1')
- if not inputs: self.parseError('TEXTAREA')
- self.logDebug(inputs)
- if inputs['st'] == 'OK':
- self.html = self.load(action, post = inputs)
- elif inputs['st'] == 'Can not leech file':
- self.retry(max_tries=20, wait_time=180, reason=inputs['st'])
- else:
- self.fail(inputs['st'])
-
- #get easybytez.com link for uploaded file
- 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()
-getInfo = create_getInfo(EasybytezCom) \ No newline at end of file
+getInfo = create_getInfo(EasybytezCom)
diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py
index ad278e60f..7e6673210 100644
--- a/module/plugins/hoster/EgoFilesCom.py
+++ b/module/plugins/hoster/EgoFilesCom.py
@@ -28,12 +28,12 @@ class EgoFilesCom(SimpleHoster):
__name__ = "EgoFilesCom"
__type__ = "hoster"
__pattern__ = r"https?://(www\.)?egofiles.com/(\w+)"
- __version__ = "0.11"
+ __version__ = "0.13"
__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_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>[^\t]+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|'
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>'
diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py
index 718423986..fd91bb023 100644
--- a/module/plugins/hoster/ExtabitCom.py
+++ b/module/plugins/hoster/ExtabitCom.py
@@ -17,15 +17,17 @@
"""
import re
+
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
from module.plugins.ReCaptcha import ReCaptcha
from module.common.json_layer import json_loads
+
class ExtabitCom(SimpleHoster):
__name__ = "ExtabitCom"
__type__ = "hoster"
- __pattern__ = r"http://(\w+\.)*extabit\.com/(file|go)/(?P<ID>\w+)"
- __version__ = "0.2"
+ __pattern__ = r"http://(\w+\.)*extabit\.com/(file|go|fid)/(?P<ID>\w+)"
+ __version__ = "0.3"
__description__ = """Extabit.com"""
__author_name__ = ("zoidberg")
@@ -33,34 +35,34 @@ class ExtabitCom(SimpleHoster):
FILE_SIZE_PATTERN = r'<th>Size:</th>\s*<td class="col-fileinfo">(?P<S>[^<]+)</td>'
FILE_OFFLINE_PATTERN = r'<h1>File not found</h1>'
TEMP_OFFLINE_PATTERN = r">(File is temporary unavailable|No download mirror)<"
-
+
DOWNLOAD_LINK_PATTERN = r'"(http://guest\d+\.extabit\.com/[a-z0-9]+/.*?)"'
- def handleFree(self):
+ def handleFree(self):
if r">Only premium users can download this file" in self.html:
self.fail("Only premium users can download this file")
-
+
m = re.search(r"Next free download from your ip will be available in <b>(\d+)\s*minutes", self.html)
if m:
self.setWait(int(m.group(1)) * 60, True)
- self.wait()
+ self.wait()
elif "The daily downloads limit from your IP is exceeded" in self.html:
self.setWait(3600, True)
self.wait()
-
+
self.logDebug("URL: " + self.req.http.lastEffectiveURL)
m = re.match(self.__pattern__, self.req.http.lastEffectiveURL)
- fileID = m.group('ID') if m else self.file_info('ID')
-
+ fileID = m.group('ID') if m else self.file_info('ID')
+
m = re.search(r'recaptcha/api/challenge\?k=(\w+)', self.html)
if m:
recaptcha = ReCaptcha(self)
captcha_key = m.group(1)
-
+
for i in range(5):
get_data = {"type": "recaptcha"}
get_data["challenge"], get_data["capture"] = recaptcha.challenge(captcha_key)
- response = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get = get_data))
+ response = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data))
if "ok" in response:
self.correctCaptcha()
break
@@ -70,15 +72,16 @@ class ExtabitCom(SimpleHoster):
self.fail("Invalid captcha")
else:
self.parseError('Captcha')
-
+
if not "href" in response: self.parseError('JSON')
-
+
self.html = self.load("http://extabit.com/file/%s%s" % (fileID, response['href']))
m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
if not m:
self.parseError('Download URL')
url = m.group(1)
self.logDebug("Download URL: " + url)
- self.download(url)
+ self.download(url)
+
-getInfo = create_getInfo(ExtabitCom) \ No newline at end of file
+getInfo = create_getInfo(ExtabitCom)
diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py
index cc0b18c96..1dbf9fe8f 100644
--- a/module/plugins/hoster/FastshareCz.py
+++ b/module/plugins/hoster/FastshareCz.py
@@ -16,27 +16,39 @@
@author: zoidberg
"""
+# Test links (random.bin):
+# http://www.fastshare.cz/2141189/random.bin
+
import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns
+
class FastshareCz(SimpleHoster):
__name__ = "FastshareCz"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)?fastshare.cz/\d+/.+"
- __version__ = "0.14"
+ __version__ = "0.15"
__description__ = """FastShare.cz"""
- __author_name__ = ("zoidberg")
+ __author_name__ = ("zoidberg", "stickell")
- FILE_NAME_PATTERN = r'<h[23]><b><span style=color:black;>(?P<N>[^<]+)</b></h[23]>'
- FILE_SIZE_PATTERN = r'<tr><td>Velikost: </td><td style=font-weight:bold>(?P<S>[^<]+)</td></tr>'
+ FILE_INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*(?:Velikost|Size)\s*: (?P<S>[^,]+),'
FILE_OFFLINE_PATTERN = ur'<td align=center>Tento soubor byl smazán'
- SH_COOKIES = [("fastshare.cz","lang","cs")]
FILE_URL_REPLACEMENTS = [('#.*','')]
FREE_URL_PATTERN = ur'<form method=post action=(/free/.*?)><b>Stáhnout FREE.*?<img src="([^"]*)">'
PREMIUM_URL_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+\&[^\s\"\'<>]+)'
NOT_ENOUGH_CREDIC_PATTERN = "Nem.te dostate.n. kredit pro sta.en. tohoto souboru"
+ def process(self, pyfile):
+ pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS)
+ self.req.setOption("timeout", 120)
+ if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.handlePremium()
+ else:
+ self.html = self.load(pyfile.url, decode = not self.SH_BROKEN_ENCODING, cookies = self.SH_COOKIES)
+ self.getFileInfo()
+ self.handleFree()
+
def handleFree(self):
if u">100% FREE slotů je plných.<" in self.html:
self.setWait(60, False)
@@ -60,13 +72,20 @@ class FastshareCz(SimpleHoster):
self.retry(6, "Paralell download")
def handlePremium(self):
- if self.NOT_ENOUGH_CREDIC_PATTERN in self.html:
- self.logWarning('Not enough traffic left')
- self.resetAccount()
+ header = self.load(self.pyfile.url, just_header=True)
+ if 'location' in header:
+ url = header['location']
+ else:
+ self.html = self.load(self.pyfile.url)
+ self.getFileInfo()
+ if self.NOT_ENOUGH_CREDIC_PATTERN in self.html:
+ self.logWarning('Not enough traffic left')
+ self.resetAccount()
+
+ found = re.search(self.PREMIUM_URL_PATTERN, self.html)
+ if not found: self.parseError("Premium URL")
+ url = found.group(1)
- found = re.search(self.PREMIUM_URL_PATTERN, self.html)
- if not found: self.parseError("Premium URL")
- url = found.group(1)
self.logDebug("PREMIUM URL: %s" % url)
self.download(url)
diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py
index 66d26c999..fdde1f9d7 100644
--- a/module/plugins/hoster/FilefactoryCom.py
+++ b/module/plugins/hoster/FilefactoryCom.py
@@ -1,149 +1,133 @@
# -*- coding: utf-8 -*-
+
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
+# Test links (random.bin):
+# http://www.filefactory.com/file/ymxkmdud2o3/n/random.bin
+
+import re
+
+from module.plugins.internal.SimpleHoster import SimpleHoster
from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.ReCaptcha import ReCaptcha
from module.utils import parseFileSize
-from module.plugins.Plugin import chunks
-from module.common.json_layer import json_loads
-import re
-def checkFile(plugin, urls):
- url_dict = {}
-
+def getInfo(urls):
+ file_info = list()
+ list_ids = dict()
+
+ # Create a dict id:url. Will be used to retrieve original url
for url in urls:
- url_dict[re.search(plugin.__pattern__, url).group('id')] = (url, 0, 0, url)
- url_ids = url_dict.keys()
- urls = map(lambda url_id: 'http://www.filefactory.com/file/' + url_id, url_ids)
-
- html = getURL("http://www.filefactory.com/tool/links.php", post = {"func": "links", "links": "\n".join(urls)}, decode=True)
-
- for m in re.finditer(plugin.LC_INFO_PATTERN, html):
- if m.group('id') in url_ids:
- url_dict[m.group('id')] = (m.group('name'), parseFileSize(m.group('size')), 2, url_dict[m.group('id')][3])
-
- for m in re.finditer(plugin.LC_OFFLINE_PATTERN, html):
- if m.group('id') in url_ids:
- url_dict[m.group('id')] = (url_dict[m.group('id')][0], 0, 1, url_dict[m.group('id')][3])
-
- file_info = url_dict.values()
-
+ m = re.search(FilefactoryCom.__pattern__, url)
+ list_ids[m.group('id')] = url
+
+ # WARN: There could be a limit of urls for request
+ post_data = {'func': 'links', 'links': '\n'.join(urls)}
+ rep = getURL('http://www.filefactory.com/tool/links.php', post=post_data, decode=True)
+
+ # Online links
+ for m in re.finditer(
+ r'innerText">\s*<h1 class="name">(?P<N>.+) \((?P<S>[\w.]+) (?P<U>\w+)\)</h1>\s*<p>http://www.filefactory.com/file/(?P<ID>\w+).*</p>\s*<p class="hidden size">',
+ rep):
+ file_info.append((m.group('N'), parseFileSize(m.group('S'), m.group('U')), 2, list_ids[m.group('ID')]))
+
+ # Offline links
+ for m in re.finditer(
+ r'innerText">\s*<h1>(http://www.filefactory.com/file/(?P<ID>\w+)/)</h1>\s*<p>\1</p>\s*<p class="errorResponse">Error: file not found</p>',
+ rep):
+ file_info.append((list_ids[m.group('ID')], 0, 1, list_ids[m.group('ID')]))
+
return file_info
-
-class FilefactoryCom(Hoster):
+
+
+class FilefactoryCom(SimpleHoster):
__name__ = "FilefactoryCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+).*" # URLs given out are often longer but this is the requirement
- __version__ = "0.36"
+ __pattern__ = r"https?://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)"
+ __version__ = "0.41"
__description__ = """Filefactory.Com File Download Hoster"""
- __author_name__ = ("paulking", "zoidberg")
-
- LC_INFO_PATTERN = r'<h1 class="name">(?P<name>[^<]+) \((?P<size>[0-9.]+ \w+)\)</h1>\s*<p>http://www.filefactory.com/file/(?P<id>\w+)/'
- LC_OFFLINE_PATTERN = r'<p>http://www.filefactory.com/file/(?P<id>\w+)/</p>\s*<p class="errorResponse">'
-
- FILE_OFFLINE_PATTERN = r'<title>File Not Found'
- FILE_NAME_PATTERN = r'<span class="last">(?P<name>.*?)</span>'
- FILE_INFO_PATTERN = r'<span>(?P<size>\d(\d|\.)*) (?P<units>..) file uploaded'
-
- FILE_CHECK_PATTERN = r'check:\s*\'(?P<check>.*?)\''
- CAPTCHA_KEY_PATTERN = r'Recaptcha.create\(\s*"(.*?)",'
- WAIT_PATTERN = r'id="startWait" value="(?P<wait>\d+)"'
- FILE_URL_PATTERN = r'<p[^>]*?id="downloadLinkTarget"[^>]*>\s*<a href="(?P<url>.*?)"'
-
- def setup(self):
- self.multiDL = self.resumeDownloads = self.premium
+ __author_name__ = ("stickell")
+ __author_mail__ = ("l.stickell@yahoo.it")
+
+ DIRECT_LINK_PATTERN = r'<section id="downloadLink">\s*<p class="textAlignCenter">\s*<a href="([^"]+)">[^<]+</a>\s*</p>\s*</section>'
def process(self, pyfile):
- # Check file
- pyfile.name, pyfile.size, status, self.url = checkFile(self, [pyfile.url])[0]
- if status != 2: self.offline()
- self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size))
-
- # Handle downloading
- url = self.checkDirectDownload(pyfile.url)
- if url:
- self.download(url)
- else:
- self.html = self.load(pyfile.url, decode = True)
-
- if self.premium:
- self.handlePremium()
- else:
- self.handleFree()
-
- def checkDirectDownload(self, url):
- for i in range(5):
- header = self.load(url, just_header = True)
+ if not re.match(self.__pattern__ + r'/n/.+', pyfile.url): # Not in standard format
+ header = self.load(pyfile.url, just_header=True)
if 'location' in header:
- url = header['location'].strip()
- if not url.startswith("http://"):
- url = "http://www.filefactory.com" + url
- self.logDebug('URL: ' + url)
- elif 'content-disposition' in header:
- return url
-
- return False
-
+ self.pyfile.url = 'http://www.filefactory.com' + header['location']
+
+ if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.handlePremium()
+ else:
+ self.handleFree()
+
def handleFree(self):
+ self.html = self.load(self.pyfile.url, decode=True)
if "Currently only Premium Members can download files larger than" in self.html:
self.fail("File too large for free download")
elif "All free download slots on this server are currently in use" in self.html:
self.retry(50, 900, "All free slots are busy")
-
- # Check Id
- self.check = re.search(self.FILE_CHECK_PATTERN, self.html).group('check')
- self.logDebug("File check code is [%s]" % self.check)
-
- # Resolve captcha
- found = re.search(self.CAPTCHA_KEY_PATTERN, self.html)
- recaptcha_key = found.group(1) if found else "6LeN8roSAAAAAPdC1zy399Qei4b1BwmSBSsBN8zm"
- recaptcha = ReCaptcha(self)
-
- # Try up to 5 times
- for i in range(5):
- challenge, code = recaptcha.challenge(recaptcha_key)
- response = json_loads(self.load("http://www.filefactory.com/file/checkCaptcha.php",
- post={"check" : self.check, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code}))
- if response['status'] == 'ok':
- self.correctCaptcha()
- break
- else:
- self.invalidCaptcha()
- else:
- self.fail("No valid captcha after 5 attempts")
-
- # This will take us to a wait screen
- waiturl = "http://www.filefactory.com" + response['path']
- self.logDebug("Fetching wait with url [%s]" % waiturl)
- waithtml = self.load(waiturl, decode=True)
- found = re.search(r'<a href="(http://www.filefactory.com/dlf/.*?)"', waithtml)
- waithtml = self.load(found.group(1), decode=True)
-
- # Find the wait value and wait
- wait = int(re.search(self.WAIT_PATTERN, waithtml).group('wait'))
- self.logDebug("Waiting %d seconds." % wait)
- self.setWait(wait, True)
+
+ # Load the page that contains the direct link
+ url = re.search(r"document\.location\.host \+\s*'(.+)';", self.html)
+ if not url:
+ self.parseError('Unable to detect free link')
+ url = 'http://www.filefactory.com' + url.group(1)
+ self.html = self.load(url, decode=True)
+
+ # Free downloads wait time
+ waittime = re.search(r'id="startWait" value="(\d+)"', self.html)
+ if not waittime:
+ self.parseError('Unable to detect wait time')
+ self.setWait(int(waittime.group(1)))
self.wait()
- # Now get the real download url and retrieve the file
- url = re.search(self.FILE_URL_PATTERN,waithtml).group('url')
- # this may either download our file or forward us to an error page
- self.logDebug("Download URL: %s" % url)
- self.download(url)
-
+ # Parse the direct link and download it
+ direct = re.search(r'data-href-direct="(.*)" class="button', self.html)
+ if not direct:
+ self.parseError('Unable to detect free direct link')
+ direct = direct.group(1)
+ self.logDebug('DIRECT LINK: ' + direct)
+ self.download(direct, disposition=True)
+
check = self.checkDownload({"multiple": "You are currently downloading too many files at once.",
"error": '<div id="errorMessage">'})
if check == "multiple":
- self.setWait(15*60)
self.logDebug("Parallel downloads detected; waiting 15 minutes")
- self.wait()
- self.retry()
+ self.retry(wait_time=15 * 60, reason='Parallel downloads')
elif check == "error":
self.fail("Unknown error")
-
+
def handlePremium(self):
- self.fail('Please enable direct downloads')
-
-def getInfo(urls):
- for chunk in chunks(urls, 100): yield checkFile(FilefactoryCom, chunk)
+ header = self.load(self.pyfile.url, just_header=True)
+ if 'location' in header:
+ url = header['location'].strip()
+ if not url.startswith("http://"):
+ url = "http://www.filefactory.com" + url
+ elif 'content-disposition' in header:
+ url = self.pyfile.url
+ else:
+ html = self.load(self.pyfile.url)
+ found = re.search(self.DIRECT_LINK_PATTERN, html)
+ if found:
+ url = found.group(1)
+ else:
+ self.parseError('Unable to detect premium direct link')
+
+ self.logDebug('DIRECT PREMIUM LINK: ' + url)
+ self.download(url, disposition=True)
diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py
index 0e405930f..1e856c41d 100644
--- a/module/plugins/hoster/MediafireCom.py
+++ b/module/plugins/hoster/MediafireCom.py
@@ -18,21 +18,23 @@
import re
from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo
-from module.plugins.ReCaptcha import ReCaptcha
+from module.plugins.internal.CaptchaService import SolveMedia
from module.network.RequestFactory import getURL
+
def replace_eval(js_expr):
return js_expr.replace(r'eval("', '').replace(r"\'", r"'").replace(r'\"', r'"')
+
def checkHTMLHeader(url):
try:
for i in range(3):
- header = getURL(url, just_header = True)
+ header = getURL(url, just_header=True)
for line in header.splitlines():
line = line.lower()
- if 'location' in line:
+ if 'location' in line:
url = line.split(':', 1)[1].strip()
- if 'error.php?errno=320' in url:
+ if 'error.php?errno=320' in url:
return url, 1
if not url.startswith('http://'): url = 'http://www.mediafire.com' + url
break
@@ -42,9 +44,10 @@ def checkHTMLHeader(url):
break
except:
return url, 3
-
+
return url, 0
+
def getInfo(urls):
for url in urls:
location, status = checkHTMLHeader(url)
@@ -52,52 +55,53 @@ def getInfo(urls):
file_info = (url, 0, status, url)
else:
file_info = parseFileInfo(MediafireCom, url, getURL(url, decode=True))
- yield file_info
+ yield file_info
+
class MediafireCom(SimpleHoster):
__name__ = "MediafireCom"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)*mediafire\.com/(file/|(view/?|download.php)?\?)(\w{11}|\w{15})($|/)"
- __version__ = "0.78"
+ __version__ = "0.79"
__description__ = """Mediafire.com plugin - free only"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
DOWNLOAD_LINK_PATTERN = r'<div class="download_link"[^>]*(?:z-index:(?P<zindex>\d+))?[^>]*>\s*<a href="(?P<href>http://[^"]+)"'
JS_KEY_PATTERN = r"DoShow\('mfpromo1'\);[^{]*{((\w+)='';.*?)eval\(\2\);"
- JS_ZMODULO_PATTERN = r"\('z-index'\)\) \% (\d+)\)\);"
- RECAPTCHA_PATTERN = r'src="http://(?:api.recaptcha.net|www.google.com/recaptcha/api)/challenge\?k=([^"]+)">'
+ JS_ZMODULO_PATTERN = r"\('z-index'\)\) \% (\d+)\)\);"
+ SOLVEMEDIA_PATTERN = r'http://api\.solvemedia\.com/papi/challenge\.noscript\?k=([^"]+)'
PAGE1_ACTION_PATTERN = r'<link rel="canonical" href="([^"]+)"/>'
PASSWORD_PATTERN = r'<form name="form_password"'
FILE_NAME_PATTERN = r'<META NAME="description" CONTENT="(?P<N>[^"]+)"/>'
FILE_INFO_PATTERN = r"oFileSharePopup\.ald\('(?P<ID>[^']*)','(?P<N>[^']*)','(?P<S>[^']*)','','(?P<sha256>[^']*)'\)"
FILE_OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>'
-
+
def setup(self):
self.multiDL = False
def process(self, pyfile):
pyfile.url = re.sub(r'/view/?\?', '/?', pyfile.url)
-
+
self.url, result = checkHTMLHeader(pyfile.url)
self.logDebug('Location (%d): %s' % (result, self.url))
-
+
if result == 0:
- self.html = self.load(self.url, decode = True)
- self.checkCaptcha()
- self.multiDL = True
+ self.html = self.load(self.url, decode=True)
+ self.checkCaptcha()
+ self.multiDL = True
self.check_data = self.getFileInfo()
-
+
if self.account:
self.handlePremium()
else:
self.handleFree()
elif result == 1:
- self.offline()
+ self.offline()
else:
- self.multiDL = True
- self.download(self.url, disposition = True)
+ self.multiDL = True
+ self.download(self.url, disposition=True)
def handleFree(self):
passwords = self.getPassword().splitlines()
@@ -108,55 +112,23 @@ class MediafireCom(SimpleHoster):
self.html = self.load(self.url, post={"downloadp": password})
else:
self.fail("No or incorrect password")
-
- """
- links = re.findall(self.DOWNLOAD_LINK_PATTERN, self.html)
- link_count = len(links)
- self.logDebug('LINKS ', links)
-
- if link_count == 0:
- self.retry(3, 0, "No links found")
-
- elif link_count > 1:
- found = re.search(self.JS_KEY_PATTERN, self.html)
- try:
- result = self.js.eval(found.group(1))
- zmodulo = int(re.search(self.JS_ZMODULO_PATTERN, result).group(1))
- self.logDebug("ZMODULO: %d" % zmodulo)
- except Exception, e:
- self.logDebug(e)
- self.parseError("ZMODULO")
-
- max_index = 0
- for index, url in links:
- index = int(index) % zmodulo
- if index >= max_index:
- download_url = url
-
- self.logDebug("DOWNLOAD LINK:", download_url)
-
- else:
- zindex, download_url = links[0]
- """
+
found = re.search(r'kNO = "(http://.*?)";', self.html)
if not found: self.parseError("Download URL")
download_url = found.group(1)
- self.logDebug("DOWNLOAD LINK:", download_url)
-
+ self.logDebug("DOWNLOAD LINK:", download_url)
+
self.download(download_url)
def checkCaptcha(self):
- for i in range(5):
- found = re.search(self.RECAPTCHA_PATTERN, self.html)
+ for i in xrange(5):
+ found = re.search(self.SOLVEMEDIA_PATTERN, self.html)
if found:
- captcha_action = re.search(self.PAGE1_ACTION_PATTERN, self.html).group(1)
captcha_key = found.group(1)
- recaptcha = ReCaptcha(self)
- captcha_challenge, captcha_response = recaptcha.challenge(captcha_key)
- self.html = self.load(captcha_action, post = {
- "recaptcha_challenge_field": captcha_challenge,
- "recaptcha_response_field": captcha_response
- }, decode = True)
+ solvemedia = SolveMedia(self)
+ captcha_challenge, captcha_response = solvemedia.challenge(captcha_key)
+ self.html = self.load(self.url, post={"adcopy_challenge": captcha_challenge,
+ "adcopy_response": captcha_response}, decode=True)
else:
break
else:
diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py
index a28ddca9d..e5be4eeb7 100644
--- a/module/plugins/hoster/MegaNz.py
+++ b/module/plugins/hoster/MegaNz.py
@@ -19,7 +19,7 @@ class MegaNz(Hoster):
__name__ = "MegaNz"
__type__ = "hoster"
__pattern__ = r"https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)"
- __version__ = "0.11"
+ __version__ = "0.12"
__description__ = """mega.co.nz hoster plugin"""
__author_name__ = ("RaNaN", )
__author_mail__ = ("ranan@pyload.org", )
@@ -34,7 +34,7 @@ class MegaNz(Hoster):
def getCipherKey(self, key):
""" Construct the cipher key from the given data """
a = array("I", key)
- key_array = array("I", [a[0] ^ a[4], a[1] ^a[5], a[2] ^ a[6], a[3] ^a[7]])
+ key_array = array("I", [a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]])
return key_array
def callApi(self, **kwargs):
@@ -69,7 +69,7 @@ class MegaNz(Hoster):
self.pyfile.setStatus("decrypting")
f = open(self.lastDownload, "rb")
- df = open(self.lastDownload.rstrip(self.FILE_SUFFIX), "wb")
+ df = open(self.lastDownload.rsplit(self.FILE_SUFFIX)[0], "wb")
# TODO: calculate CBC-MAC for checksum
diff --git a/module/plugins/hoster/MovReelCom.py b/module/plugins/hoster/MovReelCom.py
new file mode 100644
index 000000000..6f5f1d3f1
--- /dev/null
+++ b/module/plugins/hoster/MovReelCom.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.utils import html_unescape
+from module.network.RequestFactory import getURL
+
+class MovReelCom(SimpleHoster):
+ __name__ = "MovReelCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://movreel.com/.*"
+ __version__ = "1.00"
+ __description__ = """MovReel.com hoster plugin"""
+ __author_name__ = ("JorisV83")
+ __author_mail__ = ("jorisv83-pyload@yahoo.com")
+
+ FILE_INFO_PATTERN = r'You have requested <font color="red">http://movreel.com/.*/(?P<N>.+?)</font>.*\((?P<S>[\d.]+) (?P<U>..)\)</font>'
+ FILE_OFFLINE_PATTERN = r'<b>File Not Found</b>'
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = False
+
+ def handleFree(self):
+
+ # Define search patterns
+ op_pattern = '<input type="hidden" name="op" value="(.*)">'
+ id_pattern = '<input type="hidden" name="id" value="(.*)">'
+ fn_pattern = '<input type="hidden" name="fname" value="(.*)">'
+ re_pattern = '<input type="hidden" name="referer" value="(.*)">'
+ ul_pattern = '<input type="hidden" name="usr_login" value="(.*)">'
+ rand_pattern = '<input type="hidden" name="rand" value="(.*)">'
+ link_pattern = "var file_link = '(.*)';"
+ downlimit_pattern = '<br><p class="err">You have reached the download-limit: .*</p>'
+
+ # Get HTML source
+ self.logDebug("Getting first HTML source")
+ html = self.load(self.pyfile.url)
+ self.logDebug(" > Done")
+
+ op_val = re.search(op_pattern, html).group(1)
+ id_val = re.search(id_pattern, html).group(1)
+ fn_val = re.search(fn_pattern, html).group(1)
+ re_val = re.search(re_pattern, html).group(1)
+ ul_val = re.search(ul_pattern, html).group(1)
+
+ # Debug values
+ self.logDebug(" > Op " + op_val)
+ self.logDebug(" > Id " + id_val)
+ self.logDebug(" > Fname " + fn_val)
+ self.logDebug(" > Referer " + re_val)
+ self.logDebug(" > User Login " + ul_val)
+
+ # Create post data
+ post_data = {"op" : op_val, "usr_login" : ul_val, "id" : id_val, "fname" : fn_val, "referer" : re_val, "method_free" : "+Free+Download"}
+
+ # Post and get new HTML source
+ self.logDebug("Getting second HTML source")
+ html = self.load(self.pyfile.url, post = post_data, decode=True)
+ self.logDebug(" > Done")
+
+ # Check download limit
+ if re.search(downlimit_pattern, html) is not None:
+ self.retry(3, 7200, "Download limit reached, wait 2h")
+
+ # Retrieve data
+ if re.search(op_pattern, html) is not None:
+ op_val = re.search(op_pattern, html).group(1)
+ else:
+ self.retry(3, 10, "Second html: no op found!!")
+
+ if re.search(id_pattern, html) is not None:
+ id_val = re.search(id_pattern, html).group(1)
+ else:
+ self.retry(3, 10, "Second html: no id found!!")
+
+ if re.search(rand_pattern, html) is not None:
+ rand_val = re.search(rand_pattern, html).group(1)
+ else:
+ self.retry(3, 10, "Second html: no rand found!!")
+
+ re_val = self.pyfile.url
+
+ # Debug values
+ self.logDebug(" > Op " + op_val)
+ self.logDebug(" > Id " + id_val)
+ self.logDebug(" > Rand " + rand_val)
+ self.logDebug(" > Referer " + re_val)
+
+ # Create post data
+ post_data = {"op" : op_val, "id" : id_val, "rand" : rand_val, "referer" : re_val, "method_free" : "+Free+Download", "method_premium" : "", "down_direct" : "1"}
+
+ # Post and get new HTML source
+ self.logDebug("Getting third HTML source")
+ html = self.load(self.pyfile.url, post = post_data, decode=True)
+ self.logDebug(" > Done")
+
+ # Get link value
+ if re.search(link_pattern, html) is not None:
+ link_val = re.search(link_pattern, html).group(1)
+ self.logDebug(" > Link " + link_val)
+ self.download(link_val)
+ else:
+ self.logDebug("No link found!!")
+ self.retry(3, 10, "No link found!!")
+
+getInfo = create_getInfo(MovReelCom) \ No newline at end of file
diff --git a/module/plugins/hoster/MultiDebridCom.py b/module/plugins/hoster/MultiDebridCom.py
new file mode 100644
index 000000000..ca98e8a0e
--- /dev/null
+++ b/module/plugins/hoster/MultiDebridCom.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+
+############################################################################
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero 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 Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+############################################################################
+
+import re
+
+from module.plugins.Hoster import Hoster
+from module.common.json_layer import json_loads
+
+
+class MultiDebridCom(Hoster):
+ __name__ = "MultiDebridCom"
+ __version__ = "0.01"
+ __type__ = "hoster"
+ __pattern__ = r"http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/dl/"
+ __description__ = """Multi-debrid.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 Multi-debrid.com account or deactivate this plugin")
+ self.fail("No Multi-debrid.com account provided")
+
+ self.logDebug("Original URL: %s" % pyfile.url)
+ if re.match(self.__pattern__, pyfile.url):
+ new_url = pyfile.url
+ else:
+ page = self.req.load('http://multi-debrid.com/api.php',
+ get={'user': self.user, 'pass': self.account.getAccountData(self.user)['password'],
+ 'link': pyfile.url})
+ self.logDebug("JSON data: " + page)
+ page = json_loads(page)
+ if page['status'] != 'ok':
+ self.fail('Unable to unrestrict link')
+ new_url = page['link']
+
+ self.logDebug("Unrestricted URL: " + new_url)
+
+ self.download(new_url, disposition=True)
diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py
index 7b87bbe71..c7c3384e9 100644
--- a/module/plugins/hoster/OneFichierCom.py
+++ b/module/plugins/hoster/OneFichierCom.py
@@ -7,7 +7,7 @@ class OneFichierCom(SimpleHoster):
__name__ = "OneFichierCom"
__type__ = "hoster"
__pattern__ = r"(http://(\w+)\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))"
- __version__ = "0.46"
+ __version__ = "0.47"
__description__ = """1fichier.com download hoster"""
__author_name__ = ("fragonib", "the-razer", "zoidberg","imclem")
__author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz","imclem on github")
@@ -19,7 +19,7 @@ class OneFichierCom(SimpleHoster):
DOWNLOAD_LINK_PATTERN = r'<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;\s+<a href="(?P<url>http://.*?)"'
PASSWORD_PROTECTED_TOKEN = "protected by password"
- WAITING_PATTERN = "Warning ! Without premium status, you can download only one file at a time and you must wait at least (\d+) minutes between each downloads."
+ WAITING_PATTERN = "Warning ! Without premium status, you can download only one file at a time and you must wait up to (\d+) minutes between each downloads."
def process(self, pyfile):
found = re.search(self.__pattern__, pyfile.url)
file_id = found.group(2)
diff --git a/module/plugins/hoster/Premium4Me.py b/module/plugins/hoster/Premium4Me.py
index 2679916e9..5dd907b9f 100644
--- a/module/plugins/hoster/Premium4Me.py
+++ b/module/plugins/hoster/Premium4Me.py
@@ -2,20 +2,22 @@
# -*- coding: utf-8 -*-
from urllib import quote
-from module.plugins.Hoster import Hoster
-from module.utils import fs_encode
from os.path import exists
from os import remove
+from module.plugins.Hoster import Hoster
+from module.utils import fs_encode
+
+
class Premium4Me(Hoster):
__name__ = "Premium4Me"
- __version__ = "0.04"
+ __version__ = "0.05"
__type__ = "hoster"
__pattern__ = r"http://premium4.me/.*"
__description__ = """premium4.me hoster plugin"""
- __author_name__ = ("RaNaN", "zoidberg")
- __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
+ __author_name__ = ("RaNaN", "zoidberg", "stickell")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
def setup(self):
self.resumeDownload = True
@@ -29,33 +31,40 @@ class Premium4Me(Hoster):
self.logDebug("premium4.me: Old URL: %s" % pyfile.url)
tra = self.getTraffic()
-
+
#raise timeout to 2min
self.req.setOption("timeout", 120)
-
- self.download("http://premium4.me/api/getfile.php?authcode=%s&link=%s" % (self.account.authcode, quote(pyfile.url, "")), disposition=True)
-
- err = ''
+
+ self.download(
+ "http://premium4.me/api/getfile.php?authcode=%s&link=%s" % (self.account.authcode, quote(pyfile.url, "")),
+ disposition=True)
+
+ check = self.checkDownload({"nopremium": "No premium account available"})
+
+ if check == "nopremium":
+ self.retry(3, 60, 'No premium account available')
+
+ err = ''
if self.req.http.code == '420':
# Custom error code send - fail
lastDownload = fs_encode(self.lastDownload)
-
- if exists(lastDownload):
+
+ if exists(lastDownload):
f = open(lastDownload, "rb")
err = f.read(256).strip()
f.close()
remove(lastDownload)
else:
err = 'File does not exist'
-
+
trb = self.getTraffic()
- self.logInfo("Filesize: %d, Traffic used %d, traffic left %d" % (pyfile.size, tra-trb, trb))
-
+ self.logInfo("Filesize: %d, Traffic used %d, traffic left %d" % (pyfile.size, tra - trb, trb))
+
if err: self.fail(err)
-
+
def getTraffic(self):
try:
- traffic = int(self.load ("http://premium4.me/api/traffic.php?authcode=%s" % self.account.authcode))
+ traffic = int(self.load("http://premium4.me/api/traffic.php?authcode=%s" % self.account.authcode))
except:
- traffic = 0
+ traffic = 0
return traffic
diff --git a/module/plugins/hoster/PutlockerCom.py b/module/plugins/hoster/PutlockerCom.py
index 9eff0dc2b..b2016472d 100644
--- a/module/plugins/hoster/PutlockerCom.py
+++ b/module/plugins/hoster/PutlockerCom.py
@@ -28,7 +28,7 @@ class PutlockerCom(SimpleHoster):
__name__ = "PutlockerCom"
__type__ = "hoster"
__pattern__ = r'http://(www\.)?putlocker\.com/(file|embed)/[A-Z0-9]+'
- __version__ = "0.24"
+ __version__ = "0.25"
__description__ = """Putlocker.Com"""
__author_name__ = ("jeix", "stickell")
__author_mail__ = ("l.stickell@yahoo.it")
@@ -37,6 +37,8 @@ class PutlockerCom(SimpleHoster):
FILE_INFO_PATTERN = r'site-content">\s*<h1>(?P<N>.+)<strong>\( (?P<S>[^)]+) \)</strong></h1>'
def handleFree(self):
+ self.pyfile.url = re.sub(r'http://putlocker\.com', r'http://www.putlocker.com', self.pyfile.url)
+
self.html = self.load(self.pyfile.url, decode=True)
link = self._getLink()
diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py
index 1cc3ff8ae..d2ca77e0f 100644
--- a/module/plugins/hoster/RapidgatorNet.py
+++ b/module/plugins/hoster/RapidgatorNet.py
@@ -29,9 +29,9 @@ class RapidgatorNet(SimpleHoster):
__name__ = "RapidgatorNet"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\w+)"
- __version__ = "0.16"
+ __version__ = "0.17"
__description__ = """rapidgator.net"""
- __author_name__ = ("zoidberg","chrox")
+ __author_name__ = ("zoidberg", "chrox", "stickell")
API_URL = 'http://rapidgator.net/api/file'
@@ -39,7 +39,7 @@ class RapidgatorNet(SimpleHoster):
FILE_OFFLINE_PATTERN = r'<title>File not found</title>'
JSVARS_PATTERN = r"\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*'?(.*?)'?;"
- DOWNLOAD_LINK_PATTERN = r"location.href = '([^']+)';\s*}\s*return false;"
+ DOWNLOAD_LINK_PATTERN = r"return '(http[^']+)';\s*}\s*}\s*}\);"
RECAPTCHA_KEY_PATTERN = r'"http://api.recaptcha.net/challenge?k=(.*?)"'
ADSCAPTCHA_SRC_PATTERN = r'(http://api.adscaptcha.com/Get.aspx[^"\']*)'
SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"'
diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py
index c2ff54e0c..7bfe4e8fe 100644
--- a/module/plugins/hoster/RyushareCom.py
+++ b/module/plugins/hoster/RyushareCom.py
@@ -7,7 +7,7 @@ class RyushareCom(XFileSharingPro):
__name__ = "RyushareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{11,}"
- __version__ = "0.10"
+ __version__ = "0.11"
__description__ = """ryushare.com hoster plugin"""
__author_name__ = ("zoidberg", "stickell")
__author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
@@ -18,7 +18,9 @@ class RyushareCom(XFileSharingPro):
DIRECT_LINK_PATTERN = r'<a href="([^"]+)">Click here to download</a>'
def setup(self):
- self.resumeDownload = self.multiDL = self.premium
+ self.resumeDownload = self.multiDL = True
+ if not self.premium:
+ self.limitDL = 2
# Up to 3 chunks allowed in free downloads. Unknown for premium
self.chunkLimit = 3
diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py
index 739f997fe..5aa08891e 100644
--- a/module/plugins/hoster/UploadedTo.py
+++ b/module/plugins/hoster/UploadedTo.py
@@ -1,6 +1,11 @@
# -*- coding: utf-8 -*-
+# Test links (random.bin):
+# http://ul.to/044yug9o
+# http://ul.to/gzfhd0xs
+
import re
+from time import sleep
from module.utils import html_unescape, parseFileSize, chunks
@@ -13,7 +18,7 @@ key = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=".decode('base64')
def getID(url):
""" returns id from file url"""
- m = re.match(r"http://[\w\.-]*?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=)(?P<ID>\w+)", url)
+ m = re.match(UploadedTo.__pattern__, url)
return m.group('ID')
@@ -27,7 +32,12 @@ def getAPIData(urls):
post["id_%s" % i] = id
idMap[id] = url
- api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1')
+ for i in xrange(5):
+ api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1')
+ if api != "can't find request":
+ break
+ else:
+ sleep(3)
result = {}
@@ -76,8 +86,8 @@ def getInfo(urls):
class UploadedTo(Hoster):
__name__ = "UploadedTo"
__type__ = "hoster"
- __pattern__ = r"http://[\w\.-]*?(uploaded\.(to|net)(/file/|/?\?id=|.*?&id=)|ul\.to/)\w+"
- __version__ = "0.65"
+ __pattern__ = r"https?://[\w\.-]*?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)"
+ __version__ = "0.70"
__description__ = """Uploaded.net Download Hoster"""
__author_name__ = ("spoob", "mkaay", "zoidberg", "netpok", "stickell")
__author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz", "netpok@gmail.com", "l.stickell@yahoo.it")
@@ -204,7 +214,7 @@ class UploadedTo(Hoster):
elif "limit-parallel" in result:
self.fail("Cannot download in parallel")
elif self.DL_LIMIT_PATTERN in result: # limit-dl
- self.setWait(60 * 60, True)
+ self.setWait(3 * 60 * 60, True)
self.wait()
self.retry()
elif 'err:"captcha"' in result:
@@ -220,9 +230,9 @@ class UploadedTo(Hoster):
if not downloadURL:
self.fail("No Download url retrieved/all captcha attempts failed")
- self.download(downloadURL)
+ self.download(downloadURL, disposition=True)
check = self.checkDownload({"limit-dl": self.DL_LIMIT_PATTERN})
if check == "limit-dl":
- self.setWait(60 * 60, True)
+ self.setWait(3 * 60 * 60, True)
self.wait()
self.retry()
diff --git a/module/plugins/hoster/UploadheroCom.py b/module/plugins/hoster/UploadheroCom.py
index eb7b5fb23..502f849af 100644
--- a/module/plugins/hoster/UploadheroCom.py
+++ b/module/plugins/hoster/UploadheroCom.py
@@ -22,8 +22,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class UploadheroCom(SimpleHoster):
__name__ = "UploadheroCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?uploadhero\.com/dl/\w+"
- __version__ = "0.12"
+ __pattern__ = r"http://(?:www\.)?uploadhero\.com?/dl/\w+"
+ __version__ = "0.13"
__description__ = """UploadHero.com plugin"""
__author_name__ = ("mcmyst", "zoidberg")
__author_mail__ = ("mcmyst@hotmail.fr", "zoidberg@mujmail.cz")
@@ -81,4 +81,4 @@ class UploadheroCom(SimpleHoster):
self.wait()
self.retry()
-getInfo = create_getInfo(UploadheroCom) \ No newline at end of file
+getInfo = create_getInfo(UploadheroCom)
diff --git a/module/plugins/hoster/XVideosCom.py b/module/plugins/hoster/XVideosCom.py
new file mode 100644
index 000000000..b7f3f7b58
--- /dev/null
+++ b/module/plugins/hoster/XVideosCom.py
@@ -0,0 +1,19 @@
+
+import re
+import urllib
+
+from module.plugins.Hoster import Hoster
+
+class XVideosCom(Hoster):
+ __name__ = "XVideos.com"
+ __version__ = "0.1"
+ __pattern__ = r"http://www\.xvideos\.com/video([0-9]+)/.*"
+ __config__ = []
+
+ def process(self, pyfile):
+ site = self.load(pyfile.url)
+ pyfile.name = "%s (%s).flv" %(
+ re.search(r"<h2>([^<]+)<span", site).group(1),
+ re.search(self.__pattern__, pyfile.url).group(1),
+ )
+ self.download(urllib.unquote(re.search(r"flv_url=([^&]+)&", site).group(1)))
diff --git a/module/plugins/hoster/XvidstageCom.py b/module/plugins/hoster/XvidstageCom.py
index 14079df43..4962c05af 100644
--- a/module/plugins/hoster/XvidstageCom.py
+++ b/module/plugins/hoster/XvidstageCom.py
@@ -1,105 +1,114 @@
# -*- 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 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.
+ 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/>.
+ 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: 4Christopher
+ @author: 4Christopher
"""
-from module.plugins.Hoster import Hoster
-from module.network.RequestFactory import getURL
import re
import HTMLParser
+from module.plugins.Hoster import Hoster
+from module.network.RequestFactory import getURL
+
+
def setup(self):
- self.wantReconnect = False
- self.resumeDownload = True
- self.multiDL = True
+ self.wantReconnect = False
+ self.resumeDownload = True
+ self.multiDL = True
+
def getInfo(urls):
- result = []
-
- for url in urls:
- result.append(parseFileInfo(url, getInfoMode = True))
- yield result
-
-def parseFileInfo(url, getInfoMode = False):
- html = getURL(url)
- info = {"name" : url, "size" : 0, "status" : 3}
- try:
- info['name'] = re.search(r'(?:Filename|Dateiname):</b></td><td nowrap[^>]*?>(.*?)<', html).group(1)
- info['size'] = re.search(r'(?:Size|Größe):</b></td><td>.*? <small>\((\d+?) bytes\)', html).group(1)
- except: ## The file is offline
- info['status'] = 1
- else:
- info['status'] = 2
-
- if getInfoMode:
- return info['name'], info['size'], info['status'], url
- else:
- return info['name'], info['size'], info['status'], html
+ result = []
+
+ for url in urls:
+ result.append(parseFileInfo(url, getInfoMode=True))
+ yield result
+
+
+def parseFileInfo(url, getInfoMode=False):
+ html = getURL(url)
+ info = {"name": url, "size": 0, "status": 3}
+ try:
+ info['name'] = re.search(r'(?:Filename|Dateiname):</b></td><td nowrap[^>]*?>(.*?)<', html).group(1)
+ info['size'] = re.search(r'(?:Size|Größe):</b></td><td>.*? <small>\((\d+?) bytes\)', html).group(1)
+ except: ## The file is offline
+ info['status'] = 1
+ else:
+ info['status'] = 2
+
+ if getInfoMode:
+ return info['name'], info['size'], info['status'], url
+ else:
+ return info['name'], info['size'], info['status'], html
+
class XvidstageCom(Hoster):
- __name__ = 'XvidstageCom'
- __version__ = '0.3'
- __pattern__ = r'http://(?:www.)?xvidstage.com/(?P<id>[0-9A-Za-z]+)'
- __type__ = 'hoster'
- __description__ = """A Plugin that allows you to download files from http://xvidstage.com"""
- __author_name__ = ('4Christopher')
- __author_mail__ = ('4Christopher@gmx.de')
-
-
- def process(self, pyfile):
- pyfile.name, pyfile.size, pyfile.status, self.html = parseFileInfo(pyfile.url)
- self.logDebug('Name: %s' % pyfile.name)
- if pyfile.status == 1: ## offline
- self.fail()
- self.id = re.search(self.__pattern__, pyfile.url).group('id')
-
- wait_sec = int(re.search(r'countdown_str">.+?>(\d+?)<', self.html).group(1))
- self.setWait(wait_sec, reconnect=False)
- self.logDebug('Waiting %d seconds before submitting the captcha' % wait_sec)
- self.wait()
-
- rand = re.search(r'<input type="hidden" name="rand" value="(.*?)">', self.html).group(1)
- self.logDebug('rand: %s, id: %s' % (rand, self.id))
- self.html = self.req.load(pyfile.url, post={'op': 'download2', 'id' : self.id, 'rand' : rand, 'code': self.get_captcha()})
- file_url = re.search(r'<a href="(?P<url>.*?)">(?P=url)</a>', self.html).group('url')
- try:
- hours_file_available = int(re.search(r'This direct link will be available for your IP next (?P<hours>\d+?) hours', self.html).group('hours'))
- self.logDebug('You have %d hours to download this file with your current IP address.' % hours_file_available)
- except:
- self.logDebug('Failed')
- self.logDebug('Download file: %s' % file_url)
- self.download(file_url)
- check = self.checkDownload({'empty': re.compile(r'^$')})
-
- if check == 'empty':
- self.logInfo('Downloaded File was empty')
- # self.retry()
-
- def get_captcha(self):
- ## <span style='position:absolute;padding-left:7px;padding-top:6px;'>&#49; …
- cap_chars = {}
- for pad_left, char in re.findall(r"position:absolute;padding-left:(\d+?)px;.*?;'>(.*?)<", self.html):
- cap_chars[int(pad_left)] = char
-
- h = HTMLParser.HTMLParser()
- ## Sorting after padding-left
- captcha = ''
- for pad_left in sorted(cap_chars):
- captcha += h.unescape(cap_chars[pad_left])
-
- self.logDebug('The captcha is: %s' % captcha)
- return captcha
+ __name__ = 'XvidstageCom'
+ __version__ = '0.4'
+ __pattern__ = r'http://(?:www.)?xvidstage.com/(?P<id>[0-9A-Za-z]+)'
+ __type__ = 'hoster'
+ __description__ = """A Plugin that allows you to download files from http://xvidstage.com"""
+ __author_name__ = ('4Christopher')
+ __author_mail__ = ('4Christopher@gmx.de')
+
+
+ def process(self, pyfile):
+ pyfile.name, pyfile.size, pyfile.status, self.html = parseFileInfo(pyfile.url)
+ self.logDebug('Name: %s' % pyfile.name)
+ if pyfile.status == 1: ## offline
+ self.offline()
+ self.id = re.search(self.__pattern__, pyfile.url).group('id')
+
+ wait_sec = int(re.search(r'countdown_str">.+?>(\d+?)<', self.html).group(1))
+ self.setWait(wait_sec, reconnect=False)
+ self.logDebug('Waiting %d seconds before submitting the captcha' % wait_sec)
+ self.wait()
+
+ rand = re.search(r'<input type="hidden" name="rand" value="(.*?)">', self.html).group(1)
+ self.logDebug('rand: %s, id: %s' % (rand, self.id))
+ self.html = self.req.load(pyfile.url,
+ post={'op': 'download2', 'id': self.id, 'rand': rand, 'code': self.get_captcha()})
+ file_url = re.search(r'<a href="(?P<url>.*?)">(?P=url)</a>', self.html).group('url')
+ try:
+ hours_file_available = int(
+ re.search(r'This direct link will be available for your IP next (?P<hours>\d+?) hours',
+ self.html).group('hours'))
+ self.logDebug(
+ 'You have %d hours to download this file with your current IP address.' % hours_file_available)
+ except:
+ self.logDebug('Failed')
+ self.logDebug('Download file: %s' % file_url)
+ self.download(file_url)
+ check = self.checkDownload({'empty': re.compile(r'^$')})
+
+ if check == 'empty':
+ self.logInfo('Downloaded File was empty')
+ # self.retry()
+
+ def get_captcha(self):
+ ## <span style='position:absolute;padding-left:7px;padding-top:6px;'>&#49; …
+ cap_chars = {}
+ for pad_left, char in re.findall(r"position:absolute;padding-left:(\d+?)px;.*?;'>(.*?)<", self.html):
+ cap_chars[int(pad_left)] = char
+
+ h = HTMLParser.HTMLParser()
+ ## Sorting after padding-left
+ captcha = ''
+ for pad_left in sorted(cap_chars):
+ captcha += h.unescape(cap_chars[pad_left])
+
+ self.logDebug('The captcha is: %s' % captcha)
+ return captcha
diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py
index 2fb1e5264..70db597cf 100644
--- a/module/plugins/hoster/YoutubeCom.py
+++ b/module/plugins/hoster/YoutubeCom.py
@@ -33,8 +33,8 @@ def which(program):
class YoutubeCom(Hoster):
__name__ = "YoutubeCom"
__type__ = "hoster"
- __pattern__ = r"(http|https)://(www\.)?(de\.)?\youtube\.com/watch\?v=.*"
- __version__ = "0.30"
+ __pattern__ = r"https?://(?:[^/]*?)youtube\.com/watch.*?[?&]v=.*"
+ __version__ = "0.32"
__config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting", "hd"),
("fmt", "int", "FMT/ITAG Number (5-102, 0 for auto)", 0),
(".mp4", "bool", "Allow .mp4", True),
@@ -47,9 +47,9 @@ class YoutubeCom(Hoster):
__author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz")
# name, width, height, quality ranking, 3D
- formats = {5: (".flv", 400, 240, 1, False),
+ formats = {5: (".flv", 400, 240, 1, False),
6: (".flv", 640, 400, 4, False),
- 17: (".3gp", 176, 144, 0, False),
+ 17: (".3gp", 176, 144, 0, False),
18: (".mp4", 480, 360, 2, False),
22: (".mp4", 1280, 720, 8, False),
43: (".webm", 640, 360, 3, False),
@@ -59,7 +59,7 @@ class YoutubeCom(Hoster):
37: (".mp4", 1920, 1080, 9, False),
38: (".mp4", 4096, 3072, 10, False),
44: (".webm", 854, 480, 5, False),
- 45: (".webm", 1280, 720, 7, False),
+ 45: (".webm", 1280, 720, 7, False),
46: (".webm", 1920, 1080, 9, False),
82: (".mp4", 640, 360, 3, True),
83: (".mp4", 400, 240, 1, True),
@@ -76,54 +76,54 @@ class YoutubeCom(Hoster):
def process(self, pyfile):
html = self.load(pyfile.url, decode=True)
- if "watch-player-unavailable" in html:
+ if '<h1 id="unavailable-message" class="message">' in html:
self.offline()
if "We have been receiving a large volume of requests from your network." in html:
self.tempOffline()
-
+
#get config
use3d = self.getConf("3d")
if use3d:
- quality = {"sd":82,"hd":84,"fullhd":85,"240p":83,"360p":82,"480p":82,"720p":84,"1080p":85,"3072p":85}
+ quality = {"sd":82,"hd":84,"fullhd":85,"240p":83,"360p":82,"480p":82,"720p":84,"1080p":85,"3072p":85}
else:
- quality = {"sd":18,"hd":22,"fullhd":37,"240p":5,"360p":18,"480p":35,"720p":22,"1080p":37,"3072p":38}
+ quality = {"sd":18,"hd":22,"fullhd":37,"240p":5,"360p":18,"480p":35,"720p":22,"1080p":37,"3072p":38}
desired_fmt = self.getConf("fmt")
if desired_fmt and desired_fmt not in self.formats:
- self.logWarning("FMT %d unknown - using default." % desired_fmt)
- desired_fmt = 0
+ self.logWarning("FMT %d unknown - using default." % desired_fmt)
+ desired_fmt = 0
if not desired_fmt:
- desired_fmt = quality.get(self.getConf("quality"), 18)
-
+ desired_fmt = quality.get(self.getConf("quality"), 18)
+
#parse available streams
streams = re.search(r'"url_encoded_fmt_stream_map": "(.*?)",', html).group(1)
streams = [x.split('\u0026') for x in streams.split(',')]
streams = [dict((y.split('=',1)) for y in x) for x in streams]
streams = [(int(x['itag']), "%s&signature=%s" % (unquote(x['url']), x['sig'])) for x in streams]
- #self.logDebug("Found links: %s" % streams)
- self.logDebug("AVAILABLE STREAMS: %s" % [x[0] for x in streams])
-
+ #self.logDebug("Found links: %s" % streams)
+ self.logDebug("AVAILABLE STREAMS: %s" % [x[0] for x in streams])
+
#build dictionary of supported itags (3D/2D)
- allowed = lambda x: self.getConfig(self.formats[x][0])
+ allowed = lambda x: self.getConfig(self.formats[x][0])
streams = [x for x in streams if x[0] in self.formats and allowed(x[0])]
if not streams:
self.fail("No available stream meets your preferences")
- fmt_dict = dict([x for x in streams if self.formats[x[0]][4] == use3d] or streams)
-
- self.logDebug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" %
- (desired_fmt,
+ fmt_dict = dict([x for x in streams if self.formats[x[0]][4] == use3d] or streams)
+
+ self.logDebug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" %
+ (desired_fmt,
"%s %dx%d Q:%d 3D:%s" % self.formats[desired_fmt],
- "" if desired_fmt in fmt_dict else "NOT ",
+ "" if desired_fmt in fmt_dict else "NOT ",
"" if allowed(desired_fmt) else "NOT ")
- )
+ )
- #return fmt nearest to quality index
+ #return fmt nearest to quality index
if desired_fmt in fmt_dict and allowed(desired_fmt):
fmt = desired_fmt
else:
sel = lambda x: self.formats[x][3] #select quality index
comp = lambda x, y: abs(sel(x) - sel(y))
-
+
self.logDebug("Choosing nearest fmt: %s" % [(x, allowed(x), comp(x, desired_fmt)) for x in fmt_dict.keys()])
fmt = reduce(lambda x, y: x if comp(x, desired_fmt) <= comp(y, desired_fmt) and
sel(x) > sel(y) else y, fmt_dict.keys())
@@ -132,7 +132,7 @@ class YoutubeCom(Hoster):
url = fmt_dict[fmt]
self.logDebug("URL: %s" % url)
- #set file name
+ #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("/", "")
diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py
index b2cc03985..d935bf1da 100644
--- a/module/plugins/internal/SimpleCrypter.py
+++ b/module/plugins/internal/SimpleCrypter.py
@@ -20,6 +20,7 @@
import re
from module.plugins.Crypter import Crypter
+from module.utils import html_unescape
class SimpleCrypter(Crypter):
@@ -57,7 +58,7 @@ class SimpleCrypter(Crypter):
if hasattr(self, 'TITLE_PATTERN'):
m = re.search(self.TITLE_PATTERN, self.html)
if m:
- name = folder = m.group('title')
+ name = folder = html_unescape(m.group('title').strip())
self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
return name, folder