summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-11-30 22:24:20 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-11-30 22:24:20 +0100
commit851011df889369cac5e4c91928be7e1a498f9ab8 (patch)
tree7138701c93ef2514c47419342e3428d270091d53 /module
parentfixed import in ExternalScripts (diff)
parentTurbobitNet: fixed #421 (diff)
downloadpyload-851011df889369cac5e4c91928be7e1a498f9ab8.tar.xz
Merge branch 'stable' of github.com:pyload/pyload into stable
Diffstat (limited to 'module')
-rw-r--r--module/plugins/accounts/FilefactoryCom.py57
-rw-r--r--module/plugins/accounts/FshareVn.py10
-rw-r--r--module/plugins/crypter/EasybytezComFolder.py6
-rw-r--r--module/plugins/crypter/YoutubeBatch.py109
-rw-r--r--module/plugins/hoster/BayfilesCom.py18
-rw-r--r--module/plugins/hoster/CrockoCom.py8
-rw-r--r--module/plugins/hoster/NowDownloadEu.py4
-rw-r--r--module/plugins/hoster/TurbobitNet.py3
-rw-r--r--module/plugins/internal/AbstractExtractor.py9
-rw-r--r--module/plugins/internal/CaptchaService.py37
-rw-r--r--module/plugins/internal/DeadCrypter.py2
-rw-r--r--module/plugins/internal/DeadHoster.py5
-rw-r--r--module/plugins/internal/MultiHoster.py97
-rw-r--r--module/plugins/internal/SimpleCrypter.py7
-rw-r--r--module/plugins/internal/SimpleHoster.py3
-rw-r--r--module/plugins/internal/UnRar.py38
-rw-r--r--module/plugins/internal/UnZip.py5
-rw-r--r--module/plugins/internal/XFSPAccount.py41
18 files changed, 275 insertions, 184 deletions
diff --git a/module/plugins/accounts/FilefactoryCom.py b/module/plugins/accounts/FilefactoryCom.py
index 679409058..04ba0ea86 100644
--- a/module/plugins/accounts/FilefactoryCom.py
+++ b/module/plugins/accounts/FilefactoryCom.py
@@ -1,45 +1,46 @@
# -*- coding: utf-8 -*-
-"""
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- @author: zoidberg
-"""
+############################################################################
+# 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 time import mktime, strptime
+from pycurl import REFERER
+
from module.plugins.Account import Account
class FilefactoryCom(Account):
__name__ = "FilefactoryCom"
- __version__ = "0.13"
+ __version__ = "0.14"
__type__ = "account"
__description__ = """filefactory.com account plugin"""
__author_name__ = ("zoidberg", "stickell")
__author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
- ACCOUNT_INFO_PATTERN = r'<time datetime="([\d-]+)">'
+ VALID_UNTIL_PATTERN = r'Premium valid until: <strong>(?P<d>\d{1,2})\w{1,2} (?P<m>\w{3}), (?P<y>\d{4})</strong>'
def loadAccountInfo(self, user, req):
- html = req.load("http://www.filefactory.com/member/")
+ html = req.load("http://www.filefactory.com/account/")
- found = re.search(self.ACCOUNT_INFO_PATTERN, html)
- if found:
+ m = re.search(self.VALID_UNTIL_PATTERN, html)
+ if m:
premium = True
- validuntil = mktime(strptime(found.group(1), "%Y-%m-%d"))
+ validuntil = re.sub(self.VALID_UNTIL_PATTERN, '\g<d> \g<m> \g<y>', m.group(0))
+ validuntil = mktime(strptime(validuntil, "%d %b %Y"))
else:
premium = False
validuntil = -1
@@ -47,10 +48,12 @@ class FilefactoryCom(Account):
return {"premium": premium, "trafficleft": -1, "validuntil": validuntil}
def login(self, user, data, req):
- html = req.load("http://www.filefactory.com/member/login.php", post={
- "email": user,
- "password": data["password"],
- "redirect": "/"})
+ req.http.c.setopt(REFERER, "http://www.filefactory.com/member/login.php")
+
+ html = req.load("http://www.filefactory.com/member/signin.php", post={
+ "loginEmail": user,
+ "loginPassword": data["password"],
+ "Submit": "Sign In"})
- if '/member/login.php?err=1' in req.http.header:
+ if req.lastEffectiveURL != "http://www.filefactory.com/account/":
self.wrongPassword()
diff --git a/module/plugins/accounts/FshareVn.py b/module/plugins/accounts/FshareVn.py
index 75191e74a..11abfa463 100644
--- a/module/plugins/accounts/FshareVn.py
+++ b/module/plugins/accounts/FshareVn.py
@@ -26,13 +26,13 @@ from module.plugins.Account import Account
class FshareVn(Account):
__name__ = "FshareVn"
- __version__ = "0.04"
+ __version__ = "0.05"
__type__ = "account"
__description__ = """fshare.vn account plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
+ __author_name__ = ("zoidberg", "stickell")
+ __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it")
- VALID_UNTIL_PATTERN = ur'<dt>Thời hạn dùng:</dt>\s*<dd>([^<]+)</dd>'
+ VALID_UNTIL_PATTERN = ur'<dt>Lần đăng nhập trước:</dt>\s*<dd>([^<]+)</dd>'
TRAFFIC_LEFT_PATTERN = ur'<dt>Tổng Dung Lượng Tài Khoản</dt>\s*<dd[^>]*>([0-9.]+) ([kKMG])B</dd>'
DIRECT_DOWNLOAD_PATTERN = ur'<input type="checkbox"\s*([^=>]*)[^>]*/>Kích hoạt download trực tiếp</dt>'
@@ -41,7 +41,7 @@ class FshareVn(Account):
found = re.search(self.VALID_UNTIL_PATTERN, html)
if found:
premium = True
- validuntil = mktime(strptime(found.group(1), '%I:%M:%S %p %d-%m-%Y'))
+ validuntil = mktime(strptime(found.group(1), '%d-%m-%Y'))
found = re.search(self.TRAFFIC_LEFT_PATTERN, html)
trafficleft = float(found.group(1)) * 1024 ** {
'k': 0, 'K': 0, 'M': 1, 'G': 2}[found.group(2)] if found else 0
diff --git a/module/plugins/crypter/EasybytezComFolder.py b/module/plugins/crypter/EasybytezComFolder.py
index 56be72669..b9cf240a0 100644
--- a/module/plugins/crypter/EasybytezComFolder.py
+++ b/module/plugins/crypter/EasybytezComFolder.py
@@ -21,12 +21,14 @@ 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.03"
+ __pattern__ = r"http://(?:www\.)?easybytez\.com/users/(?P<ID>\d+/\d+)"
+ __version__ = "0.04"
__description__ = """Easybytez Crypter Plugin"""
__author_name__ = ("stickell")
__author_mail__ = ("l.stickell@yahoo.it")
+ FILE_URL_REPLACEMENTS = [(__pattern__, r"http://www.easybytez.com/users/\g<ID>")]
+
LINK_PATTERN = r'<div class="link"><a href="(http://www\.easybytez\.com/\w+)" target="_blank">.+</a></div>'
TITLE_PATTERN = r'<Title>Files of \d+: (?P<title>.+) folder</Title>'
PAGES_PATTERN = r"<a href='[^']+'>(?P<pages>\d+)</a><a href='[^']+'>Next &#187;</a><br><small>\(\d+ total\)</small></div>"
diff --git a/module/plugins/crypter/YoutubeBatch.py b/module/plugins/crypter/YoutubeBatch.py
index b6178448d..ee84f0528 100644
--- a/module/plugins/crypter/YoutubeBatch.py
+++ b/module/plugins/crypter/YoutubeBatch.py
@@ -1,10 +1,28 @@
#!/usr/bin/env python
# -*- 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
+"""
+
import re
import json
from module.plugins.Crypter import Crypter
+from os.path import join
API_KEY = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0"
@@ -12,33 +30,86 @@ API_KEY = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0"
class YoutubeBatch(Crypter):
__name__ = "YoutubeBatch"
__type__ = "container"
- __pattern__ = r"https?://(?:[^/]*?)youtube\.com/(?:(?:view_play_list|playlist|.*?feature=PlayList).*?[?&](?:list|p)=)([a-zA-Z0-9-_]+)"
- __version__ = "0.93"
+ __pattern__ = r"https?://(?:[^/]*?)youtube\.com/(?:(view_play_list|playlist|.*?feature=PlayList|user)(?:.*?[?&](?:list|p)=|/))([a-zA-Z0-9-_]+)"
+ __version__ = "0.94"
__description__ = """Youtube.com Channel Download Plugin"""
- __author_name__ = ("RaNaN", "Spoob", "zoidberg", "roland")
- __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "zoidberg@mujmail.cz", "roland@enkore.de")
+ __author_name__ = ("RaNaN", "Spoob", "zoidberg", "roland", "Walter Purcaro")
+ __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "zoidberg@mujmail.cz", "roland@enkore.de", "vuolter@gmail.com")
- 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)
+ def json_response(self, api, req):
+ req.update({"key": API_KEY})
+ url = "https://www.googleapis.com/youtube/v3/" + api
+ page = self.load(url, get=req)
+ return json.loads(page)
+
+ def get_playlist_baseinfos(self, playlist_id):
+ res = self.json_response("playlists", {"part": "snippet", "id": playlist_id})
+
+ snippet = res["items"][0]["snippet"]
+ playlist_name = snippet["title"]
+ channel_title = snippet["channelTitle"]
+ return playlist_name, channel_title
+
+ def get_channel_id(self, user_name):
+ res = self.json_response("channels", {"part": "id", "forUsername": user_name})
+ return res["items"][0]["id"]
+
+ def get_playlists(self, user_name, token=None):
+ channel_id = self.get_channel_id(user_name)
+ req = {"part": "id", "maxResults": "50", "channelId": channel_id}
if token:
- url += "&pageToken=" + token
+ req.update({"pageToken": token})
+ res = self.json_response("playlists", req)
- response = json.loads(self.load(url))
+ for item in res["items"]:
+ yield item["id"]
- 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 res:
+ for item in self.get_playlists(user_name, res["nextPageToken"]):
+ yield item
- if "nextPageToken" in response:
- for item in self.get_videos(playlist_id, response["nextPageToken"]):
+ def get_videos(self, playlist_id, token=None):
+ req = {"part": "snippet", "maxResults": "50", "playlistId": playlist_id}
+ if token:
+ req.update({"pageToken": token})
+ res = self.json_response("playlistItems", req)
+
+ for item in res["items"]:
+ yield "http://youtube.com/watch?v=" + item["snippet"]["resourceId"]["videoId"]
+
+ if "nextPageToken" in res:
+ for item in self.get_videos(playlist_id, res["nextPageToken"]):
yield item
def decrypt(self, pyfile):
- match_id = re.match(self.__pattern__, self.pyfile.url)
- new_links = []
- playlist_id = match_id.group(1)
+ match_obj = re.match(self.__pattern__, pyfile.url)
+ match_type, match_result = match_obj.group(1), match_obj.group(2)
+ playlist_ids = []
+
+ #: is a channel username or just a playlist id?
+ if match_type == "user":
+ ids = self.get_playlists(match_result)
+ playlist_ids.extend(ids)
+ else:
+ playlist_ids.append(match_result)
+
+ self.logDebug("Playlist IDs = %s" % playlist_ids)
+
+ if not playlist_ids:
+ self.fail("Wrong url")
+
+ for id in playlist_ids:
+ self.logDebug("Processing playlist id: %s" % id)
+
+ playlist_name, channel_title = self.get_playlist_baseinfos(id)
+ video_links = [x for x in self.get_videos(id)]
+
+ self.logInfo("%s videos found on playlist \"%s\" (channel \"%s\")" % (len(video_links), playlist_name, channel_title))
+
+ if not video_links:
+ continue
- new_links.extend(self.get_videos(playlist_id))
+ self.logDebug("Video links = %s" % video_links)
- self.packages.append((self.pyfile.package().name, new_links, self.pyfile.package().name))
+ folder = join(self.config['general']['download_folder'], channel_title, playlist_name)
+ self.packages.append((playlist_name, video_links, folder)) #Note: folder is NOT used actually!
diff --git a/module/plugins/hoster/BayfilesCom.py b/module/plugins/hoster/BayfilesCom.py
index a696bac26..a7a2c75d4 100644
--- a/module/plugins/hoster/BayfilesCom.py
+++ b/module/plugins/hoster/BayfilesCom.py
@@ -26,11 +26,11 @@ from module.common.json_layer import json_loads
class BayfilesCom(SimpleHoster):
__name__ = "BayfilesCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?bayfiles\.(?:com|net)/file/\w+/\w+/.*"
- __version__ = "0.05"
+ __pattern__ = r"https?://(?:www\.)?bayfiles\.(com|net)/file/(?P<ID>[a-zA-Z0-9]+/[a-zA-Z0-9]+/[^/]+)"
+ __version__ = "0.06"
__description__ = """Bayfiles.com plugin - free only"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
+ __author_name__ = ("zoidberg", "Walter Purcaro")
+ __author_mail__ = ("zoidberg@mujmail.cz", "vuolter@gmail.com")
FILE_INFO_PATTERN = r'<p title="(?P<N>[^"]+)">[^<]*<strong>(?P<S>[0-9., ]+)(?P<U>[kKMG])i?B</strong></p>'
FILE_OFFLINE_PATTERN = r'(<p>The requested file could not be found.</p>|<title>404 Not Found</title>)'
@@ -53,7 +53,7 @@ class BayfilesCom(SimpleHoster):
self.parseError('VARS')
vfid, delay = found.groups()
- response = json_loads(self.load('http://bayfiles.com/ajax_download', get={
+ response = json_loads(self.load('https://bayfiles.com/ajax_download', get={
"_": time() * 1000,
"action": "startTimer",
"vfid": vfid}, decode=True))
@@ -64,12 +64,12 @@ class BayfilesCom(SimpleHoster):
self.setWait(int(delay))
self.wait()
- self.html = self.load('http://bayfiles.com/ajax_download', get={
+ self.html = self.load('https://bayfiles.com/ajax_download', get={
"token": response['token'],
"action": "getLink",
"vfid": vfid})
- # Get final link and download
+ # Get final link and download
found = re.search(self.LINK_PATTERN, self.html)
if not found:
self.parseError("Free link")
@@ -90,9 +90,9 @@ class BayfilesCom(SimpleHoster):
"notfound": re.compile(r"<title>404 Not Found</title>")
})
if check == "waitforfreeslots":
- self.retry(60, 300, "Wait for free slot")
+ self.retry(30, 60 * 5, "Wait for free slot")
elif check == "notfound":
- self.retry(60, 300, "404 Not found")
+ self.retry(30, 60 * 5, "404 Not found")
getInfo = create_getInfo(BayfilesCom)
diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py
index 7d5336cd9..77c45ed92 100644
--- a/module/plugins/hoster/CrockoCom.py
+++ b/module/plugins/hoster/CrockoCom.py
@@ -10,8 +10,8 @@ from module.plugins.internal.CaptchaService import ReCaptcha
class CrockoCom(SimpleHoster):
__name__ = "CrockoCom"
__type__ = "hoster"
- __pattern__ = r"http://(www\.)?(crocko|easy-share).com/.*"
- __version__ = "0.14"
+ __pattern__ = r"http://(www\.)?(crocko|easy-share).com/\w+"
+ __version__ = "0.15"
__description__ = """Crocko Download Hoster"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -32,7 +32,7 @@ class CrockoCom(SimpleHoster):
if "You need Premium membership to download this file." in self.html:
self.fail("You need Premium membership to download this file.")
- for i in range(5):
+ for _ in xrange(5):
found = re.search(self.CAPTCHA_URL_PATTERN, self.html)
if found:
url, wait_time = 'http://crocko.com' + found.group(1), found.group(2)
@@ -55,7 +55,7 @@ class CrockoCom(SimpleHoster):
recaptcha = ReCaptcha(self)
- for i in range(5):
+ for _ in xrange(5):
inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key)
self.download(action, post=inputs)
diff --git a/module/plugins/hoster/NowDownloadEu.py b/module/plugins/hoster/NowDownloadEu.py
index ff7d237f5..bd84b58bc 100644
--- a/module/plugins/hoster/NowDownloadEu.py
+++ b/module/plugins/hoster/NowDownloadEu.py
@@ -24,8 +24,8 @@ from module.utils import fixup
class NowDownloadEu(SimpleHoster):
__name__ = "NowDownloadEu"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?nowdownload\.(ch|eu|co)/(dl/|download\.php\?id=)(?P<ID>[a-zA-Z0-9]+)"
- __version__ = "0.03"
+ __pattern__ = r"http://(?:www\.)?nowdownload\.(ch|co|eu|sx)/(dl/|download\.php\?id=)(?P<ID>\w+)"
+ __version__ = "0.04"
__description__ = """NowDownloadCh"""
__author_name__ = ("godofdream", "Walter Purcaro")
__author_mail__ = ("", "vuolter@gmail.com")
diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py
index d574d1fa7..78d8b3deb 100644
--- a/module/plugins/hoster/TurbobitNet.py
+++ b/module/plugins/hoster/TurbobitNet.py
@@ -36,7 +36,7 @@ class TurbobitNet(SimpleHoster):
__name__ = "TurbobitNet"
__type__ = "hoster"
__pattern__ = r"http://(?:\w*\.)?(turbobit.net|unextfiles.com)/(?!download/folder/)(?:download/free/)?(?P<ID>\w+).*"
- __version__ = "0.10"
+ __version__ = "0.11"
__description__ = """Turbobit.net plugin"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -168,6 +168,7 @@ class TurbobitNet(SimpleHoster):
def handlePremium(self):
self.logDebug("Premium download as user %s" % self.user)
+ self.html = self.load(self.pyfile.url) # Useless in 0.5
self.downloadFile()
def downloadFile(self):
diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py
index f730a8434..32c137414 100644
--- a/module/plugins/internal/AbstractExtractor.py
+++ b/module/plugins/internal/AbstractExtractor.py
@@ -1,15 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+
class ArchiveError(Exception):
pass
+
class CRCError(Exception):
pass
+
class WrongPassword(Exception):
pass
+
class AbtractExtractor:
__version__ = "0.1"
@@ -29,7 +33,6 @@ class AbtractExtractor:
"""
raise NotImplementedError
-
def __init__(self, m, file, out, fullpath, overwrite, excludefiles, renice):
"""Initialize extractor for specific file
@@ -47,14 +50,12 @@ class AbtractExtractor:
self.overwrite = overwrite
self.excludefiles = excludefiles
self.renice = renice
- self.files = [] # Store extracted files here
-
+ self.files = [] #: Store extracted files here
def init(self):
""" Initialize additional data structures """
pass
-
def checkArchive(self):
"""Check if password if needed. Raise ArchiveError if integrity is
questionable.
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py
index b912436a7..4aa3f7dad 100644
--- a/module/plugins/internal/CaptchaService.py
+++ b/module/plugins/internal/CaptchaService.py
@@ -1,4 +1,5 @@
# -*- 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
@@ -18,49 +19,53 @@
import re
-class CaptchaService():
+
+class CaptchaService():
__version__ = "0.02"
-
+
def __init__(self, plugin):
self.plugin = plugin
-
+
+
class ReCaptcha():
def __init__(self, plugin):
self.plugin = plugin
-
+
def challenge(self, id):
- js = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={"k":id}, cookies=True)
-
+ js = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={"k": id}, cookies=True)
+
try:
challenge = re.search("challenge : '(.*?)',", js).group(1)
server = re.search("server : '(.*?)',", js).group(1)
except:
self.plugin.fail("recaptcha error")
- result = self.result(server,challenge)
-
+ result = self.result(server, challenge)
+
return challenge, result
def result(self, server, challenge):
- return self.plugin.decryptCaptcha("%simage"%server, get={"c":challenge}, cookies=True, forceUser=True, imgtype="jpg")
+ return self.plugin.decryptCaptcha("%simage" % server, get={"c": challenge}, cookies=True, forceUser=True, imgtype="jpg")
+
class AdsCaptcha(CaptchaService):
def challenge(self, src):
js = self.plugin.req.load(src, cookies=True)
-
+
try:
challenge = re.search("challenge: '(.*?)',", js).group(1)
server = re.search("server: '(.*?)',", js).group(1)
except:
self.plugin.fail("adscaptcha error")
- result = self.result(server,challenge)
-
+ result = self.result(server, challenge)
+
return challenge, result
def result(self, server, challenge):
return self.plugin.decryptCaptcha("%sChallenge.aspx" % server, get={"cid": challenge, "dummy": random()}, cookies=True, imgtype="jpg")
+
class SolveMedia(CaptchaService):
- def __init__(self,plugin):
+ def __init__(self, plugin):
self.plugin = plugin
def challenge(self, src):
@@ -70,8 +75,8 @@ class SolveMedia(CaptchaService):
except:
self.plugin.fail("solvmedia error")
result = self.result(challenge)
-
+
return challenge, result
- def result(self,challenge):
- return self.plugin.decryptCaptcha("http://api.solvemedia.com/papi/media?c=%s" % challenge,imgtype="gif") \ No newline at end of file
+ def result(self, challenge):
+ return self.plugin.decryptCaptcha("http://api.solvemedia.com/papi/media?c=%s" % challenge, imgtype="gif")
diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py
index 805f781af..51e24a00a 100644
--- a/module/plugins/internal/DeadCrypter.py
+++ b/module/plugins/internal/DeadCrypter.py
@@ -9,6 +9,6 @@ class DeadCrypter(_Crypter):
__description__ = """Crypter is no longer available"""
__author_name__ = ("stickell")
__author_mail__ = ("l.stickell@yahoo.it")
-
+
def setup(self):
self.fail("Crypter is no longer available")
diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py
index e180e2384..ba6abc0c5 100644
--- a/module/plugins/internal/DeadHoster.py
+++ b/module/plugins/internal/DeadHoster.py
@@ -5,6 +5,7 @@ def create_getInfo(plugin):
yield [('#N/A: ' + url, 0, 1, url) for url in urls]
return getInfo
+
class DeadHoster(_Hoster):
__name__ = "DeadHoster"
__type__ = "hoster"
@@ -13,6 +14,6 @@ class DeadHoster(_Hoster):
__description__ = """Hoster is no longer available"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
-
+
def setup(self):
- self.fail("Hoster is no longer available") \ No newline at end of file
+ self.fail("Hoster is no longer available")
diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py
index a8961aafc..bd6dc7877 100644
--- a/module/plugins/internal/MultiHoster.py
+++ b/module/plugins/internal/MultiHoster.py
@@ -6,6 +6,7 @@ import re
from module.utils import remove_chars
from module.plugins.Hook import Hook
+
class MultiHoster(Hook):
"""
Generic MultiHoster plugin
@@ -14,19 +15,19 @@ class MultiHoster(Hook):
__version__ = "0.19"
replacements = [("2shared.com", "twoshared.com"), ("4shared.com", "fourshared.com"), ("cloudnator.com", "shragle.com"),
- ("ifile.it", "filecloud.io"), ("easy-share.com","crocko.com"), ("freakshare.net","freakshare.com"),
- ("hellshare.com", "hellshare.cz"), ("share-rapid.cz","sharerapid.com"), ("sharerapid.cz","sharerapid.com"),
- ("ul.to","uploaded.to"), ("uploaded.net","uploaded.to"), ("1fichier.com", "onefichier.com")]
+ ("ifile.it", "filecloud.io"), ("easy-share.com", "crocko.com"), ("freakshare.net", "freakshare.com"),
+ ("hellshare.com", "hellshare.cz"), ("share-rapid.cz", "sharerapid.com"), ("sharerapid.cz", "sharerapid.com"),
+ ("ul.to", "uploaded.to"), ("uploaded.net", "uploaded.to"), ("1fichier.com", "onefichier.com")]
ignored = []
- interval = 24 * 60 * 60 # reload hosters daily
-
+ interval = 24 * 60 * 60 #: reload hosters daily
+
def setup(self):
self.hosters = []
self.supported = []
self.new_supported = []
-
- def getConfig(self, option, default = ''):
- """getConfig with default value - sublass may not implements all config options"""
+
+ def getConfig(self, option, default=''):
+ """getConfig with default value - sublass may not implements all config options"""
try:
return self.getConf(option)
except KeyError:
@@ -40,33 +41,33 @@ class MultiHoster(Hook):
except Exception, e:
self.logError("%s" % str(e))
return []
-
- try:
+
+ try:
configMode = self.getConfig('hosterListMode', 'all')
if configMode in ("listed", "unlisted"):
- configSet = self.toHosterSet(self.getConfig('hosterList', '').replace('|',',').replace(';',',').split(','))
-
+ configSet = self.toHosterSet(self.getConfig('hosterList', '').replace('|', ',').replace(';', ',').split(','))
+
if configMode == "listed":
hosterSet &= configSet
else:
hosterSet -= configSet
-
+
except Exception, e:
self.logError("%s" % str(e))
-
+
self.hosters = list(hosterSet)
return self.hosters
-
+
def toHosterSet(self, hosters):
hosters = set((str(x).strip().lower() for x in hosters))
-
+
for rep in self.replacements:
if rep[0] in hosters:
hosters.remove(rep[0])
hosters.add(rep[1])
-
- hosters.discard('')
+
+ hosters.discard('')
return hosters
def getHoster(self):
@@ -75,34 +76,34 @@ class MultiHoster(Hook):
:return: List of domain names
"""
raise NotImplementedError
-
+
def coreReady(self):
if self.cb:
self.core.scheduler.removeJob(self.cb)
-
- self.setConfig("activated", True) # config not in sync after plugin reload
-
- cfg_interval = self.getConfig("interval", None) # reload interval in hours
+
+ self.setConfig("activated", True) #: config not in sync after plugin reload
+
+ cfg_interval = self.getConfig("interval", None) #: reload interval in hours
if cfg_interval is not None:
- self.interval = cfg_interval * 60 * 60
-
+ self.interval = cfg_interval * 60 * 60
+
if self.interval:
self._periodical()
else:
self.periodical()
-
+
def initPeriodical(self):
- pass
-
+ pass
+
def periodical(self):
"""reload hoster list periodically"""
self.logInfo("Reloading supported hoster list")
-
+
old_supported = self.supported
self.supported, self.new_supported, self.hosters = [], [], []
-
+
self.overridePlugins()
-
+
old_supported = [hoster for hoster in old_supported if hoster not in self.supported]
if old_supported:
self.logDebug("UNLOAD: %s" % ", ".join(old_supported))
@@ -113,15 +114,15 @@ class MultiHoster(Hook):
pluginMap = {}
for name in self.core.pluginManager.hosterPlugins.keys():
pluginMap[name.lower()] = name
-
- accountList = [ name.lower() for name, data in self.core.accountManager.accounts.items() if data ]
+
+ accountList = [name.lower() for name, data in self.core.accountManager.accounts.items() if data]
excludedList = []
-
+
for hoster in self.getHosterCached():
name = remove_chars(hoster.lower(), "-.")
if name in accountList:
- excludedList.append(hoster)
+ excludedList.append(hoster)
else:
if name in pluginMap:
self.supported.append(pluginMap[name])
@@ -134,27 +135,27 @@ class MultiHoster(Hook):
module = self.core.pluginManager.getPlugin(self.__name__)
klass = getattr(module, self.__name__)
-
+
# inject plugin plugin
self.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(self.supported)))
for hoster in self.supported:
dict = self.core.pluginManager.hosterPlugins[hoster]
dict["new_module"] = module
dict["new_name"] = self.__name__
-
+
if excludedList:
self.logInfo("The following hosters were not overwritten - account exists: %s" % ", ".join(sorted(excludedList)))
if self.new_supported:
self.logDebug("New Hosters: %s" % ", ".join(sorted(self.new_supported)))
-
+
# create new regexp
- regexp = r".*(%s).*" % "|".join([x.replace(".", "\\.") for x in self.new_supported])
+ regexp = r".*(%s).*" % "|".join([x.replace(".", "\\.") for x in self.new_supported])
if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__:
regexp = r"%s|%s" % (klass.__pattern__, regexp)
-
+
self.logDebug("Regexp: %s" % regexp)
-
+
dict = self.core.pluginManager.hosterPlugins[self.__name__]
dict["pattern"] = regexp
dict["re"] = re.compile(regexp)
@@ -172,18 +173,18 @@ class MultiHoster(Hook):
"""Remove override for all hosters. Scheduler job is removed by hookmanager"""
for hoster in self.supported:
self.unloadHoster(hoster)
-
+
# reset pattern
klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__)
dict = self.core.pluginManager.hosterPlugins[self.__name__]
- dict["pattern"] = getattr(klass, '__pattern__', r"^unmatchable$")
- dict["re"] = re.compile(dict["pattern"])
-
+ dict["pattern"] = getattr(klass, '__pattern__', r"^unmatchable$")
+ dict["re"] = re.compile(dict["pattern"])
+
def downloadFailed(self, pyfile):
- """remove plugin override if download fails but not if file is offline/temp.offline"""
+ """remove plugin override if download fails but not if file is offline/temp.offline"""
if pyfile.hasStatus("failed") and self.getConfig("unloadFailing", True):
hdict = self.core.pluginManager.hosterPlugins[pyfile.pluginname]
if "new_name" in hdict and hdict['new_name'] == self.__name__:
- self.logDebug("Unload MultiHoster", pyfile.pluginname, hdict)
+ self.logDebug("Unload MultiHoster", pyfile.pluginname, hdict)
self.unloadHoster(pyfile.pluginname)
- pyfile.setStatus("queued") \ No newline at end of file
+ pyfile.setStatus("queued")
diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py
index f0fe0b764..78c7158bf 100644
--- a/module/plugins/internal/SimpleCrypter.py
+++ b/module/plugins/internal/SimpleCrypter.py
@@ -21,11 +21,12 @@ import re
from module.plugins.Crypter import Crypter
from module.utils import html_unescape
+from module.plugins.internal.SimpleHoster import replace_patterns
class SimpleCrypter(Crypter):
__name__ = "SimpleCrypter"
- __version__ = "0.06"
+ __version__ = "0.07"
__pattern__ = None
__type__ = "crypter"
__description__ = """Base crypter plugin"""
@@ -52,7 +53,11 @@ class SimpleCrypter(Crypter):
must return the html of the page number 'page_n'
"""
+ FILE_URL_REPLACEMENTS = []
+
def decrypt(self, pyfile):
+ pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS)
+
self.html = self.load(pyfile.url, decode=True)
package_name, folder_name = self.getPackageNameAndFolder()
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
index 856d3fde6..962d7639e 100644
--- a/module/plugins/internal/SimpleHoster.py
+++ b/module/plugins/internal/SimpleHoster.py
@@ -213,7 +213,8 @@ class SimpleHoster(Hoster):
self.handleFree()
def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False):
- if type(url) == unicode: url = url.encode('utf8')
+ if type(url) == unicode:
+ url = url.encode('utf8')
return Hoster.load(self, url=url, get=get, post=post, ref=ref, cookies=cookies,
just_header=just_header, decode=decode)
diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py
index 80ee39cdf..ec430c5bc 100644
--- a/module/plugins/internal/UnRar.py
+++ b/module/plugins/internal/UnRar.py
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
-
+
@author: RaNaN
"""
@@ -27,6 +27,7 @@ from string import digits
from module.utils import save_join, decode
from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPassword, ArchiveError, CRCError
+
class UnRar(AbtractExtractor):
__name__ = "UnRar"
__version__ = "0.14"
@@ -50,7 +51,7 @@ class UnRar(AbtractExtractor):
p.communicate()
except OSError:
- #fallback to rar
+ # fallback to rar
UnRar.CMD = "rar"
p = Popen([UnRar.CMD], stdout=PIPE, stderr=PIPE)
p.communicate()
@@ -62,11 +63,12 @@ class UnRar(AbtractExtractor):
result = []
for file, id in files_ids:
- if not file.endswith(".rar"): continue
+ if not file.endswith(".rar"):
+ continue
match = UnRar.re_splitfile.findall(file)
if match:
- #only add first parts
+ # only add first parts
if int(match[0][1]) == 1:
result.append((file, id))
else:
@@ -74,12 +76,11 @@ class UnRar(AbtractExtractor):
return result
-
def init(self):
self.passwordProtected = False
- self.headerProtected = False #list files will not work without password
- self.smallestFile = None #small file to test passwords
- self.password = "" #save the correct password
+ self.headerProtected = False #: list files will not work without password
+ self.smallestFile = None #: small file to test passwords
+ self.password = "" #: save the correct password
def checkArchive(self):
p = self.call_unrar("l", "-v", self.file)
@@ -102,7 +103,7 @@ class UnRar(AbtractExtractor):
return False
def checkPassword(self, password):
- #at this point we can only verify header protected files
+ # at this point we can only verify header protected files
if self.headerProtected:
p = self.call_unrar("l", "-v", self.file, password=password)
out, err = p.communicate()
@@ -111,7 +112,6 @@ class UnRar(AbtractExtractor):
return True
-
def extract(self, progress, password=None):
command = "x" if self.fullpath else "e"
@@ -144,7 +144,7 @@ class UnRar(AbtractExtractor):
raise CRCError
elif "CRC failed" in err:
raise WrongPassword
- if err.strip(): #raise error if anything is on stderr
+ if err.strip(): #: raise error if anything is on stderr
raise ArchiveError(err.strip())
if p.returncode:
raise ArchiveError("Process terminated")
@@ -153,7 +153,6 @@ class UnRar(AbtractExtractor):
self.password = password
self.listContent()
-
def getDeleteFiles(self):
if ".part" in self.file:
return glob(re.sub("(?<=\.part)([01]+)", "*", self.file, re.IGNORECASE))
@@ -169,7 +168,7 @@ class UnRar(AbtractExtractor):
if "Cannot open" in err:
raise ArchiveError("Cannot open file")
- if err.strip(): # only log error at this point
+ if err.strip(): #: only log error at this point
self.m.logError(err.strip())
result = set()
@@ -180,26 +179,25 @@ class UnRar(AbtractExtractor):
self.files = result
-
def call_unrar(self, command, *xargs, **kwargs):
args = []
- #overwrite flag
+ # overwrite flag
args.append("-o+") if self.overwrite else args.append("-o-")
-
+
if self.excludefiles:
for word in self.excludefiles.split(';'):
- args.append("-x%s" % word )
-
+ args.append("-x%s" % word)
+
# assume yes on all queries
args.append("-y")
- #set a password
+ # set a password
if "password" in kwargs and kwargs["password"]:
args.append("-p%s" % kwargs["password"])
else:
args.append("-p-")
- #NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
+ # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
call = [self.CMD, command] + args + list(xargs)
self.m.logDebug(" ".join(call))
diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py
index 9aa9ac75c..501962442 100644
--- a/module/plugins/internal/UnZip.py
+++ b/module/plugins/internal/UnZip.py
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
-
+
@author: RaNaN
"""
@@ -22,6 +22,7 @@ import sys
from module.plugins.internal.AbstractExtractor import AbtractExtractor
+
class UnZip(AbtractExtractor):
__name__ = "UnZip"
__version__ = "0.1"
@@ -46,4 +47,4 @@ class UnZip(AbtractExtractor):
z.extractall(self.out)
def getDeleteFiles(self):
- return [self.file] \ No newline at end of file
+ return [self.file]
diff --git a/module/plugins/internal/XFSPAccount.py b/module/plugins/internal/XFSPAccount.py
index 8333c7265..e4f211216 100644
--- a/module/plugins/internal/XFSPAccount.py
+++ b/module/plugins/internal/XFSPAccount.py
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
-
+
@author: zoidberg
"""
@@ -23,6 +23,7 @@ from module.plugins.Account import Account
from module.plugins.internal.SimpleHoster import parseHtmlForm
from module.utils import parseFileSize
+
class XFSPAccount(Account):
__name__ = "XFSPAccount"
__version__ = "0.05"
@@ -30,18 +31,18 @@ class XFSPAccount(Account):
__description__ = """XFileSharingPro account base"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
-
+
MAIN_PAGE = None
-
+
VALID_UNTIL_PATTERN = r'>Premium.[Aa]ccount expire:</TD><TD><b>([^<]+)</b>'
TRAFFIC_LEFT_PATTERN = r'>Traffic available today:</TD><TD><b>([^<]+)</b>'
-
- def loadAccountInfo(self, user, req):
- html = req.load(self.MAIN_PAGE + "?op=my_account", decode = True)
-
+
+ def loadAccountInfo(self, user, req):
+ html = req.load(self.MAIN_PAGE + "?op=my_account", decode=True)
+
validuntil = trafficleft = None
premium = True if '>Renew premium<' in html else False
-
+
found = re.search(self.VALID_UNTIL_PATTERN, html)
if found:
premium = True
@@ -58,22 +59,22 @@ class XFSPAccount(Account):
if "Unlimited" in trafficleft:
premium = True
else:
- trafficleft = parseFileSize(trafficleft) / 1024
-
+ trafficleft = parseFileSize(trafficleft) / 1024
+
return ({"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium})
-
+
def login(self, user, data, req):
- html = req.load('%slogin.html' % self.MAIN_PAGE, decode = True)
-
+ html = req.load('%slogin.html' % self.MAIN_PAGE, decode=True)
+
action, inputs = parseHtmlForm('name="FL"', html)
if not inputs:
inputs = {"op": "login",
- "redirect": self.MAIN_PAGE}
-
+ "redirect": self.MAIN_PAGE}
+
inputs.update({"login": user,
"password": data['password']})
-
- html = req.load(self.MAIN_PAGE, post = inputs, decode = True)
-
- if 'Incorrect Login or Password' in html or '>Error<' in html:
- self.wrongPassword() \ No newline at end of file
+
+ html = req.load(self.MAIN_PAGE, post=inputs, decode=True)
+
+ if 'Incorrect Login or Password' in html or '>Error<' in html:
+ self.wrongPassword()