diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..df5f5e852f --- /dev/null +++ b/.gitignore @@ -0,0 +1,211 @@ +# https://raw.githubusercontent.com/github/gitignore/master/Global/Archives.gitignore + +# It's better to unpack these files and commit the raw source because +# git has its own built in compression methods. +*.7z +*.jar +*.rar +*.zip +*.gz +*.tgz +*.bzip +*.bz2 +*.xz +*.lzma +*.cab + +# Packing-only formats +*.iso +*.tar + +# Package management formats +*.dmg +*.xpi +*.gem +*.egg +*.deb +*.rpm +*.msi +*.msm +*.msp + + +# https://raw.githubusercontent.com/github/gitignore/master/Global/Linux.gitignore + +*~ + +# Temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + + +# https://raw.githubusercontent.com/github/gitignore/master/Global/Windows.gitignore + +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +# https://raw.githubusercontent.com/github/gitignore/master/Global/macOS.gitignore + +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +# https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +# TODO: Activate this rule when dependencies are not handled in this repo anymore +#lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# TODO: Activate these rules when translations are not handled in this repo anymore +# Translations +#*.mo +#*.po +#*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# PyCharm +.idea/ diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 1215b241de..0000000000 --- a/.hgignore +++ /dev/null @@ -1,36 +0,0 @@ -# ignoreing unneeded files, using glob syntax -syntax: glob -*.pyc -*~ -*.pidaproject -.svn -*.DS_Store -*.egg-info -*.project -*.pydevproject -Downloads/* -container/* -Logs/* -docs/module/ -docs/_build -module/plugins/container/DLC_*.py -failed_links.txt -module/config/gui.xml -module/config/core.xml -module/config/plugin.xml -links.txt -ssl.crt -ssl.key -cert.pem -module/web/pyload.db -*.svg -*.prefs -*.po -*.orig -*.rej -pyload/* -dist/* -build/* -setup.py -paver-minilib.zip -env/* diff --git a/LICENSE b/LICENSE.MD similarity index 100% rename from LICENSE rename to LICENSE.MD diff --git a/README b/README deleted file mode 100644 index 7f3c4f4c83..0000000000 --- a/README +++ /dev/null @@ -1,89 +0,0 @@ - -Description -=========== - -pyLoad is a free and open source downloader for 1-click-hosting sites -like rapidshare.com or uploaded.to. -It supports link decryption as well as all important container formats. - -pyLoad is written entirely in Python and is currently under heavy development. - -For news, downloads, wiki, forum and further information visit http://pyload.org/ - -To report bugs, suggest features, ask a question, get the developer version -or help us out, visit http://bitbucket.org/spoob/pyload/ - -Documentation about extending pyLoad can be found at http://docs.pyload.org or join us at #pyload on irc.freenode.net - -Dependencies -============ - -You need at least python 2.5 to run pyLoad and all of these required libaries. -They should be automatically installed when using pip install. -The prebuilt pyload packages also install these dependencies or have them included, so manuall install -is only needed when installing pyLoad from source. - -Required --------- - -- pycurl a.k.a python-curl -- jinja2 -- beaker -- thrift -- simplejson (for python 2.5) - -Some plugins require additional packages, only install these when needed. - -Optional --------- - -- pycrypto: RSDF/CCF/DLC support -- tesseract, python-pil a.k.a python-imaging: Automatic captcha recognition for a small amount of plugins -- jsengine (spidermonkey, ossp-js, pyv8, rhino): Used for several hoster, ClickNLoad -- feedparser -- BeautifulSoup -- pyOpenSSL: For SSL connection - -First start -=========== - -Note: If you installed pyload via package-manager `python pyLoadCore.py` is probably equivalent to `pyLoadCore` - -Run:: - - python pyLoadCore.py - -and follow the instructions of the setup assistent. - -For a list of options use:: - - python pyLoadCore.py -h - -Configuration -============= - -After finishing the setup assistent pyLoad is ready to use and more configuration can be done via webinterface. -Additionally you could simply edit the config files located in your pyLoad home dir (defaults to: ~/.pyload) -with your favorite editor and edit the appropriate options. For a short description of -the options take a look at http://pyload.org/configuration. - -To restart the configure assistent run:: - - python pyLoadCore.py -s - -Adding downloads ----------------- - -To start the CLI and connect to a local server, run:: - - python pyLoadCli.py -l - -for more options refer to:: - - python pyLoadCli.py -h - -The webinterface can be accessed when pointing your webbrowser to the ip and configured port, defaults to http://localhost:8000 - -Notes -===== -For more information, see http://pyload.org/ diff --git a/README.MD b/README.MD new file mode 100644 index 0000000000..2e588f2e6d --- /dev/null +++ b/README.MD @@ -0,0 +1,87 @@ +# ⚠️ Important: This Branch is Deprecated + +pyLoad v0.4.x has reached **end-of-life**. +There will be **no further updates, bug fixes, or new features** here. +Python 2.x has been deprecated for over 6 years, yet pyLoad continued to support it until now. It's time to move on. + +# **please migrate to [pyLoad-ng](https://github.com/pyload/pyload/tree/main) (v0.5.x).** +
%s\n' % repr(e) - err += '
%s\n' % format_exc(10) - environ['wsgi.errors'].write(err) #TODO: wsgi.error should not get html - start_response('500 INTERNAL SERVER ERROR', [('Content-Type', 'text/html')]) + err += '
\n%s\n\n' \ + '
\n%s\n\n' \ + % (html_escape(repr(_e())), html_escape(format_exc())) + environ['wsgi.errors'].write(err) + headers = [('Content-Type', 'text/html; charset=UTF-8')] + start_response('500 INTERNAL SERVER ERROR', headers, sys.exc_info()) return [tob(err)] def __call__(self, environ, start_response): @@ -851,20 +993,41 @@ def __call__(self, environ, start_response): # HTTP and WSGI Tools ########################################################## ############################################################################### - -class BaseRequest(DictMixin): +class BaseRequest(object): """ A wrapper for WSGI environment dictionaries that adds a lot of - convenient access methods and properties. Most of them are read-only.""" + convenient access methods and properties. Most of them are read-only. + + Adding new attributes to a request actually adds them to the environ + dictionary (as 'bottle.request.ext.
Sorry, the requested URL {{repr(request.url)}} caused an error:
-{{e.output}}
- %if DEBUG and e.exception:
+ {{e.body}}
+ %%if DEBUG and e.exception:
{{repr(e.exception)}}
- %end
- %if DEBUG and e.traceback:
+ %%end
+ %%if DEBUG and e.traceback:
{{e.traceback}}
- %end
+ %%end
-%except ImportError:
+%%except ImportError:
ImportError: Could not generate the error page. Please add bottle to
the import path.
-%end
-"""
+%%end
+""" % __name__
-#: A thread-safe instance of :class:`Request` representing the `current` request.
-request = Request()
+#: A thread-safe instance of :class:`LocalRequest`. If accessed from within a
+#: request callback, this instance always refers to the *current* request
+#: (even on a multithreaded server).
+request = LocalRequest()
-#: A thread-safe instance of :class:`Response` used to build the HTTP response.
-response = Response()
+#: A thread-safe instance of :class:`LocalResponse`. It is used to change the
+#: HTTP response for the *current* request.
+response = LocalResponse()
#: A thread-safe namespace. Not used by Bottle.
local = threading.local()
@@ -2894,29 +3742,30 @@ def wrapper(*args, **kwargs):
#: A virtual package that redirects import statements.
#: Example: ``import bottle.ext.sqlite`` actually imports `bottle_sqlite`.
-ext = _ImportRedirect(__name__+'.ext', 'bottle_%s').module
+ext = _ImportRedirect('bottle.ext' if __name__ == '__main__' else __name__+".ext", 'bottle_%s').module
if __name__ == '__main__':
opt, args, parser = _cmd_options, _cmd_args, _cmd_parser
if opt.version:
- print 'Bottle', __version__; sys.exit(0)
+ _stdout('Bottle %s\n'%__version__)
+ sys.exit(0)
if not args:
parser.print_help()
- print '\nError: No application specified.\n'
+ _stderr('\nError: No application specified.\n')
sys.exit(1)
- try:
- sys.path.insert(0, '.')
- sys.modules.setdefault('bottle', sys.modules['__main__'])
- except (AttributeError, ImportError), e:
- parser.error(e.args[0])
+ sys.path.insert(0, '.')
+ sys.modules.setdefault('bottle', sys.modules['__main__'])
+
+ host, port = (opt.bind or 'localhost'), 8080
+ if ':' in host and host.rfind(']') < host.rfind(':'):
+ host, port = host.rsplit(':', 1)
+ host = host.strip('[]')
+
+ run(args[0], host=host, port=int(port), server=opt.server,
+ reloader=opt.reload, plugins=opt.plugin, debug=opt.debug)
+
- if opt.bind and ':' in opt.bind:
- host, port = opt.bind.rsplit(':', 1)
- else:
- host, port = (opt.bind or 'localhost'), 8080
- debug(opt.debug)
- run(args[0], host=host, port=port, server=opt.server, reloader=opt.reload, plugins=opt.plugin)
# THE END
diff --git a/module/lib/wsgiserver/LICENSE.txt b/module/lib/wsgiserver/LICENSE.txt
index a15165ee26..23c7d09635 100644
--- a/module/lib/wsgiserver/LICENSE.txt
+++ b/module/lib/wsgiserver/LICENSE.txt
@@ -1,22 +1,27 @@
-Copyright (c) 2004-2007, CherryPy Team (team@cherrypy.org)
-All rights reserved.
+**Copyright © 2004-2017, CherryPy Team (team@cherrypy.org)**
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
+**All rights reserved.**
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the CherryPy Team nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+* * *
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of CherryPy nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
diff --git a/module/lib/wsgiserver/__init__.py b/module/lib/wsgiserver/__init__.py
index c380e18b05..e6e48a6c1f 100644
--- a/module/lib/wsgiserver/__init__.py
+++ b/module/lib/wsgiserver/__init__.py
@@ -1,1794 +1,13 @@
-"""A high-speed, production ready, thread pooled, generic WSGI server.
-
-Simplest example on how to use this module directly
-(without using CherryPy's application machinery):
-
- from cherrypy import wsgiserver
-
- def my_crazy_app(environ, start_response):
- status = '200 OK'
- response_headers = [('Content-type','text/plain')]
- start_response(status, response_headers)
- return ['Hello world!\n']
-
- server = wsgiserver.CherryPyWSGIServer(
- ('0.0.0.0', 8070), my_crazy_app,
- server_name='www.cherrypy.example')
-
-The CherryPy WSGI server can serve as many WSGI applications
-as you want in one instance by using a WSGIPathInfoDispatcher:
-
- d = WSGIPathInfoDispatcher({'/': my_crazy_app, '/blog': my_blog_app})
- server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 80), d)
-
-Want SSL support? Just set these attributes:
-
- server.ssl_certificate = ', '').replace('', '')
- self.logDebug('Account Info API data: ' + api_data)
- api_data = json_loads(api_data)
-
- if api_data['status'] != 'OK': # 'status' must be always OK for a working account
- return {"premium": False, "valid": False}
-
- if api_data['account_type'] == 'REGISTERED':
- premium = False
- validuntil = None
- else:
- premium = True
- validuntil = int(mktime(strptime(api_data['premium_expire'], "%Y-%m-%d %H:%M:%S")))
-
- if api_data['usr_bandwidth_available'] == 'UNLIMITED':
- trafficleft = -1
- else:
- trafficleft = parseFileSize(api_data['usr_bandwidth_available']) / 1024
-
- return {"premium": premium, "validuntil": validuntil, "trafficleft": trafficleft}
diff --git a/module/plugins/accounts/DdownloadCom.py b/module/plugins/accounts/DdownloadCom.py
new file mode 100644
index 0000000000..0e22348205
--- /dev/null
+++ b/module/plugins/accounts/DdownloadCom.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+import pycurl
+
+from ..internal.XFSAccount import XFSAccount
+
+
+class DdownloadCom(XFSAccount):
+ __name__ = "DdownloadCom"
+ __type__ = "account"
+ __version__ = "0.09"
+ __status__ = "testing"
+
+ __description__ = """Ddownload.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+ PLUGIN_DOMAIN = "ddownload.com"
+ PLUGIN_URL = "http://ddownload.com"
+
+ PREMIUM_PATTERN = r">Premium Member<"
+ TRAFFIC_LEFT_PATTERN = r'available[^/]*) / Traffic left: (?P
'
-
- def loadAccountInfo(self, user, req):
- html = req.load("http://egofiles.com")
- if 'You are logged as a Free User' in html:
- return {"premium": False, "validuntil": None, "trafficleft": None}
-
- m = re.search(self.PREMIUM_ACCOUNT_PATTERN, html)
- if m:
- validuntil = int(time.mktime(time.strptime(m.group('P'), "%Y-%m-%d %H:%M:%S")))
- trafficleft = parseFileSize(m.group('T'), m.group('U')) / 1024
- return {"premium": True, "validuntil": validuntil, "trafficleft": trafficleft}
- else:
- self.logError('Unable to retrieve account information - Plugin may be out of date')
-
- def login(self, user, data, req):
- # Set English language
- req.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True)
-
- html = req.load("http://egofiles.com/ajax/register.php",
- post={"log": 1,
- "loginV": user,
- "passV": data["password"]})
- if 'Login successful' not in html:
- self.wrongPassword()
diff --git a/module/plugins/accounts/EuroshareEu.py b/module/plugins/accounts/EuroshareEu.py
index 830c1db3f5..f1f88d43b0 100644
--- a/module/plugins/accounts/EuroshareEu.py
+++ b/module/plugins/accounts/EuroshareEu.py
@@ -1,56 +1,54 @@
# -*- 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
| (\d+|\d\d\.\d\d\.) | ' - def loadAccountInfo(self, user, req): - self.relogin(user) - html = req.load("http://www.hellshare.com/") + def grab_info(self, user, password, data): + html = self.load("http://www.hellshare.com/") - found = re.search(self.CREDIT_LEFT_PATTERN, html) - if found is None: + m = re.search(self.CREDIT_LEFT_PATTERN, html) + if m is None: trafficleft = None validuntil = None premium = False else: - credit = found.group(1) + credit = m.group(1) premium = True try: if "." in credit: - #Time-based account + #: Time-based account vt = [int(x) for x in credit.split('.')[:2]] lt = time.localtime() - year = lt.tm_year + int(vt[1] < lt.tm_mon or (vt[1] == lt.tm_mon and vt[0] < lt.tm_mday)) - validuntil = time.mktime(time.strptime("%s%d 23:59:59" % (credit, year), "%d.%m.%Y %H:%M:%S")) + year = lt.tm_year + \ + int(vt[1] < lt.tm_mon or ( + vt[1] == lt.tm_mon and vt[0] < lt.tm_mday)) + validuntil = time.mktime( + time.strptime( + "%s%d 23:59:59" % + (credit, year), "%d.%m.%Y %H:%M:%S")) trafficleft = -1 else: - #Traffic-based account - trafficleft = int(credit) * 1024 + #: Traffic-based account + trafficleft = self.parse_traffic(credit, "MB") validuntil = -1 + except Exception, e: - self.logError('Unable to parse credit info', e) + self.log_error(_("Unable to parse credit info"), e) validuntil = -1 trafficleft = -1 - return {"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium} + return {'validuntil': validuntil, + 'trafficleft': trafficleft, 'premium': premium} + + def signin(self, user, password, data): + html = self.load('http://www.hellshare.com/') + if self.req.lastEffectiveURL != 'http://www.hellshare.com/': + #: Switch to English + self.log_debug("Switch lang - URL: %s" % self.req.lastEffectiveURL) + + json = self.load( + "%s?do=locRouter-show" % + self.req.lastEffectiveURL) + hash = re.search(r'(--[0-9a-f]+\-)', json).group(1) + + self.log_debug("Switch lang - HASH: %s" % hash) - def login(self, user, data, req): - html = req.load('http://www.hellshare.com/') - if req.lastEffectiveURL != 'http://www.hellshare.com/': - #Switch to English - self.logDebug('Switch lang - URL: %s' % req.lastEffectiveURL) - json = req.load("%s?do=locRouter-show" % req.lastEffectiveURL) - hash = re.search(r"(--[0-9a-f]+-)", json).group(1) - self.logDebug('Switch lang - HASH: %s' % hash) - html = req.load('http://www.hellshare.com/%s/' % hash) + html = self.load('http://www.hellshare.com/%s/' % hash) if re.search(self.CREDIT_LEFT_PATTERN, html): - self.logDebug('Already logged in') + self.log_debug("Already logged in") return - html = req.load('http://www.hellshare.com/login?do=loginForm-submit', post={ - "login": "Log in", - "password": data["password"], - "username": user, - "perm_login": "on" - }) + html = self.load("https://www.hellshare.com/login", + get={'do': "loginForm-submit"}, + post={'login': "Log in", + 'password': password, + 'username': user, + 'perm_login': "on"}) if "Premium Pro account expire | (.+?)<"
+ TRAFFIC_LEFT_PATTERN = r"Traffic available today.*?\s*(?P| Max. počet paralelních stahování: | (\d+)'
+ VALID_UNTIL_PATTERN = ur' | Paušální stahování aktivní. Vyprší | (.*?)'
+ TRAFFIC_LEFT_PATTERN = r' | Kredit | (.*?) GiB'
+
+ def grab_info(self, user, password, data):
+ htmll = self.load("http://megarapid.cz/mujucet/")
+
+ m = re.search(self.LIMITDL_PATTERN, htmll)
+ if m is not None:
+ data['options']['limitDL'] = [int(m.group(1))]
+
+ m = re.search(self.VALID_UNTIL_PATTERN, htmll)
+ if m is not None:
+ validuntil = time.mktime(
+ time.strptime(
+ m.group(1),
+ "%d.%m.%Y - %H:%M"))
+ return {'premium': True, 'trafficleft': -
+ 1, 'validuntil': validuntil}
+
+ m = re.search(self.TRAFFIC_LEFT_PATTERN, htmll)
+ if m is not None:
+ trafficleft = float(m.group(1)) * 1024 ** 3
+ return {'premium': True, 'trafficleft': trafficleft, 'validuntil': -1}
+
+ return {'premium': False, 'trafficleft': None, 'validuntil': None}
+
+ def signin(self, user, password, data):
+ html = self.load("http://megarapid.cz/prihlaseni/")
+
+ if "Heslo:" in html:
+ start = html.index('id="inp_hash" name="hash" value="')
+ html = html[start + 33:]
+ hashes = html[0:32]
+ html = self.load("https://megarapid.cz/prihlaseni/",
+ post={'hash': hashes,
+ 'login': user,
+ 'pass1': password,
+ 'remember': 1,
+ 'sbmt': u"Přihlásit"})
diff --git a/module/plugins/accounts/MegaRapidoNet.py b/module/plugins/accounts/MegaRapidoNet.py
new file mode 100644
index 0000000000..0e579e371f
--- /dev/null
+++ b/module/plugins/accounts/MegaRapidoNet.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+from ..internal.MultiAccount import MultiAccount
+
+
+class MegaRapidoNet(MultiAccount):
+ __name__ = "MegaRapidoNet"
+ __type__ = "account"
+ __version__ = "0.10"
+ __status__ = "testing"
+
+ __config__ = [("mh_mode", "all;listed;unlisted", "Filter hosters to use", "all"),
+ ("mh_list", "str", "Hoster list (comma separated)", ""),
+ ("mh_interval", "int", "Reload interval in hours", 12)]
+
+ __description__ = """MegaRapido.net account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
+
+ VALID_UNTIL_PATTERN = r'<\s*?div[^>]*?class\s*?=\s*?[\'"]premium_index[\'"].*?>[^<]*?<[^>]*?b.*?>\s*?TEMPO\s*?PREMIUM.*?<[^>]*?/b.*?>\s*?(\d*)[^\d]*?DIAS[^\d]*?(\d*)[^\d]*?HORAS[^\d]*?(\d*)[^\d]*?MINUTOS[^\d]*?(\d*)[^\d]*?SEGUNDOS'
+ USER_ID_PATTERN = r'<\s*?div[^>]*?class\s*?=\s*?["\']checkbox_compartilhar["\'].*?>.*?<\s*?input[^>]*?name\s*?=\s*?["\']usar["\'].*?>.*?<\s*?input[^>]*?name\s*?=\s*?["\']user["\'][^>]*?value\s*?=\s*?["\'](.*?)\s*?["\']'
+
+ def grab_hosters(self, user, password, data):
+ hosters = {'1fichier': [], # leave it there are so many possible addresses?
+ '1st-files': ['1st-files.com'],
+ '2shared': ['2shared.com'],
+ '4shared': ['4shared.com', '4shared-china.com'],
+ 'asfile': ['http://asfile.com/'],
+ 'bitshare': ['bitshare.com'],
+ 'brupload': ['brupload.net'],
+ 'crocko': ['crocko.com', 'easy-share.com'],
+ 'dailymotion': ['dailymotion.com'],
+ 'depfile': ['depfile.com'],
+ 'depositfiles': ['depositfiles.com', 'dfiles.eu'],
+ 'dizzcloud': ['dizzcloud.com'],
+ 'dl.dropbox': [],
+ 'extabit': ['extabit.com'],
+ 'extmatrix': ['extmatrix.com'],
+ 'facebook': [],
+ 'file4go': ['file4go.com'],
+ 'filecloud': ['filecloud.io', 'ifile.it', 'mihd.net'],
+ 'filefactory': ['filefactory.com'],
+ 'fileom': ['fileom.com'],
+ 'fileparadox': ['fileparadox.in'],
+ 'filepost': ['filepost.com', 'fp.io'],
+ 'filerio': ['filerio.in', 'filerio.com', 'filekeen.com'],
+ 'filesflash': ['filesflash.com'],
+ 'firedrive': ['firedrive.com', 'putlocker.com'],
+ 'flashx': [],
+ 'freakshare': ['freakshare.net', 'freakshare.com'],
+ 'gigasize': ['gigasize.com'],
+ 'hipfile': ['hipfile.com'],
+ 'junocloud': ['junocloud.me'],
+ 'letitbit': ['letitbit.net', 'shareflare.net'],
+ 'mediafire': ['mediafire.com'],
+ 'mega': ['mega.co.nz'],
+ 'megashares': ['megashares.com'],
+ 'metacafe': ['metacafe.com'],
+ 'netload': ['netload.in'],
+ 'oboom': ['oboom.com'],
+ 'rapidgator': ['rapidgator.net'],
+ 'rapidshare': ['rapidshare.com'],
+ 'rarefile': ['rarefile.net'],
+ 'ryushare': ['ryushare.com'],
+ 'sendspace': ['sendspace.com'],
+ 'turbobit': ['turbobit.net', 'unextfiles.com'],
+ 'uploadable': ['uploadable.ch'],
+ 'uploadbaz': ['uploadbaz.com'],
+ 'uploaded': ['uploaded.to', 'uploaded.net', 'ul.to'],
+ 'uploadhero': ['uploadhero.com'],
+ 'uploading': ['uploading.com'],
+ 'uptobox': ['uptobox.com'],
+ 'xvideos': ['xvideos.com'],
+ 'youtube': ['youtube.com']}
+
+ hoster_list = []
+
+ for item in hosters.values():
+ hoster_list.extend(item)
+
+ return hoster_list
+
+ def grab_info(self, user, password, data):
+ validuntil = None
+ trafficleft = None
+ premium = False
+
+ html = self.load("http://megarapido.net/gerador")
+
+ validuntil = re.search(self.VALID_UNTIL_PATTERN, html)
+ if validuntil:
+ #: Hier weitermachen!!! (müssen umbedingt die zeit richtig machen damit! (sollte aber möglich))
+ validuntil = time.time() + int(validuntil.group(1)) * 24 * 3600 + int(validuntil.group(2)
+ ) * 3600 + int(validuntil.group(3)) * 60 + int(validuntil.group(4))
+ trafficleft = -1
+ premium = True
+
+ return {'validuntil': validuntil,
+ 'trafficleft': trafficleft,
+ 'premium': premium}
+
+ def signin(self, user, password, data):
+ self.load("http://megarapido.net/login")
+ self.load("http://megarapido.net/painel_user/ajax/logar.php",
+ post={'login': user,
+ 'senha': password})
+
+ html = self.load("http://megarapido.net/gerador")
+
+ if "sair" not in html.lower():
+ self.fail_login()
+ else:
+ m = re.search(self.USER_ID_PATTERN, html)
+ if m is not None:
+ data['uid'] = m.group(1)
+ else:
+ self.fail_login("Couldn't find the user ID")
diff --git a/module/plugins/accounts/MegasharesCom.py b/module/plugins/accounts/MegasharesCom.py
index e7d5f9ca91..20fe59d68a 100644
--- a/module/plugins/accounts/MegasharesCom.py
+++ b/module/plugins/accounts/MegasharesCom.py
@@ -1,44 +1,46 @@
# -*- coding: utf-8 -*-
import re
-from time import mktime, strptime
+import time
-from module.plugins.Account import Account
+from ..internal.Account import Account
class MegasharesCom(Account):
__name__ = "MegasharesCom"
- __version__ = "0.02"
__type__ = "account"
- __description__ = """megashares.com account plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
+ __version__ = "0.11"
+ __status__ = "testing"
+
+ __description__ = """Megashares.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
VALID_UNTIL_PATTERN = r' | \s*Period Ends: (\w{3} \d{1,2}, \d{4}) ' - def loadAccountInfo(self, user, req): - #self.relogin(user) - html = req.load("http://d01.megashares.com/myms.php", decode=True) + def grab_info(self, user, password, data): + html = self.load("http://d01.megashares.com/myms.php") premium = False if '>Premium Upgrade<' in html else True validuntil = trafficleft = -1 try: timestr = re.search(self.VALID_UNTIL_PATTERN, html).group(1) - self.logDebug(timestr) - validuntil = mktime(strptime(timestr, "%b %d, %Y")) + self.log_debug(timestr) + validuntil = time.mktime(time.strptime(timestr, "%b %d, %Y")) + except Exception, e: - self.logError(e) + self.log_error(e, trace=True) - return {"validuntil": validuntil, "trafficleft": -1, "premium": premium} + return {'validuntil': validuntil, + 'trafficleft': -1, 'premium': premium} - def login(self, user, data, req): - html = req.load('http://d01.megashares.com/myms_login.php', post={ - "httpref": "", - "myms_login": "Login", - "mymslogin_name": user, - "mymspassword": data['password'] - }, decode=True) + def signin(self, user, password, data): + html = self.load('http://d01.megashares.com/myms_login.php', + post={'httpref': "", + 'myms_login': "Login", + 'mymslogin_name': user, + 'mymspassword': password}) if not '%s' % user in html: - self.wrongPassword() + self.fail_login() diff --git a/module/plugins/accounts/MovReelCom.py b/module/plugins/accounts/MovReelCom.py new file mode 100644 index 0000000000..6837f03aa1 --- /dev/null +++ b/module/plugins/accounts/MovReelCom.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +from ..internal.XFSAccount import XFSAccount + + +class MovReelCom(XFSAccount): + __name__ = "MovReelCom" + __type__ = "account" + __version__ = "0.08" + __status__ = "testing" + + __description__ = """Movreel.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")] + + login_timeout = 60 + info_threshold = 30 + + PLUGIN_DOMAIN = "movreel.com" diff --git a/module/plugins/accounts/Mp4uploadCom.py b/module/plugins/accounts/Mp4uploadCom.py new file mode 100644 index 0000000000..26648239a1 --- /dev/null +++ b/module/plugins/accounts/Mp4uploadCom.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +from ..internal.XFSAccount import XFSAccount + + +class Mp4uploadCom(XFSAccount): + __name__ = "Mp4uploadCom" + __type__ = "account" + __version__ = "0.01" + __status__ = "testing" + + __description__ = """Mp4upload.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")] + + PLUGIN_DOMAIN = "mp4upload.com" + LOGIN_URL = "https://www.mp4upload.com/login" + LOGIN_SKIP_PATTERN = r"https://www\.mp4upload\.com/logout/" + PREMIUM_PATTERN = r">Premium Account" + VALID_UNTIL_PATTERN = r"Premium expiration:.*?>(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})" + VALID_UNTIL_FORMAT = "%Y-%m-%d %H:%M:%S" diff --git a/module/plugins/accounts/MultiDebridCom.py b/module/plugins/accounts/MultiDebridCom.py deleted file mode 100644 index 904be5ee76..0000000000 --- a/module/plugins/accounts/MultiDebridCom.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- 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' in html:
- self.wrongPassword()
\ No newline at end of file
+ if 'err' in api_data:
+ self.fail_login(api_data['err'])
diff --git a/module/plugins/accounts/MyfastfileCom.py b/module/plugins/accounts/MyfastfileCom.py
new file mode 100644
index 0000000000..308eac78ee
--- /dev/null
+++ b/module/plugins/accounts/MyfastfileCom.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+import time
+
+from ..internal.misc import json
+from ..internal.MultiAccount import MultiAccount
+
+
+class MyfastfileCom(MultiAccount):
+ __name__ = "MyfastfileCom"
+ __type__ = "account"
+ __version__ = "0.12"
+ __status__ = "testing"
+
+ __config__ = [("mh_mode", "all;listed;unlisted", "Filter hosters to use", "all"),
+ ("mh_list", "str", "Hoster list (comma separated)", ""),
+ ("mh_interval", "int", "Reload interval in hours", 12)]
+
+ __description__ = """Myfastfile.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+ def grab_hosters(self, user, password, data):
+ json_data = self.load(
+ "http://myfastfile.com/api.php",
+ get={
+ 'hosts': ""})
+ self.log_debug("JSON data", json_data)
+ json_data = json.loads(json_data)
+
+ return json_data['hosts']
+
+ def grab_info(self, user, password, data):
+ if 'days_left' in self.json_data:
+ validuntil = time.time() + \
+ self.json_data['days_left'] * 24 * 60 * 60
+ return {'premium': True, 'validuntil': validuntil, 'trafficleft': -1}
+ else:
+ self.log_error(_("Unable to get account information"))
+
+ def signin(self, user, password, data):
+ #: Password to use is the API-Password written in http://myfastfile.com/myaccount
+ html = self.load("https://myfastfile.com/api.php",
+ get={'user': user,
+ 'pass': password})
+
+ self.log_debug("JSON data: " + html)
+
+ self.json_data = json.loads(html)
+ if self.json_data['status'] != 'ok':
+ self.fail_login(_("Invalid username or password"))
diff --git a/module/plugins/accounts/NetloadIn.py b/module/plugins/accounts/NetloadIn.py
deleted file mode 100755
index 3e3bd93c14..0000000000
--- a/module/plugins/accounts/NetloadIn.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- 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 (?P | "
diff --git a/module/plugins/accounts/NowVideoSx.py b/module/plugins/accounts/NowVideoSx.py
new file mode 100644
index 0000000000..ff2c842f6d
--- /dev/null
+++ b/module/plugins/accounts/NowVideoSx.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+from ..internal.Account import Account
+
+
+class NowVideoSx(Account):
+ __name__ = "NowVideoSx"
+ __type__ = "account"
+ __version__ = "0.11"
+ __status__ = "testing"
+
+ __description__ = """NowVideo.at account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+ VALID_UNTIL_PATTERN = r'>Your premium membership expires on: (.+?)<'
+
+ def grab_info(self, user, password, data):
+ validuntil = None
+ trafficleft = -1
+ premium = None
+
+ html = self.load("http://www.nowvideo.sx/premium.php")
+
+ m = re.search(self.VALID_UNTIL_PATTERN, html)
+ if m is not None:
+ expiredate = m.group(1).strip()
+ self.log_debug("Expire date: " + expiredate)
+
+ try:
+ validuntil = time.mktime(time.strptime(expiredate, "%Y-%b-%d"))
+
+ except Exception, e:
+ self.log_error(e, trace=True)
+
+ else:
+ if validuntil > time.mktime(time.gmtime()):
+ premium = True
+ else:
+ premium = False
+ validuntil = -1
+
+ return {'validuntil': validuntil,
+ 'trafficleft': trafficleft, 'premium': premium}
+
+ def signin(self, user, password, data):
+ html = self.load("http://www.nowvideo.sx/login.php",
+ post={'user': user,
+ 'pass': password})
+
+ if re.search(r'>Log In<', html):
+ self.fail_login()
diff --git a/module/plugins/accounts/OboomIo.py b/module/plugins/accounts/OboomIo.py
new file mode 100644
index 0000000000..aa39340258
--- /dev/null
+++ b/module/plugins/accounts/OboomIo.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+from ..internal.Account import Account
+from ..internal.misc import json
+
+
+class OboomIo(Account):
+ __name__ = "OboomIo"
+ __type__ = "account"
+ __version__ = "0.01"
+ __status__ = "testing"
+
+ __description__ = """Oboom.io account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+ PREMIUM_PATTERN = r">Plan Elite"
+ VALID_UNTIL_PATTERN = r'fa-calendar-star">\s*([\d\w,\.: ]+)'
+
+ def grab_info(self, user, password, data):
+ html = self.load("https://oboom.io/dashboard")
+
+ premium = re.search(self.PREMIUM_PATTERN, html) is not None
+
+ validuntil = None
+ m = re.search(self.VALID_UNTIL_PATTERN, html)
+ if m is not None:
+ validuntil = time.mktime(time.strptime(m.group(1).strip(), "%d %b %Y, %H:%M"))
+
+ else:
+ self.log_error(self._("VALID_UNTIL_PATTERN not found"))
+
+ return {"validuntil": validuntil, "trafficleft": -1, "premium": premium}
+
+ def signin(self, user, password, data):
+ html = self.load("https://oboom.io/dashboard")
+ if 'href="/logout"' in html:
+ self.skip_login()
+
+ html = self.load(
+ "https://oboom.io/api/1.0/apiGetUserLogin/",
+ post={
+ "email": user,
+ "pass": password,
+ "re": "0"
+ }
+ )
+ json_data = json.loads(html)
+ if json_data.get("message") != "successUserLogin":
+ self.fail_login()
diff --git a/module/plugins/accounts/OneFichierCom.py b/module/plugins/accounts/OneFichierCom.py
new file mode 100644
index 0000000000..5872bb5a23
--- /dev/null
+++ b/module/plugins/accounts/OneFichierCom.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+import pycurl
+from module.network.HTTPRequest import BadHeader
+
+from ..internal.Account import Account
+
+
+class OneFichierCom(Account):
+ __name__ = "OneFichierCom"
+ __type__ = "account"
+ __version__ = "0.25"
+ __status__ = "testing"
+
+ __description__ = """1fichier.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Elrick69", "elrick69[AT]rocketmail[DOT]com"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+ VALID_UNTIL_PATTERN = r'valid until (\d+\-\d+\-\d+)<'
+
+ def grab_info(self, user, password, data):
+ validuntil = None
+ trafficleft = -1
+ premium = False
+
+ html = self.load("https://1fichier.com/console/abo.pl")
+
+ m = re.search(self.VALID_UNTIL_PATTERN, html)
+ if m is not None:
+ expiredate = m.group(1)
+ self.log_debug("Expire date: " + expiredate)
+
+ try:
+ validuntil = time.mktime(time.strptime(expiredate, "%Y-%m-%d"))
+
+ except Exception, e:
+ self.log_error(e, trace=True)
+
+ else:
+ premium = True
+
+ return {'validuntil': validuntil,
+ 'trafficleft': trafficleft,
+ 'premium': premium}
+
+ def signin(self, user, password, data):
+ login_url = "https://1fichier.com/login.pl?lg=en"
+
+ html = self.load(login_url)
+ if "/logout.pl" in html:
+ self.skip_login()
+
+ try:
+ html = self.load(login_url,
+ ref=login_url,
+ post={'mail': user,
+ 'pass': password,
+ 'lt': "on",
+ 'purge': "off",
+ 'valider': "OK"})
+
+ if any(_x in html for _x in
+ ('>Invalid username or Password', '>Invalid email address', '>Invalid password', '>Invalid username')):
+ self.fail_login()
+
+ except BadHeader, e:
+ if e.code == 403:
+ self.fail_login()
+ else:
+ raise
diff --git a/module/plugins/accounts/OverLoadMe.py b/module/plugins/accounts/OverLoadMe.py
new file mode 100644
index 0000000000..4fc1f26b55
--- /dev/null
+++ b/module/plugins/accounts/OverLoadMe.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+from ..internal.misc import json
+from ..internal.MultiAccount import MultiAccount
+
+
+class OverLoadMe(MultiAccount):
+ __name__ = "OverLoadMe"
+ __type__ = "account"
+ __version__ = "0.13"
+ __status__ = "testing"
+
+ __config__ = [("mh_mode", "all;listed;unlisted", "Filter hosters to use", "all"),
+ ("mh_list", "str", "Hoster list (comma separated)", ""),
+ ("mh_interval", "int", "Reload interval in hours", 12)]
+
+ __description__ = """Over-Load.me account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("marley", "marley@over-load.me")]
+
+ def grab_hosters(self, user, password, data):
+ html = self.load("https://api.over-load.me/hoster.php",
+ get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"})
+ return [x for x in map(
+ str.strip, html.replace("\"", "").split(",")) if x]
+
+ def grab_info(self, user, password, data):
+ html = self.load("https://api.over-load.me/account.php",
+ get={'user': user,
+ 'auth': password}).strip()
+
+ data = json.loads(html)
+ self.log_debug(data)
+
+ #: Check for premium
+ if data['membership'] == "Free":
+ return {'premium': False, 'validuntil': None, 'trafficleft': None}
+ else:
+ return {'premium': True,
+ 'validuntil': data['expirationunix'],
+ 'trafficleft': -1}
+
+ def signin(self, user, password, data):
+ html = self.load("https://api.over-load.me/account.php",
+ get={'user': user,
+ 'auth': password}).strip()
+
+ data = json.loads(html)
+
+ if data['err'] == 1:
+ self.fail_login()
diff --git a/module/plugins/accounts/PixeldrainCom.py b/module/plugins/accounts/PixeldrainCom.py
new file mode 100644
index 0000000000..b951603043
--- /dev/null
+++ b/module/plugins/accounts/PixeldrainCom.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+import pycurl
+from module.network.HTTPRequest import BadHeader
+
+from ..internal.Account import Account
+from ..internal.misc import json
+
+
+class PixeldrainCom(Account):
+ __name__ = "PixeldrainCom"
+ __type__ = "account"
+ __version__ = "0.01"
+ __status__ = "testing"
+
+ __description__ = """Pixeldrain.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+ #: See https://pixeldrain.com/api/
+ API_URL = "https://pixeldrain.com/api/"
+
+ def grab_info(self, user, password, data):
+ # unfortunately, there is no method for account info, assume premium
+ return {"validuntil": -1,
+ "trafficleft": -1,
+ "premium": True}
+
+ def signin(self, user, password, data):
+ self.req.http.c.setopt(pycurl.USERPWD, ":%s" % password)
+ try:
+ json_data = self.load(self.API_URL + "/user/lists")
+ except BadHeader as exc:
+ json_data = exc.content
+
+ api_data = json.loads(json_data)
+ if not api_data.get("success", True):
+ self.log_error(api_data["message"])
+ self.fail_login()
diff --git a/module/plugins/accounts/PorntrexCom.py b/module/plugins/accounts/PorntrexCom.py
new file mode 100644
index 0000000000..272f50773e
--- /dev/null
+++ b/module/plugins/accounts/PorntrexCom.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+from ..internal.Account import Account
+from ..internal.misc import parse_html_form
+
+
+class PorntrexCom(Account):
+ # Actually not needed
+ __name__ = "PorntrexCom"
+ __type__ = "account"
+ __version__ = "0.01"
+ __status__ = "testing"
+
+ __description__ = """Porntrex.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("ondrej", "git@ondrej.it")]
+
+ def grab_info(self, user, password, data):
+ return {
+ "validuntil": -1,
+ "trafficleft": -1,
+ }
+
+ def signin(self, user, password, data):
+ html = self.load("https://www.porntrex.com")
+ if ">Log out<" in html:
+ self.skip_login()
+
+ url, inputs = parse_html_form('action="https://www.porntrex.com/ajax-login/"', html)
+ if inputs is None:
+ self.fail_login("Login form not found")
+
+ inputs["username"] = user
+ inputs["pass"] = password
+
+ html = self.load(url, post=inputs)
+ if ">Log out<" not in html:
+ self.fail_login()
diff --git a/module/plugins/accounts/Premium4Me.py b/module/plugins/accounts/Premium4Me.py
deleted file mode 100644
index 467c5943ed..0000000000
--- a/module/plugins/accounts/Premium4Me.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from module.plugins.Account import Account
-
-
-class Premium4Me(Account):
- __name__ = "Premium4Me"
- __version__ = "0.03"
- __type__ = "account"
- __description__ = """Premium.to account plugin"""
- __author_name__ = ("RaNaN", "zoidberg", "stickell")
- __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
-
- def loadAccountInfo(self, user, req):
- traffic = req.load("http://premium.to/api/traffic.php?authcode=%s" % self.authcode)
-
- account_info = {"trafficleft": int(traffic) / 1024,
- "validuntil": -1}
-
- return account_info
-
- def login(self, user, data, req):
- self.authcode = req.load("http://premium.to/api/getauthcode.php?username=%s&password=%s" % (
- user, data["password"])).strip()
-
- if "wrong username" in self.authcode:
- self.wrongPassword()
diff --git a/module/plugins/accounts/PremiumTo.py b/module/plugins/accounts/PremiumTo.py
new file mode 100644
index 0000000000..dfad2ce67c
--- /dev/null
+++ b/module/plugins/accounts/PremiumTo.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+from ..internal.MultiAccount import MultiAccount
+from ..internal.misc import json
+
+
+class PremiumTo(MultiAccount):
+ __name__ = "PremiumTo"
+ __type__ = "account"
+ __version__ = "0.21"
+ __status__ = "testing"
+
+ __config__ = [("mh_mode", "all;listed;unlisted", "Filter hosters to use", "all"),
+ ("mh_list", "str", "Hoster list (comma separated)", ""),
+ ("mh_interval", "int", "Reload interval in hours", 12)]
+
+ __description__ = """Premium.to account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.net"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+
+ # See https://premium.to/API.html
+ API_URL = "http://api.premium.to/api/2/"
+
+ def api_response(self, method, **kwargs):
+ return json.loads(self.load(self.API_URL + method + ".php",
+ get=kwargs))
+
+ def grab_hosters(self, user, password, data):
+ json_data = self.api_response("hosts", userid=user, apikey=password)
+ return json_data['hosts'] if json_data.get('code') == 200 else []
+
+ def grab_info(self, user, password, data):
+ json_data = self.api_response("traffic", userid=user, apikey=password)
+
+ if json_data.get('code') == 200:
+ trafficleft = float(json_data['traffic'] + json_data['specialtraffic'])
+ return {'premium': True,
+ 'trafficleft': trafficleft,
+ 'validuntil': -1}
+
+ else:
+ return {'premium': False,
+ 'trafficleft': None,
+ 'validuntil': None}
+
+ def signin(self, user, password, data):
+ json_data = self.api_response("traffic", userid=user, apikey=password)
+
+ if json_data['code'] != 200:
+ self.log_warning(_("Username and password for PremiumTo should be the API userid & apikey"),
+ _("Trying via username and password"))
+
+ json_data = self.api_response("getapicredentials", username=user, password=password)
+ if not json_data.get('userid') or not json_data.get('userid'):
+ self.log_warning(json_data['message'])
+ self.fail_login()
+
+ else:
+ # Replace current user & password with the generated userid & apikey
+ # Hacky hack, but what can we do?!
+ userid = json_data['userid']
+ apikey = json_data['apikey']
+ plugin = self.classname
+ self.pyload.accountManager.accounts[plugin][userid] = self.pyload.accountManager.accounts[plugin].pop(user)
+ self.pyload.accountManager.accounts[plugin][userid]['password'] = apikey
+ self.user = userid
+ self.info['data']['login'] = userid
+ self.info['login']['password'] = apikey
+
diff --git a/module/plugins/accounts/PremiumizeMe.py b/module/plugins/accounts/PremiumizeMe.py
index c5c712c52f..8fdf55df31 100644
--- a/module/plugins/accounts/PremiumizeMe.py
+++ b/module/plugins/accounts/PremiumizeMe.py
@@ -1,42 +1,63 @@
-from module.plugins.Account import Account
+# -*- coding: utf-8 -*-
-from module.common.json_layer import json_loads
+from ..internal.misc import json
+from ..internal.MultiAccount import MultiAccount
-class PremiumizeMe(Account):
+class PremiumizeMe(MultiAccount):
__name__ = "PremiumizeMe"
- __version__ = "0.11"
__type__ = "account"
- __description__ = """Premiumize.Me account plugin"""
- __author_name__ = ("Florian Franzen")
- __author_mail__ = ("FlorianFranzen@gmail.com")
-
- def loadAccountInfo(self, user, req):
- # Get user data from premiumize.me
- status = self.getAccountStatus(user, req)
- self.logDebug(status)
-
- # Parse account info
- account_info = {"validuntil": float(status['result']['expires']),
- "trafficleft": max(0, status['result']['trafficleft_bytes'] / 1024)}
-
- if status['result']['type'] == 'free':
- account_info['premium'] = False
-
- return account_info
-
- def login(self, user, data, req):
- # Get user data from premiumize.me
- status = self.getAccountStatus(user, req)
-
- # Check if user and password are valid
- if status['status'] != 200:
- self.wrongPassword()
-
- def getAccountStatus(self, user, req):
- # Use premiumize.me API v1 (see https://secure.premiumize.me/?show=api)
- # to retrieve account info and return the parsed json answer
- answer = req.load(
- "https://api.premiumize.me/pm-api/v1.php?method=accountstatus¶ms[login]=%s¶ms[pass]=%s" % (
- user, self.accounts[user]['password']))
- return json_loads(answer)
+ __version__ = "0.32"
+ __status__ = "testing"
+
+ __config__ = [("mh_mode", "all;listed;unlisted", "Filter hosters to use", "all"),
+ ("mh_list", "str", "Hoster list (comma separated)", ""),
+ ("mh_interval", "int", "Reload interval in hours", 12)]
+
+ __description__ = """Premiumize.me account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com"),
+ ("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]
+
+ # See https://www.premiumize.me/api
+ API_URL = "https://www.premiumize.me/api/"
+
+ def api_respond(self, method, **kwargs):
+ json_data = self.load(self.API_URL + method, get=kwargs)
+
+ return json.loads(json_data)
+
+ def grab_hosters(self, user, password, data):
+ res = self.api_respond("services/list", apikey=password)
+ return res['directdl'] + reduce(lambda x, y: x + y, [res['aliases'][_h] if _h in res['aliases'] else []
+ for _h in res['directdl']])
+
+ def grab_info(self, user, password, data):
+ validuntil = None
+ trafficleft = None
+ premium = False
+
+ res = self.api_respond("account/info", apikey=password)
+
+ if res['status'] == "success":
+ premium = res['premium_until'] is not False
+
+ if premium:
+ validuntil = res['premium_until']
+
+ trafficleft = -1
+
+ return {'validuntil': validuntil,
+ 'trafficleft': trafficleft,
+ 'premium': premium}
+
+ def signin(self, user, password, data):
+ res = self.api_respond("account/info", apikey=password)
+
+ if res['status'] != "success":
+ self.log_error(_("Password for premiumize.me should be the API token - get it from: https://www.premiumize.me/account"))
+ self.fail_login(res['message'])
+
+ elif res['customer_id'] != user:
+ self.log_error(_("username for premiumize.me should be the Customer ID - get it from: https://www.premiumize.me/account"))
+ self.fail_login()
diff --git a/module/plugins/accounts/PutdriveCom.py b/module/plugins/accounts/PutdriveCom.py
new file mode 100644
index 0000000000..53964a932d
--- /dev/null
+++ b/module/plugins/accounts/PutdriveCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from .ZeveraCom import ZeveraCom
+
+
+class PutdriveCom(ZeveraCom):
+ __name__ = "PutdriveCom"
+ __type__ = "account"
+ __version__ = "0.07"
+ __status__ = "testing"
+
+ __description__ = """Putdrive.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+ PLUGIN_DOMAIN = "putdrive.com"
diff --git a/module/plugins/accounts/QuickshareCz.py b/module/plugins/accounts/QuickshareCz.py
index 1af7cbffd7..3a2a1716a9 100644
--- a/module/plugins/accounts/QuickshareCz.py
+++ b/module/plugins/accounts/QuickshareCz.py
@@ -1,54 +1,40 @@
# -*- 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 |
|---|
Файл номер [^<]* (не найден|удален) !!!
' - - SESSION_ID_PATTERN = r']+)>' - INTS_SESSION_PATTERN = r'\(\'ints_session\'\);\s*if\(tag\)\{tag.value = "([^"]+)";\}' - HIDDEN_INPUT_PATTERN = r"var v = .*?name='([^']+)' value='1'" - DOWNLOAD_LINK_PATTERN = r'неверный код,Файл номер .*? (не найден|удален) !!!
' - url, session_id = re.search(self.SESSION_ID_PATTERN, self.html).groups() - self.html = self.load(url, cookies=True, decode=True) + SESSION_ID_PATTERN = r'неверный код,(?P[\d.,]+) (?P[\w^_]+)
.
+from ..internal.misc import json
+from ..internal.SimpleHoster import SimpleHoster
- @author: zoidberg
-"""
-import re
-from module.plugins.Hoster import Hoster
-from module.network.RequestFactory import getURL
+def get_api_password(episode):
+ api_key = "fb5f58a820353bd7095de526253c14fd"
+ timestamp = int(round(time.time() / 24 / 3600))
+ api_pass = api_key + "/episode/" + episode + str(timestamp)
-def getInfo(urls):
- result = []
+ m = hashlib.md5(api_pass)
- for url in urls:
+ return m.hexdigest()
+
+
+def get_all_link(data, container):
+ videos = []
+
+ for i in range(0, len(data["video_qualities"])):
+ if container == "webm" and len(
+ data["video_qualities"][i]["formats"]) != 1:
+ videos.append(data["video_qualities"][i]["formats"][1]["source"])
- html = getURL(url)
- if re.search(StreamCz.FILE_OFFLINE_PATTERN, html):
- # File offline
- result.append((url, 0, 1, url))
else:
- result.append((url, 0, 2, url))
- yield result
+ videos.append(data["video_qualities"][i]["formats"][0]["source"])
+
+ return videos
-class StreamCz(Hoster):
+def get_link_quality(videos, quality):
+ quality_index = ["144p", "240p", "360p", "480p", "720p", "1080p"]
+ quality = quality_index.index(quality)
+
+ link = None
+ while quality >= 0:
+ if len(videos) >= quality + 1:
+ link = videos[quality]
+ break
+
+ else:
+ quality -= 1
+
+ return link
+
+
+class StreamCz(SimpleHoster):
__name__ = "StreamCz"
__type__ = "hoster"
- __pattern__ = r"http://www.stream.cz/[^/]+/\d+.*"
- __version__ = "0.1"
- __description__ = """stream.cz"""
- __author_name__ = ("zoidberg")
+ __version__ = "0.41"
+ __status__ = "testing"
- FILE_OFFLINE_PATTERN = r'