summaryrefslogtreecommitdiffstats
path: root/module/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'module/plugins')
-rw-r--r--module/plugins/accounts/LinestorageCom.py18
-rw-r--r--module/plugins/accounts/OboomCom.py9
-rw-r--r--module/plugins/accounts/RapiduNet.py2
-rw-r--r--module/plugins/accounts/UptoboxCom.py20
-rwxr-xr-x[-rw-r--r--]module/plugins/crypter/Go4UpCom.py33
-rw-r--r--module/plugins/crypter/GoogledriveComFolder.py4
-rw-r--r--module/plugins/crypter/LinkCryptWs.py17
-rw-r--r--module/plugins/crypter/MultiUpOrg.py8
-rw-r--r--module/plugins/crypter/SexuriaCom.py61
-rw-r--r--module/plugins/crypter/TNTVillageScambioeticoOrg.py4
-rw-r--r--module/plugins/hooks/Checksum.py4
-rw-r--r--module/plugins/hooks/ExtractArchive.py12
-rw-r--r--module/plugins/hooks/IRCInterface.py4
-rw-r--r--module/plugins/hooks/TransmissionRPC.py84
-rw-r--r--module/plugins/hooks/XFileSharingPro.py12
-rw-r--r--module/plugins/hoster/OneFichierCom.py59
-rw-r--r--module/plugins/hoster/OpenloadIo.py12
-rw-r--r--module/plugins/hoster/PremiumizeMe.py8
-rw-r--r--module/plugins/hoster/ShareonlineBiz.py4
-rw-r--r--module/plugins/hoster/UlozTo.py10
-rw-r--r--module/plugins/hoster/UserscloudCom.py37
-rw-r--r--module/plugins/hoster/YoutubeCom.py28
-rw-r--r--module/plugins/internal/Addon.py8
-rw-r--r--module/plugins/internal/Captcha.py14
-rw-r--r--module/plugins/internal/Container.py2
-rw-r--r--module/plugins/internal/Hoster.py62
-rw-r--r--module/plugins/internal/Plugin.py31
-rw-r--r--module/plugins/internal/SimpleCrypter.py5
-rw-r--r--module/plugins/internal/SimpleHoster.py27
-rw-r--r--module/plugins/internal/XFSAccount.py15
30 files changed, 416 insertions, 198 deletions
diff --git a/module/plugins/accounts/LinestorageCom.py b/module/plugins/accounts/LinestorageCom.py
deleted file mode 100644
index 87dd2a1d3..000000000
--- a/module/plugins/accounts/LinestorageCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.XFSAccount import XFSAccount
-
-
-class LinestorageCom(XFSAccount):
- __name__ = "LinestorageCom"
- __type__ = "account"
- __version__ = "0.04"
- __status__ = "testing"
-
- __description__ = """Linestorage.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = "linestorage.com"
- HOSTER_URL = "http://linestorage.com/"
diff --git a/module/plugins/accounts/OboomCom.py b/module/plugins/accounts/OboomCom.py
index 380368b70..a792848ea 100644
--- a/module/plugins/accounts/OboomCom.py
+++ b/module/plugins/accounts/OboomCom.py
@@ -40,7 +40,7 @@ class OboomCom(Account):
get={'auth': user,
'pass': pbkdf2}))
- if not result[0] == 200:
+ if result[0] != 200:
self.log_warning(_("Failed to log in: %s") % result[1])
self.login_fail()
@@ -52,10 +52,7 @@ class OboomCom(Account):
userData = account_data['user']
- if userData['premium'] == "null":
- premium = False
- else:
- premium = True
+ premium = userData['premium'] != "null"
if userData['premium_unix'] == "null":
validUntil = -1
@@ -65,7 +62,7 @@ class OboomCom(Account):
traffic = userData['traffic']
trafficLeft = traffic['current'] / 1024 #@TODO: Remove `/ 1024` in 0.4.10
- maxTraffic = traffic['max'] / 1024 #@TODO: Remove `/ 1024` in 0.4.10
+ maxTraffic = traffic['max'] / 1024 #@TODO: Remove `/ 1024` in 0.4.10
session = account_data['session']
diff --git a/module/plugins/accounts/RapiduNet.py b/module/plugins/accounts/RapiduNet.py
index 1ec29bd77..2033d377f 100644
--- a/module/plugins/accounts/RapiduNet.py
+++ b/module/plugins/accounts/RapiduNet.py
@@ -62,5 +62,5 @@ class RapiduNet(Account):
self.log_debug(json)
- if not json['message'] == "success":
+ if json['message'] != "success":
self.login_fail()
diff --git a/module/plugins/accounts/UptoboxCom.py b/module/plugins/accounts/UptoboxCom.py
index 68aaecc47..7cc217823 100644
--- a/module/plugins/accounts/UptoboxCom.py
+++ b/module/plugins/accounts/UptoboxCom.py
@@ -4,16 +4,16 @@ from module.plugins.internal.XFSAccount import XFSAccount
class UptoboxCom(XFSAccount):
- __name__ = "UptoboxCom"
- __type__ = "account"
- __version__ = "0.09"
- __status__ = "testing"
+ __name__ = "UptoboxCom"
+ __type__ = "account"
+ __version__ = "0.12"
+ __status__ = "testing"
- __description__ = """DDLStorage.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+ __description__ = """Uptobox.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("benbox69", "dev@tollet.me")]
- HOSTER_DOMAIN = "uptobox.com"
- HOSTER_URL = "https://uptobox.com/"
- LOGIN_URL = "https://login.uptobox.com/"
+ HOSTER_DOMAIN = "uptobox.com"
+ HOSTER_URL = "https://uptobox.com/"
+ LOGIN_URL = "https://login.uptobox.com/logarithme/"
diff --git a/module/plugins/crypter/Go4UpCom.py b/module/plugins/crypter/Go4UpCom.py
index 026982014..2d423a1a9 100644..100755
--- a/module/plugins/crypter/Go4UpCom.py
+++ b/module/plugins/crypter/Go4UpCom.py
@@ -4,18 +4,20 @@ import re
import urlparse
from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
+import json
class Go4UpCom(SimpleCrypter):
__name__ = "Go4UpCom"
__type__ = "crypter"
- __version__ = "0.13"
+ __version__ = "0.14"
__status__ = "testing"
__pattern__ = r'http://go4up\.com/(dl/\w{12}|rd/\w{12}/\d+)'
__config__ = [("use_premium" , "bool", "Use premium account if available" , True),
("use_subfolder" , "bool", "Save package to subfolder" , True),
- ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
+ ("subfolder_per_pack", "bool", "Create a subfolder for each package", True),
+ ("preferred_hoster" , "int" , "Id of preferred hoster or 0 for all", 0)]
__description__ = """Go4Up.com decrypter plugin"""
__license__ = "GPLv3"
@@ -32,19 +34,20 @@ class Go4UpCom(SimpleCrypter):
def get_links(self):
links = []
-
- m = re.search(r'(/download/gethosts/.+?)"', self.html)
- if m:
- self.html = self.load(urlparse.urljoin("http://go4up.com/", m.group(1)))
- pages = [self.load(url) for url in re.findall(self.LINK_PATTERN, self.html)]
- else:
- pages = [self.html]
-
- for html in pages:
- try:
- links.append(re.search(r'<b><a href="(.+?)"', html).group(1))
- except Exception:
- continue
+ preference = self.get_config("preferred_hoster")
+
+ hosterslink_re = re.search(r'(/download/gethosts/.+?)"', self.html)
+ if hosterslink_re:
+ hosters = self.load(urlparse.urljoin("http://go4up.com/", hosterslink_re.group(1)))
+ for hoster in json.loads(hosters):
+ if preference != 0 and preference != int(hoster["hostId"]):
+ continue
+ pagelink_re = re.search(self.LINK_PATTERN, hoster["link"])
+ if pagelink_re:
+ page = self.load(pagelink_re.group(1))
+ link_re = re.search(r'<b><a href="(.+?)"', page)
+ if link_re:
+ links.append(link_re.group(1))
return links
diff --git a/module/plugins/crypter/GoogledriveComFolder.py b/module/plugins/crypter/GoogledriveComFolder.py
index 88c7ebab2..e7a5bae2c 100644
--- a/module/plugins/crypter/GoogledriveComFolder.py
+++ b/module/plugins/crypter/GoogledriveComFolder.py
@@ -6,11 +6,11 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
class GoogledriveComFolder(SimpleCrypter):
__name__ = "GoogledriveCom"
__type__ = "crypter"
- __version__ = "0.02"
+ __version__ = "0.03"
__status__ = "testing"
__pattern__ = r'https?://(?:www\.)?drive\.google\.com/folderview\?.*id=\w+'
- __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package']
+ __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True),
("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
__description__ = """Drive.google.com folder decrypter plugin"""
diff --git a/module/plugins/crypter/LinkCryptWs.py b/module/plugins/crypter/LinkCryptWs.py
index af13f55f6..16ee1d4f1 100644
--- a/module/plugins/crypter/LinkCryptWs.py
+++ b/module/plugins/crypter/LinkCryptWs.py
@@ -14,7 +14,7 @@ from module.utils import html_unescape
class LinkCryptWs(Crypter):
__name__ = "LinkCryptWs"
__type__ = "crypter"
- __version__ = "0.10"
+ __version__ = "0.12"
__status__ = "testing"
__pattern__ = r'http://(?:www\.)?linkcrypt\.ws/(dir|container)/(?P<ID>\w+)'
@@ -31,7 +31,6 @@ class LinkCryptWs(Crypter):
def setup(self):
- self.captcha = False
self.links = []
self.sources = ['cnl', 'web', 'dlc', 'rsdf', 'ccf']
@@ -60,7 +59,6 @@ class LinkCryptWs(Crypter):
self.retry(8, 15, _("Can't handle Key-Captcha"))
if self.is_captcha_protected():
- self.captcha = True
self.unlock_captcha_protection()
self.handle_captcha_errors()
@@ -154,7 +152,7 @@ class LinkCryptWs(Crypter):
unrarpw = sitein[indexi:indexe]
- if not (unrarpw == "Password" or "Dateipasswort") :
+ if unrarpw not in ("Password", "Dateipasswort"):
self.log_debug("File password set to: [%s]"% unrarpw)
self.pyfile.package().password = unrarpw
@@ -165,12 +163,11 @@ class LinkCryptWs(Crypter):
def handle_captcha_errors(self):
- if self.captcha:
- if "Your choice was wrong!" in self.html:
- self.captcha.invalid()
- self.retry()
- else:
- self.captcha.correct()
+ if "Your choice was wrong!" in self.html:
+ self.captcha.invalid()
+ self.retry()
+ else:
+ self.captcha.correct()
def handle_link_source(self, type):
diff --git a/module/plugins/crypter/MultiUpOrg.py b/module/plugins/crypter/MultiUpOrg.py
index 23e6dfa4a..fb228c3cd 100644
--- a/module/plugins/crypter/MultiUpOrg.py
+++ b/module/plugins/crypter/MultiUpOrg.py
@@ -9,10 +9,10 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
class MultiUpOrg(SimpleCrypter):
__name__ = "MultiUpOrg"
__type__ = "crypter"
- __version__ = "0.04"
+ __version__ = "0.05"
__status__ = "testing"
- __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?'
+ __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|mirror)/\w+(/\w+)?'
__config__ = [("use_premium" , "bool", "Use premium account if available" , True),
("use_subfolder" , "bool", "Save package to subfolder" , True),
("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
@@ -34,8 +34,8 @@ class MultiUpOrg(SimpleCrypter):
pattern = r'style="width:97%;text-align:left".*\n.*href="(.*)"'
if m_type == "download":
dl_pattern = r'href="(.*)">.*\n.*<h5>DOWNLOAD</h5>'
- miror_page = urlparse.urljoin("http://www.multiup.org/", re.search(dl_pattern, self.html).group(1))
- self.html = self.load(miror_page)
+ mirror_page = urlparse.urljoin("http://www.multiup.org/", re.search(dl_pattern, self.html).group(1))
+ self.html = self.load(mirror_page)
return re.findall(pattern, self.html)
diff --git a/module/plugins/crypter/SexuriaCom.py b/module/plugins/crypter/SexuriaCom.py
index 7942d5e42..24a5060b9 100644
--- a/module/plugins/crypter/SexuriaCom.py
+++ b/module/plugins/crypter/SexuriaCom.py
@@ -1,25 +1,23 @@
# -*- coding: utf-8 -*-
import re
-
from module.plugins.internal.Crypter import Crypter
-
class SexuriaCom(Crypter):
__name__ = "SexuriaCom"
__type__ = "crypter"
- __version__ = "0.04"
+ __version__ = "0.10"
__status__ = "testing"
__pattern__ = r'http://(?:www\.)?sexuria\.com/(v1/)?(Pornos_Kostenlos_.+?_(\d+)\.html|dl_links_\d+_\d+\.html|id=\d+\&part=\d+\&link=\d+)'
- __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True),
- ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
+ __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
__description__ = """Sexuria.com decrypter plugin"""
__license__ = "GPLv3"
__authors__ = [("NETHead", "NETHead.AT.gmx.DOT.net")]
-
+ #: Constants
PATTERN_SUPPORTED_MAIN = r'http://(www\.)?sexuria\.com/(v1/)?Pornos_Kostenlos_.+?_(\d+)\.html'
PATTERN_SUPPORTED_CRYPT = r'http://(www\.)?sexuria\.com/(v1/)?dl_links_\d+_(?P<ID>\d+)\.html'
PATTERN_SUPPORTED_REDIRECT = r'http://(www\.)?sexuria\.com/out\.php\?id=(?P<ID>\d+)\&part=\d+\&link=\d+'
@@ -27,15 +25,17 @@ class SexuriaCom(Crypter):
PATTERN_PASSWORD = r'<strong>Passwort: </strong></div></td>.*?bgcolor="#EFEFEF">(?P<PWD>.*?)</td>'
PATTERN_DL_LINK_PAGE = r'"(dl_links_\d+_\d+\.html)"'
PATTERN_REDIRECT_LINKS = r'value="(http://sexuria\.com/out\.php\?id=\d+\&part=\d+\&link=\d+)" readonly'
-
+ LIST_PWDIGNORE = ["Kein Passwort", "-"]
def decrypt(self, pyfile):
#: Init
self.pyfile = pyfile
self.package = pyfile.package()
- #: Get package links
+ #: Decrypt and add links
package_name, self.links, folder_name, package_pwd = self.decrypt_links(self.pyfile.url)
+ if package_pwd:
+ self.pyfile.package().password = package_pwd
self.packages = [(package_name, self.links, folder_name)]
@@ -62,34 +62,45 @@ class SexuriaCom(Crypter):
#: Extract info from main file
id = re.search(self.PATTERN_SUPPORTED_CRYPT, url, re.I).group('ID')
html = self.load("http://sexuria.com/v1/Pornos_Kostenlos_info_%s.html" % id)
+ #: Webpage title / Package name
+ titledata = re.search(self.PATTERN_TITLE, html, re.I)
+ if not titledata:
+ self.log_warning("No title data found, has site changed?")
+ else:
+ title = titledata.group('TITLE').strip()
+ if title:
+ name = folder = title
+ self.log_debug("Package info found, name [%s] and folder [%s]" % (name, folder))
+ #: Password
+ pwddata = re.search(self.PATTERN_PASSWORD, html, re.I | re.S)
+ if not pwddata:
+ self.log_warning("No password data found, has site changed?")
+ else:
+ pwd = pwddata.group('PWD').strip()
+ if pwd and not (pwd in self.LIST_PWDIGNORE):
+ password = pwd
+ self.log_debug("Package info found, password [%s]" % password)
- title = re.search(self.PATTERN_TITLE, html, re.I).group('TITLE').strip()
- if title:
- name = folder = title
- self.log_debug("Package info found, name [%s] and folder [%s]" % (name, folder))
-
- pwd = re.search(self.PATTERN_PASSWORD, html, re.I | re.S).group('PWD')
- if pwd and pwd not in ("Kein Passwort", "-"):
- password = pwd.strip()
- self.log_debug("Password info [%s] found" % password)
-
- #: Process link (dl_link)
+ #: Process links (dl_link)
html = self.load(url)
links = re.findall(self.PATTERN_REDIRECT_LINKS, html, re.I)
- if len(links) == 0:
+ if not links:
self.log_error(_("Broken for link: %s") % link)
else:
for link in links:
link = link.replace("http://sexuria.com/", "http://www.sexuria.com/")
finallink = self.load(link, just_header=True)['location']
- if not finallink or "sexuria.com/" in finallink:
+ if not finallink or ("sexuria.com/" in finallink):
self.log_error(_("Broken for link: %s") % link)
else:
linklist.append(finallink)
- #: Debug log
- self.log_debug("%d supported links" % len(linklist))
- for i, link in enumerate(linklist):
- self.log_debug("Supported link %d, %s" % (i + 1, link))
+ #: Log result
+ if not linklist:
+ self.fail(_("Unable to extract links (maybe plugin out of date?)"))
+ else:
+ for i, link in enumerate(linklist):
+ self.log_debug("Supported link %d/%d: %s" % (i+1, len(linklist), link))
+ #: All done, return to caller
return name, linklist, folder, password
diff --git a/module/plugins/crypter/TNTVillageScambioeticoOrg.py b/module/plugins/crypter/TNTVillageScambioeticoOrg.py
index 6ba1ee19b..e85a8fbb7 100644
--- a/module/plugins/crypter/TNTVillageScambioeticoOrg.py
+++ b/module/plugins/crypter/TNTVillageScambioeticoOrg.py
@@ -6,11 +6,11 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
class TNTVillageScambioeticoOrg(SimpleCrypter):
__name__ = "TNTVillageScambioeticoOrg"
__type__ = "crypter"
- __version__ = "0.02"
+ __version__ = "0.03"
__status__ = "testing"
__pattern__ = r'http://(?:www\.)?forum\.tntvillage\.scambioetico\.org/index\.php\?.*showtopic=\d+'
- __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package']
+ __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True),
("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
__description__ = """TNTVillage.scambioetico.org decrypter plugin"""
diff --git a/module/plugins/hooks/Checksum.py b/module/plugins/hooks/Checksum.py
index da4d35df1..64c5fa3ff 100644
--- a/module/plugins/hooks/Checksum.py
+++ b/module/plugins/hooks/Checksum.py
@@ -38,7 +38,7 @@ def compute_checksum(local_file, algorithm):
class Checksum(Addon):
__name__ = "Checksum"
__type__ = "hook"
- __version__ = "0.20"
+ __version__ = "0.21"
__status__ = "testing"
__config__ = [("check_checksum", "bool" , "Check checksum? (If False only size will be verified)", True ),
@@ -114,7 +114,7 @@ class Checksum(Addon):
api_size = int(data['size'])
file_size = os.path.getsize(local_file)
- if api_size is not file_size:
+ if api_size != file_size:
self.log_warning(_("File %s has incorrect size: %d B (%d expected)") % (pyfile.name, file_size, api_size))
self.check_failed(pyfile, local_file, "Incorrect file size")
diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py
index eab196160..87cd38ade 100644
--- a/module/plugins/hooks/ExtractArchive.py
+++ b/module/plugins/hooks/ExtractArchive.py
@@ -51,7 +51,7 @@ except ImportError:
pass
from module.plugins.internal.Addon import Addon, Expose, threaded
-from module.plugins.internal.Plugin import replace_patterns
+from module.plugins.internal.Plugin import exists, replace_patterns
from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError
from module.utils import fs_encode, save_join as fs_join, uniqify
@@ -107,7 +107,7 @@ class ArchiveQueue(object):
class ExtractArchive(Addon):
__name__ = "ExtractArchive"
__type__ = "hook"
- __version__ = "1.49"
+ __version__ = "1.50"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , True ),
@@ -288,7 +288,7 @@ class ExtractArchive(Addon):
if subfolder:
out = fs_join(out, pypack.folder)
- if not os.path.exists(out):
+ if not exists(out):
os.makedirs(out)
matched = False
@@ -313,7 +313,7 @@ class ExtractArchive(Addon):
for fname, fid, fout in targets:
name = os.path.basename(fname)
- if not os.path.exists(fname):
+ if not exists(fname):
self.log_debug(name, "File not found")
continue
@@ -356,7 +356,7 @@ class ExtractArchive(Addon):
for filename in new_files:
file = fs_encode(fs_join(os.path.dirname(archive.filename), filename))
- if not os.path.exists(file):
+ if not exists(file):
self.log_debug("New file %s does not exists" % filename)
continue
@@ -476,7 +476,7 @@ class ExtractArchive(Addon):
deltotrash = self.get_config('deltotrash')
for f in delfiles:
file = fs_encode(f)
- if not os.path.exists(file):
+ if not exists(file):
continue
if not deltotrash:
diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py
index 08b1bad0c..5d8928a57 100644
--- a/module/plugins/hooks/IRCInterface.py
+++ b/module/plugins/hooks/IRCInterface.py
@@ -18,7 +18,7 @@ from module.utils import formatSize
class IRCInterface(Thread, Addon):
__name__ = "IRCInterface"
__type__ = "hook"
- __version__ = "0.15"
+ __version__ = "0.16"
__status__ = "testing"
__config__ = [("host" , "str" , "IRC-Server Address" , "Enter your server here!"),
@@ -40,7 +40,7 @@ class IRCInterface(Thread, Addon):
def __init__(self, core, manager):
Thread.__init__(self)
Addon.__init__(self, core, manager)
- self.set_daemon(True)
+ self.setDaemon(True)
def activate(self):
diff --git a/module/plugins/hooks/TransmissionRPC.py b/module/plugins/hooks/TransmissionRPC.py
new file mode 100644
index 000000000..2ca06a9ad
--- /dev/null
+++ b/module/plugins/hooks/TransmissionRPC.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+import random
+import re
+
+import pycurl
+
+from module.common.json_layer import json_loads, json_dumps
+from module.network.HTTPRequest import BadHeader
+from module.network.RequestFactory import getRequest as get_request
+from module.plugins.internal.Addon import Addon
+
+
+class TransmissionRPC(Addon):
+ __name__ = "TransmissionRPC"
+ __type__ = "hook"
+ __version__ = "0.12"
+ __status__ = "testing"
+
+ __pattern__ = r"https?://.+\.torrent|magnet:\?.+"
+ __config__ = [("rpc_url", "str", "Transmission RPC URL", "http://127.0.0.1:9091/transmission/rpc")]
+
+ __description__ = """Send torrent and magnet URLs to Transmission Bittorent daemon via RPC"""
+ __license__ = "GPLv3"
+ __authors__ = [("GammaC0de", None)]
+
+
+ def init(self):
+ self.event_map = {'linksAdded': "links_added"}
+
+
+ def links_added(self, links, pid):
+ pattern = re.compile(self.__pattern__)
+ urls = [link for link in links if pattern.match(link)]
+
+ for url in urls:
+ self.log_debug("Sending link: %s" % url)
+ self.send_to_transmission(url)
+ links.remove(url)
+
+
+ def send_to_transmission(self, url):
+ transmission_rpc_url = self.get_config('rpc_url')
+ client_request_id = self.__name__ + "".join(random.choice('0123456789ABCDEF') for _i in xrange(4))
+ req = get_request()
+
+ try:
+ response = self.load(transmission_rpc_url,
+ post=json_dumps({'arguments': {'filename': url},
+ 'method' : 'torrent-add',
+ 'tag' : client_request_id}),
+ req=req)
+
+ except BadHeader, e:
+ if e.code == 409:
+ headers = dict(re.findall(r"(?P<name>.+?): (?P<value>.+?)\r?\n", req.header))
+ session_id = headers['X-Transmission-Session-Id']
+ req.c.setopt(pycurl.HTTPHEADER, ["X-Transmission-Session-Id: %s" % session_id])
+ try:
+ response = self.load(transmission_rpc_url,
+ post=json_dumps({'arguments': {'filename': url},
+ 'method' : 'torrent-add',
+ 'tag' : client_request_id}),
+ req=req)
+
+ except Exception, e:
+ self.log_error(e)
+ return
+
+ else:
+ self.log_error(e)
+ return
+
+ except Exception, e:
+ self.log_error(e)
+ return
+
+ try:
+ res = json_loads(response)
+ if "result" in res:
+ self.log_debug("Result: %s" % res['result'])
+
+ except Exception, e:
+ self.log_error(e)
diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py
index 7567a31a3..9b9c7f0ad 100644
--- a/module/plugins/hooks/XFileSharingPro.py
+++ b/module/plugins/hooks/XFileSharingPro.py
@@ -29,18 +29,20 @@ class XFileSharingPro(Hook):
r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')}
HOSTER_BUILTIN = [#WORKING HOSTERS:
- "ani-stream.com", "backin.net", "cloudsix.me", "eyesfile.ca", "file4safe.com",
- "fileband.com", "filedwon.com", "fileparadox.in", "filevice.com",
- "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com",
+ "ani-stream.com", "backin.net", "cloudsix.me", "eyesfile.ca",
+ "file4safe.com", "fileband.com", "filedwon.com", "fileparadox.in",
+ "filevice.com", "hostingbulk.com", "junkyvideo.com", "ravishare.com",
"ryushare.com", "salefiles.com", "sendmyway.com", "sharebeast.com",
- "sharesix.com", "thefile.me", "verzend.be", "worldbytez.com", "xvidstage.com",
+ "sharesix.com", "thefile.me", "verzend.be", "worldbytez.com",
+ "xvidstage.com",
#: NOT TESTED:
"101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com",
"linkzhost.com", "mightyupload.com", "rockdizfile.com", "sharerepo.com",
"shareswift.com", "uploadbaz.com", "uploadc.com", "vidbull.com",
"zalaa.com", "zomgupload.com",
#: NOT WORKING:
- "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"]
+ "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com",
+ "laoupload.com", "rd-fs.com"]
CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"]
diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py
index cba67b26c..70229a6ef 100644
--- a/module/plugins/hoster/OneFichierCom.py
+++ b/module/plugins/hoster/OneFichierCom.py
@@ -2,13 +2,14 @@
import re
+from module.network.RequestFactory import getURL as get_url
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class OneFichierCom(SimpleHoster):
__name__ = "OneFichierCom"
__type__ = "hoster"
- __version__ = "0.88"
+ __version__ = "0.90"
__status__ = "testing"
__pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?'
@@ -28,6 +29,8 @@ class OneFichierCom(SimpleHoster):
COOKIES = [("1fichier.com", "LG", "en")]
+ DIRECT_LINK = True
+
NAME_PATTERN = r'>File\s*Name :</td>\s*<td.*>(?P<N>.+?)<'
SIZE_PATTERN = r'>Size :</td>\s*<td.*>(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
OFFLINE_PATTERN = r'File not found !\s*<'
@@ -40,7 +43,61 @@ class OneFichierCom(SimpleHoster):
self.resume_download = True
+ @classmethod
+ def get_info(cls, url="", html=""):
+ redirect = url
+ for i in xrange(10):
+ try:
+ headers = dict(re.findall(r"(?P<name>.+?): (?P<value>.+?)\r?\n", get_url(redirect, just_header=True).lower()))
+ if 'location' in headers and headers['location']:
+ redirect = headers['location']
+ else:
+ if 'content-type' in headers and headers['content-type'] == "application/octet-stream":
+ if "filename=" in headers.get('content-disposition'):
+ name = dict(_i.split("=") for _i in map(str.strip, headers['content-disposition'].split(";"))[1:])['filename'].strip("\"'")
+ else:
+ name = url
+
+ info = {'name' : name,
+ 'size' : long(headers.get('content-length')),
+ 'status': 3,
+ 'url' : url}
+
+ else:
+ info = super(OneFichierCom, cls).get_info(url, html)
+
+ break
+
+ except Exception, e:
+ info = {'status' : 8,
+ 'error' : e.message}
+
+ else:
+ info = {'status' : 8,
+ 'error' : _("Too many redirects")}
+
+ return info
+
+
+ def handle_direct(self, pyfile):
+ redirect = pyfile.url
+ for i in xrange(self.get_config("maxredirs", plugin="UserAgentSwitcher")):
+
+ headers = self.load(redirect, just_header=True)
+ if 'location' in headers and headers['location']:
+ self.log_debug("Redirect #%d to: %s" % (i, redirect))
+ redirect = headers['location']
+ else:
+ if 'content-type' in headers and headers['content-type'] == "application/octet-stream":
+ self.link = pyfile.url
+ break
+ else:
+ self.fail(_("Too many redirects"))
+
+
def handle_free(self, pyfile):
+ self.check_errors()
+
id = self.info['pattern']['ID1'] or self.info['pattern']['ID2']
url, inputs = self.parse_html_form('action="https://1fichier.com/\?%s' % id)
diff --git a/module/plugins/hoster/OpenloadIo.py b/module/plugins/hoster/OpenloadIo.py
index c46462344..372ce28f9 100644
--- a/module/plugins/hoster/OpenloadIo.py
+++ b/module/plugins/hoster/OpenloadIo.py
@@ -6,25 +6,25 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class OpenloadIo(SimpleHoster):
__name__ = "OpenloadIo"
__type__ = "hoster"
- __version__ = "0.04"
+ __version__ = "0.05"
__status__ = "testing"
- __pattern__ = r'https?://(?:www\.)?openload\.io/f/[\w_-]{11}'
+ __pattern__ = r'https?://(?:www\.)?openload\.(co|io)/f/[\w-]+'
- __description__ = """Openload.io hoster plugin"""
+ __description__ = """Openload.co hoster plugin"""
__license__ = "GPLv3"
__authors__ = [(None, None)]
NAME_PATTERN = r'<span id="filename">(?P<N>.+?)</'
- SIZE_PATTERN = r'<span class="count">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<'
+ SIZE_PATTERN = r'<span class="count">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
OFFLINE_PATTERN = r">(We can't find the file you are looking for)"
- LINK_FREE_PATTERN = r'id="real\w*download"><a href="(https?://[\w\.]+\.openload\.io/dl/.*?)"'
+ LINK_FREE_PATTERN = r'id="real\w*download"><a href="(https?://[\w\.]+\.openload\.co/dl/.*?)"'
def setup(self):
- self.multiDL = True
+ self.multiDL = True
self.chunk_limit = 1
diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py
index d968eccec..e682a5a4c 100644
--- a/module/plugins/hoster/PremiumizeMe.py
+++ b/module/plugins/hoster/PremiumizeMe.py
@@ -7,7 +7,7 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
class PremiumizeMe(MultiHoster):
__name__ = "PremiumizeMe"
__type__ = "hoster"
- __version__ = "0.20"
+ __version__ = "0.21"
__status__ = "testing"
__pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.activate
@@ -44,6 +44,12 @@ class PremiumizeMe(MultiHoster):
status = data['status']
if status == 200:
+ if 'filename' in data['result']:
+ self.pyfile.name = data['result']['filename']
+
+ if 'filesize' in data['result']:
+ self.pyfile.size = data['result']['filesize']
+
self.link = data['result']['location']
return
diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py
index b5af3ea35..dbe7fe401 100644
--- a/module/plugins/hoster/ShareonlineBiz.py
+++ b/module/plugins/hoster/ShareonlineBiz.py
@@ -79,7 +79,7 @@ class ShareonlineBiz(SimpleHoster):
post={'dl_free' : "1",
'recaptcha_challenge_field': challenge,
'recaptcha_response_field' : response})
- if not res == "0":
+ if res != "0":
self.captcha.correct()
return res
else:
@@ -136,7 +136,7 @@ class ShareonlineBiz(SimpleHoster):
self.log_debug(dlinfo)
- if not dlinfo['status'] == "online":
+ if dlinfo['status'] != "online":
self.offline()
else:
pyfile.name = dlinfo['name']
diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py
index b402433a4..066d1daf0 100644
--- a/module/plugins/hoster/UlozTo.py
+++ b/module/plugins/hoster/UlozTo.py
@@ -15,7 +15,7 @@ def convert_decimal_prefix(m):
class UlozTo(SimpleHoster):
__name__ = "UlozTo"
__type__ = "hoster"
- __version__ = "1.13"
+ __version__ = "1.14"
__status__ = "testing"
__pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(?:live/)?(?P<ID>\w+/[^/?]*)'
@@ -27,7 +27,7 @@ class UlozTo(SimpleHoster):
INFO_PATTERN = r'<p>File <strong>(?P<N>[^<]+)</strong> is password protected</p>'
- NAME_PATTERN = r'<title>(?P<N>[^<]+) \| Uloz\.to</title>'
+ NAME_PATTERN = r'<title>(?P<N>.+?) \|'
SIZE_PATTERN = r'<span id="fileSize">.*?(?P<S>[\d.,]+\s[kMG]?B)</span>'
OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>'
@@ -68,7 +68,9 @@ class UlozTo(SimpleHoster):
#: New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013
self.log_debug('Using "new" version')
- xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={'rnd': str(int(time.time()))})
+ xapca = self.load("http://www.ulozto.net/reloadXapca.php",
+ get={'rnd': str(int(time.time()))})
+ xapca = xapca.replace('sound":"', 'sound":"http:').replace('image":"', 'image":"http:')
self.log_debug("xapca = " + str(xapca))
data = json_loads(xapca)
@@ -121,7 +123,7 @@ class UlozTo(SimpleHoster):
def check_file(self):
check = self.check_download({
- 'wrong_captcha': re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'),
+ 'wrong_captcha': ">An error ocurred while verifying the user",
'offline' : re.compile(self.OFFLINE_PATTERN),
'passwd' : self.PASSWD_PATTERN,
'server_error' : 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', #: Paralell dl, server overload etc.
diff --git a/module/plugins/hoster/UserscloudCom.py b/module/plugins/hoster/UserscloudCom.py
new file mode 100644
index 000000000..ebaed4859
--- /dev/null
+++ b/module/plugins/hoster/UserscloudCom.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+
+
+class UserscloudCom(SimpleHoster):
+ __name__ = "UserscloudCom"
+ __type__ = "hoster"
+ __version__ = "0.01"
+ __status__ = "testing"
+
+ __pattern__ = r'https?://(?:www\.)?userscloud\.com/\w{12}'
+
+ __description__ = """Userscloud.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("GammaC0de", None)]
+
+
+ NAME_PATTERN = r'<h2 class="strong margin-none">(?P<N>.+?)<'
+ SIZE_PATTERN = r'<div class="ribbon">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<'
+ OFFLINE_PATTERN = r'The file you are trying to download is no longer available'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.resume_download = False
+ self.chunk_limit = 1
+
+
+ def handle_free(self, pyfile):
+ self.download(pyfile.url,
+ post=dict(re.findall(r'<input type="hidden" name="(.+?)" value="(.*?)">', self.html)))
+
+
+getInfo = create_getInfo(UserscloudCom)
diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py
index 86cca7cf1..5c7c13962 100644
--- a/module/plugins/hoster/YoutubeCom.py
+++ b/module/plugins/hoster/YoutubeCom.py
@@ -6,37 +6,17 @@ import subprocess
import urllib
from module.plugins.internal.Hoster import Hoster
-from module.plugins.internal.Plugin import replace_patterns
+from module.plugins.internal.Plugin import replace_patterns, which
from module.utils import html_unescape
-def which(program):
- """
- Works exactly like the unix command which
- Courtesy of http://stackoverflow.com/a/377028/675646
- """
- isExe = lambda x: os.path.isfile(x) and os.access(x, os.X_OK)
-
- fpath, fname = os.path.split(program)
-
- if fpath:
- if isExe(program):
- return program
- else:
- for path in os.environ['PATH'].split(os.pathsep):
- path = path.strip('"')
- exe_file = os.path.join(path, program)
- if isExe(exe_file):
- return exe_file
-
-
class YoutubeCom(Hoster):
__name__ = "YoutubeCom"
__type__ = "hoster"
- __version__ = "0.45"
+ __version__ = "0.46"
__status__ = "testing"
- __pattern__ = r'https?://(?:[^/]*\.)?(youtube\.com|youtu\.be)/watch\?(?:.*&)?v=.+'
+ __pattern__ = r'https?://(?:[^/]*\.)?(youtu\.be/|youtube\.com/watch\?(?:.*&)?v=)\w+'
__config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting" , "hd" ),
("fmt" , "int" , "FMT/ITAG Number (0 for auto)", 0 ),
(".mp4" , "bool" , "Allow .mp4" , True ),
@@ -51,7 +31,7 @@ class YoutubeCom(Hoster):
("zoidberg", "zoidberg@mujmail.cz")]
- URL_REPLACEMENTS = [(r'youtu\.be/', 'youtube.com/')]
+ URL_REPLACEMENTS = [(r'youtu\.be/', 'youtube.com/watch?v=')]
#: Invalid characters that must be removed from the file name
invalid_chars = u'\u2605:?><"|\\'
diff --git a/module/plugins/internal/Addon.py b/module/plugins/internal/Addon.py
index 45ca98eac..4ccaaba8b 100644
--- a/module/plugins/internal/Addon.py
+++ b/module/plugins/internal/Addon.py
@@ -25,7 +25,7 @@ def threaded(fn):
class Addon(Plugin):
__name__ = "Addon"
__type__ = "hook" #@TODO: Change to `addon` in 0.4.10
- __version__ = "0.04"
+ __version__ = "0.05"
__status__ = "testing"
__config__ = [] #: [("name", "type", "desc", "default")]
@@ -57,6 +57,12 @@ class Addon(Plugin):
self.init_events()
+ #@TODO: Remove in 0.4.10
+ def _log(self, level, plugintype, pluginname, messages):
+ plugintype = "addon" if plugintype is "hook" else plugintype
+ return super(Addon, self)._log(level, plugintype, pluginname, messages)
+
+
def init_events(self):
if self.event_map:
for event, funcs in self.event_map.items():
diff --git a/module/plugins/internal/Captcha.py b/module/plugins/internal/Captcha.py
index c08050ee8..b864fd2d8 100644
--- a/module/plugins/internal/Captcha.py
+++ b/module/plugins/internal/Captcha.py
@@ -12,7 +12,7 @@ from module.plugins.internal.Plugin import Plugin
class Captcha(Plugin):
__name__ = "Captcha"
__type__ = "captcha"
- __version__ = "0.42"
+ __version__ = "0.43"
__status__ = "testing"
__description__ = """Base anti-captcha plugin"""
@@ -50,18 +50,18 @@ class Captcha(Plugin):
pass
- def decrypt(self, url, get={}, post={}, ref=False, cookies=False, decode=False,
+ def decrypt(self, url, get={}, post={}, ref=False, cookies=True, decode=False,
input_type='jpg', output_type='textual', ocr=True, timeout=120):
img = self.load(url, get=get, post=post, ref=ref, cookies=cookies, decode=decode)
return self._decrypt(img, input_type, output_type, ocr, timeout)
#@TODO: Definitely choose a better name for this method!
- def _decrypt(self, raw, input_type='jpg', output_type='textual', ocr=False, timeout=120):
+ def _decrypt(self, data, input_type='jpg', output_type='textual', ocr=False, timeout=120):
"""
Loads a captcha and decrypts it with ocr, plugin, user input
- :param raw: image raw data
+ :param data: image raw data
:param get: get part for request
:param post: post part for request
:param cookies: True if cookies should be enabled
@@ -77,7 +77,7 @@ class Captcha(Plugin):
time_ref = ("%.2f" % time.time())[-6:].replace(".", "")
with open(os.path.join("tmp", "captcha_image_%s_%s.%s" % (self.plugin.__name__, time_ref, input_type)), "wb") as tmp_img:
- tmp_img.write(raw)
+ tmp_img.write(data)
if ocr:
if isinstance(ocr, basestring):
@@ -90,7 +90,7 @@ class Captcha(Plugin):
captchaManager = self.pyload.captchaManager
try:
- self.task = captchaManager.newTask(raw, input_type, tmp_img.name, output_type)
+ self.task = captchaManager.newTask(data, input_type, tmp_img.name, output_type)
captchaManager.handleCaptcha(self.task)
@@ -120,7 +120,7 @@ class Captcha(Plugin):
self.log_warning(_("Error removing: %s") % tmp_img.name, e)
traceback.print_exc()
- self.log_info(_("Captcha result: ") + result) #@TODO: Remove from here?
+ #self.log_info(_("Captcha result: ") + result) #@TODO: Remove from here?
return result
diff --git a/module/plugins/internal/Container.py b/module/plugins/internal/Container.py
index 729592a0d..66e1ad904 100644
--- a/module/plugins/internal/Container.py
+++ b/module/plugins/internal/Container.py
@@ -63,7 +63,7 @@ class Container(Crypter):
f.write(content)
except IOError, e:
- self.fail(str(e)) #@TODO: Remove `str` in 0.4.10
+ self.fail(e)
else:
self.pyfile.name = os.path.basename(self.pyfile.url)
diff --git a/module/plugins/internal/Hoster.py b/module/plugins/internal/Hoster.py
index b397a92a6..ac42182c4 100644
--- a/module/plugins/internal/Hoster.py
+++ b/module/plugins/internal/Hoster.py
@@ -44,7 +44,7 @@ def create_getInfo(klass):
class Hoster(Plugin):
__name__ = "Hoster"
__type__ = "hoster"
- __version__ = "0.20"
+ __version__ = "0.22"
__status__ = "testing"
__pattern__ = r'^unmatchable$'
@@ -368,7 +368,7 @@ class Hoster(Plugin):
url = self.fixurl(url)
if not url or not isinstance(url, basestring):
- self.fail(_("No url given"))
+ self.fail(_("No given url"))
if self.pyload.debug:
self.log_debug("DOWNLOAD URL " + url,
@@ -412,7 +412,7 @@ class Hoster(Plugin):
if disposition and newname:
finalname = urlparse.urlparse(newname).path.split('/')[-1].split(' filename*=')[0]
- if finalname != newname != self.pyfile.name:
+ if finalname != newname:
try:
os.rename(fs_join(location, newname), fs_join(location, finalname))
@@ -421,8 +421,9 @@ class Hoster(Plugin):
finalname = newname
self.log_info(_("`%s` saved as `%s`") % (self.pyfile.name, finalname))
- self.pyfile.name = finalname
- filename = os.path.join(location, finalname)
+
+ self.pyfile.name = finalname
+ filename = os.path.join(location, finalname)
self.set_permissions(fs_encode(filename))
@@ -431,9 +432,35 @@ class Hoster(Plugin):
return self.last_download
- def check_download(self, rules, delete=False, file_size=0, size_tolerance=1024, read_size=1048576):
+ def check_filesize(self, file_size, size_tolerance=1024):
+ """
+ Checks the file size of the last downloaded file
+
+ :param file_size: expected file size
+ :param size_tolerance: size check tolerance
"""
- Checks the content of the last downloaded file, re match is saved to `lastCheck`
+ if not self.last_download:
+ return
+
+ download_size = os.stat(fs_encode(self.last_download)).st_size
+
+ if download_size < 1:
+ self.fail(_("Empty file"))
+
+ elif file_size > 0:
+ diff = abs(file_size - download_size)
+
+ if diff > size_tolerance:
+ self.fail(_("File size mismatch | Expected file size: %s | Downloaded file size: %s")
+ % (file_size, download_size))
+
+ elif diff != 0:
+ self.log_warning(_("File size is not equal to expected size"))
+
+
+ def check_download(self, rules, delete=False, read_size=1048576, file_size=0, size_tolerance=1024):
+ """
+ Checks the content of the last downloaded file, re match is saved to `last_check`
:param rules: dict with names and rules to match (compiled regexp or strings)
:param delete: delete if matched
@@ -446,26 +473,11 @@ class Hoster(Plugin):
last_download = fs_encode(self.last_download)
if not self.last_download or not exists(last_download):
- self.last_download = ""
+ self.last_download = "" #@NOTE: Bad place...
self.fail(self.pyfile.error or _("No file downloaded"))
try:
- download_size = os.stat(last_download).st_size
-
- if download_size < 1:
- do_delete = True
- self.fail(_("Empty file"))
-
- elif file_size > 0:
- diff = abs(file_size - download_size)
-
- if diff > size_tolerance:
- do_delete = True
- self.fail(_("File size mismatch | Expected file size: %s | Downloaded file size: %s")
- % (file_size, download_size))
-
- elif diff != 0:
- self.log_warning(_("File size is not equal to expected size"))
+ self.check_filesize(file_size, size_tolerance)
with open(last_download, "rb") as f:
content = f.read(read_size)
@@ -495,8 +507,8 @@ class Hoster(Plugin):
traceback.print_exc()
else:
+ self.log_info(_("File deleted: ") + self.last_download)
self.last_download = ""
- self.log_info(_("File deleted"))
def direct_link(self, url, follow_location=None):
diff --git a/module/plugins/internal/Plugin.py b/module/plugins/internal/Plugin.py
index 8bc5d4a65..feabe9f1d 100644
--- a/module/plugins/internal/Plugin.py
+++ b/module/plugins/internal/Plugin.py
@@ -52,11 +52,40 @@ def fixurl(url):
return html_unescape(urllib.unquote(url.decode('unicode-escape'))).strip().rstrip('/')
+def fixname(m):
+ m = unicodedata.normalize('NFKD', m)
+ output = ''
+ for c in m:
+ if not unicodedata.combining(c):
+ output += c
+ return output
+
+
#@TODO: Move to utils in 0.4.10
def timestamp():
return int(time.time() * 1000)
+#@TODO: Move to utils in 0.4.10
+def which(program):
+ """
+ Works exactly like the unix command which
+ Courtesy of http://stackoverflow.com/a/377028/675646
+ """
+ isExe = lambda x: os.path.isfile(x) and os.access(x, os.X_OK)
+
+ fpath, fname = os.path.split(program)
+
+ if fpath:
+ if isExe(program):
+ return program
+ else:
+ for path in os.environ['PATH'].split(os.pathsep):
+ exe_file = os.path.join(path.strip('"'), program)
+ if isExe(exe_file):
+ return exe_file
+
+
def seconds_to_midnight(gmt=0):
now = datetime.datetime.utcnow() + datetime.timedelta(hours=gmt)
@@ -325,7 +354,7 @@ class Plugin(object):
url = fixurl(url)
if not url or not isinstance(url, basestring):
- self.fail(_("No url given"))
+ self.fail(_("No given url"))
if self.pyload.debug:
self.log_debug("LOAD URL " + url,
diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py
index 6a3f91a5b..d348f92e2 100644
--- a/module/plugins/internal/SimpleCrypter.py
+++ b/module/plugins/internal/SimpleCrypter.py
@@ -10,11 +10,11 @@ from module.utils import fixup, html_unescape
class SimpleCrypter(Crypter, SimpleHoster):
__name__ = "SimpleCrypter"
__type__ = "crypter"
- __version__ = "0.60"
+ __version__ = "0.61"
__status__ = "testing"
__pattern__ = r'^unmatchable$'
- __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package']
+ __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True),
("subfolder_per_pack", "bool", "Create a subfolder for each package", True)]
__description__ = """Simple decrypter plugin"""
@@ -91,6 +91,7 @@ class SimpleCrypter(Crypter, SimpleHoster):
def decrypt(self, pyfile):
+ self.links = [] #@TODO: Recheck in 0.4.10
self.prepare()
self.check_info() #@TODO: Remove in 0.4.10
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
index 69f88081a..89af22c87 100644
--- a/module/plugins/internal/SimpleHoster.py
+++ b/module/plugins/internal/SimpleHoster.py
@@ -11,7 +11,7 @@ from module.PyFile import statusMap as _statusMap
from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getURL as get_url
from module.plugins.internal.Hoster import Hoster, create_getInfo, parse_fileInfo
-from module.plugins.internal.Plugin import Fail, encode, fixurl, replace_patterns, seconds_to_midnight, set_cookie, set_cookies
+from module.plugins.internal.Plugin import Fail, encode, fixurl, fixname, replace_patterns, seconds_to_midnight, set_cookie, set_cookies
from module.utils import fixup, fs_encode, parseFileSize as parse_size
@@ -22,12 +22,13 @@ statusMap = dict((v, k) for k, v in _statusMap.items())
class SimpleHoster(Hoster):
__name__ = "SimpleHoster"
__type__ = "hoster"
- __version__ = "1.81"
+ __version__ = "1.82"
__status__ = "testing"
__pattern__ = r'^unmatchable$'
- __config__ = [("use_premium", "bool", "Use premium account if available" , True),
- ("fallback" , "bool", "Fallback to free download if premium fails", True)]
+ __config__ = [("use_premium" , "bool", "Use premium account if available" , True),
+ ("premium_fallback", "bool", "Fallback to free download if premium fails", True),
+ ("chk_filesize" , "bool", "Check file size" , True)]
__description__ = """Simple hoster plugin"""
__license__ = "GPLv3"
@@ -174,7 +175,8 @@ class SimpleHoster(Hoster):
info['status'] = 2
if 'N' in info['pattern']:
- info['name'] = replace_patterns(fixurl(info['pattern']['N']),
+ name = fixname(info['pattern']['N'])
+ info['name'] = replace_patterns(fixurl(name),
cls.NAME_REPLACEMENTS)
if 'S' in info['pattern']:
@@ -294,7 +296,7 @@ class SimpleHoster(Hoster):
self.check_file()
except Fail, e: #@TODO: Move to PluginThread in 0.4.10
- if self.get_config('fallback', True) and self.premium:
+ if self.get_config('premium_fallback', True) and self.premium:
self.log_warning(_("Premium download failed"), e)
self.restart(nopremium=True)
@@ -309,15 +311,16 @@ class SimpleHoster(Hoster):
self.captcha.invalid()
self.retry(10, reason=_("Wrong captcha"))
- # 10485760 is 10MB, tolerance is used when comparing displayed size on the hoster website to real size
- # For example displayed size can be 1.46GB for example, but real size can be 1.4649853GB
elif self.check_download({'Empty file': re.compile(r'\A((.|)(\2|\s)*)\Z')},
- file_size=self.info['size'] if 'size' in self.info else 0,
- size_tolerance=10485760,
- delete=False): #@TODO: Make `delete` settable in 0.4.10
+ delete=True):
self.error(_("Empty file"))
else:
+ if self.get_config('chk_filesize', False) and 'size' in self.info:
+ # 10485760 is 10MB, tolerance is used when comparing displayed size on the hoster website to real size
+ # For example displayed size can be 1.46GB for example, but real size can be 1.4649853GB
+ self.check_filesize(self.info['size'], size_tolerance=10485760)
+
self.log_debug("Using default check rules...")
for r, p in self.FILE_ERRORS:
errmsg = self.check_download({r: re.compile(p)})
@@ -340,7 +343,7 @@ class SimpleHoster(Hoster):
self.check_errors()
self.log_info(_("No errors found"))
- self.pyfile.error = ""
+ self.pyfile.error = "" #@TODO: Recheck in 0.4.10
def check_errors(self):
diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py
index 5a4cc35fb..3f2158a0b 100644
--- a/module/plugins/internal/XFSAccount.py
+++ b/module/plugins/internal/XFSAccount.py
@@ -4,6 +4,7 @@ import re
import time
import urlparse
+from module.common.json_layer import json_loads
from module.plugins.internal.Account import Account
from module.plugins.internal.Plugin import parse_html_form, set_cookie
@@ -11,7 +12,7 @@ from module.plugins.internal.Plugin import parse_html_form, set_cookie
class XFSAccount(Account):
__name__ = "XFSAccount"
__type__ = "account"
- __version__ = "0.43"
+ __version__ = "0.44"
__status__ = "testing"
__description__ = """XFileSharing account plugin"""
@@ -174,5 +175,13 @@ class XFSAccount(Account):
html = self.load(url, post=inputs, cookies=self.COOKIES)
- if re.search(self.LOGIN_FAIL_PATTERN, html):
- self.login_fail()
+ try:
+ json = json_loads(html)
+
+ except ValueError:
+ if re.search(self.LOGIN_FAIL_PATTERN, html):
+ self.login_fail()
+
+ else:
+ if not 'success' in json or not json['success']:
+ self.login_fail()