summaryrefslogtreecommitdiffstats
path: root/module/plugins/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'module/plugins/hooks')
-rw-r--r--module/plugins/hooks/AndroidPhoneNotify.py27
-rw-r--r--module/plugins/hooks/AntiStandby.py30
-rw-r--r--module/plugins/hooks/AntiVirus.py28
-rw-r--r--module/plugins/hooks/BypassCaptcha.py12
-rw-r--r--module/plugins/hooks/Captcha9Kw.py43
-rw-r--r--module/plugins/hooks/CaptchaBrotherhood.py19
-rw-r--r--module/plugins/hooks/Checksum.py34
-rw-r--r--module/plugins/hooks/ClickNLoad.py25
-rw-r--r--module/plugins/hooks/DeathByCaptcha.py26
-rw-r--r--module/plugins/hooks/DeleteFinished.py11
-rw-r--r--module/plugins/hooks/DownloadScheduler.py6
-rw-r--r--module/plugins/hooks/EventMapper.py80
-rw-r--r--module/plugins/hooks/ExpertDecoders.py18
-rw-r--r--module/plugins/hooks/ExternalScripts.py197
-rw-r--r--module/plugins/hooks/ExtractArchive.py58
-rw-r--r--module/plugins/hooks/HotFolder.py21
-rw-r--r--module/plugins/hooks/IRC.py (renamed from module/plugins/hooks/IRCInterface.py)49
-rw-r--r--module/plugins/hooks/ImageTyperz.py28
-rw-r--r--module/plugins/hooks/JustPremium.py6
-rw-r--r--module/plugins/hooks/LogMarker.py12
-rw-r--r--module/plugins/hooks/MergeFiles.py10
-rw-r--r--module/plugins/hooks/MultiHome.py6
-rw-r--r--module/plugins/hooks/PushBullet.py27
-rw-r--r--module/plugins/hooks/PushOver.py29
-rw-r--r--module/plugins/hooks/RestartFailed.py9
-rw-r--r--module/plugins/hooks/SkipRev.py49
-rw-r--r--module/plugins/hooks/TransmissionRPC.py10
-rw-r--r--module/plugins/hooks/UnSkipOnFail.py42
-rw-r--r--module/plugins/hooks/UpdateManager.py24
-rw-r--r--module/plugins/hooks/UserAgentSwitcher.py10
-rw-r--r--module/plugins/hooks/WarezWorld.py277
-rw-r--r--module/plugins/hooks/WindowsPhoneNotify.py29
-rw-r--r--module/plugins/hooks/XFileSharing.py29
-rw-r--r--module/plugins/hooks/XMPP.py (renamed from module/plugins/hooks/XMPPInterface.py)52
34 files changed, 566 insertions, 767 deletions
diff --git a/module/plugins/hooks/AndroidPhoneNotify.py b/module/plugins/hooks/AndroidPhoneNotify.py
index cc7fe8d6b..5a5188365 100644
--- a/module/plugins/hooks/AndroidPhoneNotify.py
+++ b/module/plugins/hooks/AndroidPhoneNotify.py
@@ -6,19 +6,22 @@ from module.plugins.internal.Notifier import Notifier
class AndroidPhoneNotify(Notifier):
__name__ = "AndroidPhoneNotify"
__type__ = "hook"
- __version__ = "0.13"
+ __version__ = "0.15"
__status__ = "testing"
- __config__ = [("activated" , "bool", "Activated" , False),
- ("apikey" , "str" , "API key" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify packages processed" , True ),
- ("notifyupdate" , "bool", "Notify plugin updates" , True ),
- ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ),
- ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ),
- ("sendpermin" , "int" , "Max notifications per minute" , 12 ),
- ("ignoreclient" , "bool", "Send notifications if client is connected", False)]
+ __config__ = [("activated" , "bool", "Activated" , False),
+ ("apikey" , "str" , "API key" , "" ),
+ ("captcha" , "bool", "Notify captcha request" , True ),
+ ("reconnection" , "bool", "Notify reconnection request" , False),
+ ("downloadfinished", "bool", "Notify download finished" , True ),
+ ("downloadfailed" , "bool", "Notify download failed" , True ),
+ ("packagefinished" , "bool", "Notify package finished" , True ),
+ ("packagefailed" , "bool", "Notify package failed" , True ),
+ ("update" , "bool", "Notify pyLoad update" , False),
+ ("exit" , "bool", "Notify pyLoad shutdown/restart" , False),
+ ("sendinterval" , "int" , "Interval in seconds between notifications", 1 ),
+ ("sendpermin" , "int" , "Max notifications per minute" , 60 ),
+ ("ignoreclient" , "bool", "Send notifications if client is connected", True )]
__description__ = """Send push notifications to your Android Phone using notifymyandroid.com"""
__license__ = "GPLv3"
@@ -27,7 +30,7 @@ class AndroidPhoneNotify(Notifier):
def get_key(self):
- return self.get_config('apikey')
+ return self.config.get('apikey')
def send(self, event, msg, key):
diff --git a/module/plugins/hooks/AntiStandby.py b/module/plugins/hooks/AntiStandby.py
index 5ad95d6e8..2159e5937 100644
--- a/module/plugins/hooks/AntiStandby.py
+++ b/module/plugins/hooks/AntiStandby.py
@@ -13,7 +13,7 @@ except ImportError:
pass
from module.plugins.internal.Addon import Addon, Expose
-from module.plugins.internal.utils import encode, fs_join
+from module.plugins.internal.misc import encode, fsjoin
class Kernel32(object):
@@ -27,7 +27,7 @@ class Kernel32(object):
class AntiStandby(Addon):
__name__ = "AntiStandby"
__type__ = "hook"
- __version__ = "0.13"
+ __version__ = "0.14"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , True ),
@@ -50,12 +50,12 @@ class AntiStandby(Addon):
def activate(self):
- hdd = self.get_config('hdd')
- system = not self.get_config('system')
- display = not self.get_config('display')
+ hdd = self.config.get('hdd')
+ system = not self.config.get('system')
+ display = not self.config.get('display')
if hdd:
- self.start_periodical(self.get_config('interval'), threaded=True)
+ self.periodical.start(self.config.get('interval'), threaded=True)
if os.name is "nt":
self.win_standby(system, display)
@@ -68,11 +68,7 @@ class AntiStandby(Addon):
def deactivate(self):
- try:
- os.remove(self.TMP_FILE)
-
- except OSError:
- pass
+ self.remove(self.TMP_FILE, trash=False)
if os.name is "nt":
self.win_standby(True)
@@ -152,22 +148,22 @@ class AntiStandby(Addon):
@Expose
def max_mtime(self, path):
return max(0, 0,
- *(os.path.getmtime(fs_join(root, file))
+ *(os.path.getmtime(fsjoin(root, file))
for root, dirs, files in os.walk(encode(path), topdown=False)
for file in files))
- def periodical(self):
- if self.get_config('hdd') is False:
+ def periodical_task(self):
+ if self.config.get('hdd') is False:
return
if (self.pyload.threadManager.pause or
- not self.pyload.api.isTimeDownload() or
- not self.pyload.threadManager.getActiveFiles()):
+ not self.pyload.api.isTimeDownload() or
+ not self.pyload.threadManager.getActiveFiles()):
return
dl_folder = self.pyload.config.get("general", "download_folder")
- if (self.max_mtime(dl_folder) - self.mtime) < self.interval:
+ if (self.max_mtime(dl_folder) - self.mtime) < self.periodical.interval:
return
self.touch(self.TMP_FILE)
diff --git a/module/plugins/hooks/AntiVirus.py b/module/plugins/hooks/AntiVirus.py
index 049e92ab8..1a0f3f8bd 100644
--- a/module/plugins/hooks/AntiVirus.py
+++ b/module/plugins/hooks/AntiVirus.py
@@ -10,14 +10,14 @@ except ImportError:
pass
from module.plugins.internal.Addon import Addon, Expose, threaded
-from module.plugins.internal.utils import encode, exists, fs_join
+from module.plugins.internal.misc import encode, exists, fsjoin
class AntiVirus(Addon):
__name__ = "AntiVirus"
__type__ = "hook"
- __version__ = "0.15"
- __status__ = "testing"
+ __version__ = "0.16"
+ __status__ = "broken"
#@TODO: add trash option (use Send2Trash lib)
__config__ = [("activated" , "bool" , "Activated" , False ),
@@ -38,18 +38,18 @@ class AntiVirus(Addon):
@Expose
@threaded
def scan(self, pyfile, thread):
- avfile = encode(self.get_config('avfile'))
- avargs = encode(self.get_config('avargs').strip())
+ avfile = encode(self.config.get('avfile'))
+ avargs = encode(self.config.get('avargs').strip())
if not os.path.isfile(avfile):
self.fail(_("Antivirus executable not found"))
- scanfolder = self.get_config('avtarget') is "folder"
+ scanfolder = self.config.get('avtarget') is "folder"
if scanfolder:
dl_folder = self.pyload.config.get("general", "download_folder")
package_folder = pyfile.package().folder if self.pyload.config.get("general", "folder_per_package") else ""
- target = fs_join(dl_folder, package_folder, pyfile.name)
+ target = fsjoin(dl_folder, package_folder, pyfile.name)
target_repr = "Folder: " + package_folder or dl_folder
else:
target = encode(pyfile.plugin.last_download)
@@ -75,12 +75,12 @@ class AntiVirus(Addon):
if err:
self.log_warning(target_repr, err)
- if not self.get_config('ignore-err'):
+ if not self.config.get('ignore-err'):
self.log_debug("Delete/Quarantine task aborted due scan error")
return
if p.returncode:
- action = self.get_config('action')
+ action = self.config.get('action')
if scanfolder:
if action is "Antivirus default":
@@ -91,7 +91,7 @@ class AntiVirus(Addon):
try:
if action is "Delete":
- if not self.get_config('deltotrash'):
+ if not self.config.get('deltotrash'):
os.remove(file)
else:
@@ -101,19 +101,19 @@ class AntiVirus(Addon):
except NameError:
self.log_warning(_("Send2Trash lib not found, moving to quarantine instead"))
pyfile.setCustomStatus(_("file moving"))
- shutil.move(file, self.get_config('quardir'))
+ shutil.move(file, self.config.get('quardir'))
except Exception, e:
self.log_warning(_("Unable to move file to trash: %s, moving to quarantine instead") % e.message)
pyfile.setCustomStatus(_("file moving"))
- shutil.move(file, self.get_config('quardir'))
+ shutil.move(file, self.config.get('quardir'))
else:
self.log_debug("Successfully moved file to trash")
elif action is "Quarantine":
pyfile.setCustomStatus(_("file moving"))
- shutil.move(file, self.get_config('quardir'))
+ shutil.move(file, self.config.get('quardir'))
except (IOError, shutil.Error), e:
self.log_error(target_repr, action + " action failed!", e)
@@ -132,5 +132,5 @@ class AntiVirus(Addon):
def download_failed(self, pyfile):
#: Check if pyfile is still "failed", maybe might has been restarted in meantime
- if pyfile.status is 8 and self.get_config('scanfailed'):
+ if pyfile.status is 8 and self.config.get('scanfailed'):
return self.scan(pyfile)
diff --git a/module/plugins/hooks/BypassCaptcha.py b/module/plugins/hooks/BypassCaptcha.py
index 581d2f6dd..bc28b1469 100644
--- a/module/plugins/hooks/BypassCaptcha.py
+++ b/module/plugins/hooks/BypassCaptcha.py
@@ -28,7 +28,7 @@ class BypassCaptchaException(Exception):
class BypassCaptcha(Addon):
__name__ = "BypassCaptcha"
__type__ = "hook"
- __version__ = "0.09"
+ __version__ = "0.10"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False),
@@ -50,7 +50,7 @@ class BypassCaptcha(Addon):
def get_credits(self):
- res = self.load(self.GETCREDITS_URL, post={'key': self.get_config('passkey')})
+ res = self.load(self.GETCREDITS_URL, post={'key': self.config.get('passkey')})
data = dict(x.split(' ', 1) for x in res.splitlines())
return int(data['Left'])
@@ -65,7 +65,7 @@ class BypassCaptcha(Addon):
try:
res = self.load(self.SUBMIT_URL,
post={'vendor_key': self.PYLOAD_KEY,
- 'key': self.get_config('passkey'),
+ 'key': self.config.get('passkey'),
'gen_task_id': "1",
'file': (pycurl.FORM_FILE, captcha)},
req=req)
@@ -85,7 +85,7 @@ class BypassCaptcha(Addon):
def respond(self, ticket, success):
try:
- res = self.load(self.RESPOND_URL, post={'task_id': ticket, 'key': self.get_config('passkey'),
+ res = self.load(self.RESPOND_URL, post={'task_id': ticket, 'key': self.config.get('passkey'),
'cv': 1 if success else 0})
except BadHeader, e:
self.log_error(_("Could not send response"), e)
@@ -98,10 +98,10 @@ class BypassCaptcha(Addon):
if not task.isTextual():
return False
- if not self.get_config('passkey'):
+ if not self.config.get('passkey'):
return False
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return False
if self.get_credits() > 0:
diff --git a/module/plugins/hooks/Captcha9Kw.py b/module/plugins/hooks/Captcha9Kw.py
index c81882f67..714be8bc4 100644
--- a/module/plugins/hooks/Captcha9Kw.py
+++ b/module/plugins/hooks/Captcha9Kw.py
@@ -2,11 +2,10 @@
from __future__ import with_statement
+import base64
import re
import time
-from base64 import b64encode
-
from module.network.HTTPRequest import BadHeader
from module.plugins.internal.Addon import Addon, threaded
@@ -14,7 +13,7 @@ from module.plugins.internal.Addon import Addon, threaded
class Captcha9Kw(Addon):
__name__ = "Captcha9Kw"
__type__ = "hook"
- __version__ = "0.31"
+ __version__ = "0.32"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False ),
@@ -40,7 +39,7 @@ class Captcha9Kw(Addon):
def get_credits(self):
res = self.load(self.API_URL,
- get={'apikey': self.get_config('passkey'),
+ get={'apikey': self.config.get('passkey'),
'pyload': "1",
'source': "pyload",
'action': "usercaptchaguthaben"})
@@ -71,14 +70,14 @@ class Captcha9Kw(Addon):
'numeric' : 0,
'case_sensitive': 0,
'math' : 0,
- 'prio' : min(max(self.get_config('prio'), 0), 10),
- 'confirm' : self.get_config('confirm'),
- 'timeout' : min(max(self.get_config('timeout'), 300), 3999),
- 'selfsolve' : self.get_config('selfsolve'),
- 'cph' : self.get_config('captchaperhour'),
- 'cpm' : self.get_config('captchapermin')}
-
- for opt in str(self.get_config('hoster_options').split('|')):
+ 'prio' : min(max(self.config.get('prio'), 0), 10),
+ 'confirm' : self.config.get('confirm'),
+ 'timeout' : min(max(self.config.get('timeout'), 300), 3999),
+ 'selfsolve' : self.config.get('selfsolve'),
+ 'cph' : self.config.get('captchaperhour'),
+ 'cpm' : self.config.get('captchapermin')}
+
+ for opt in str(self.config.get('hoster_options').split('|')):
details = map(str.strip, opt.split(':'))
if not details or details[0].lower() is not pluginname.lower():
@@ -96,7 +95,7 @@ class Captcha9Kw(Addon):
break
- post_data = {'apikey' : self.get_config('passkey'),
+ post_data = {'apikey' : self.config.get('passkey'),
'prio' : option['prio'],
'confirm' : option['confirm'],
'maxtimeout' : option['timeout'],
@@ -114,7 +113,7 @@ class Captcha9Kw(Addon):
'source' : "pyload",
'base64' : 1,
'mouse' : 1 if task.isPositional() else 0,
- 'file-upload-01': b64encode(data),
+ 'file-upload-01': base64.b64encode(data),
'action' : "usercaptchaupload"}
for _i in xrange(5):
@@ -136,9 +135,9 @@ class Captcha9Kw(Addon):
task.data['ticket'] = res
- for _i in xrange(int(self.get_config('timeout') / 5)):
+ for _i in xrange(int(self.config.get('timeout') / 5)):
result = self.load(self.API_URL,
- get={'apikey': self.get_config('passkey'),
+ get={'apikey': self.config.get('passkey'),
'id' : res,
'pyload': "1",
'info' : "1",
@@ -163,10 +162,10 @@ class Captcha9Kw(Addon):
if not task.isTextual() and not task.isPositional():
return
- if not self.get_config('passkey'):
+ if not self.config.get('passkey'):
return
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return
credits = self.get_credits()
@@ -175,8 +174,8 @@ class Captcha9Kw(Addon):
self.log_error(_("Your captcha 9kw.eu account has not enough credits"))
return
- queue = min(self.get_config('queue'), 999)
- timeout = min(max(self.get_config('timeout'), 300), 3999)
+ queue = min(self.config.get('queue'), 999)
+ timeout = min(max(self.config.get('timeout'), 300), 3999)
pluginname = re.search(r'_(.+?)_\d+.\w+', task.captchaFile).group(1)
for _i in xrange(5):
@@ -189,7 +188,7 @@ class Captcha9Kw(Addon):
else:
self.fail(_("Too many captchas in queue"))
- for opt in str(self.get_config('hoster_options').split('|')):
+ for opt in str(self.config.get('hoster_options').split('|')):
details = map(str.strip, opt.split(':'))
if not details or details[0].lower() is not pluginname.lower():
@@ -219,7 +218,7 @@ class Captcha9Kw(Addon):
self.log_debug("No CaptchaID for %s request (task: %s)" % (type, task))
return
- passkey = self.get_config('passkey')
+ passkey = self.config.get('passkey')
for _i in xrange(3):
res = self.load(self.API_URL,
diff --git a/module/plugins/hooks/CaptchaBrotherhood.py b/module/plugins/hooks/CaptchaBrotherhood.py
index 5334c1c5b..15546c63f 100644
--- a/module/plugins/hooks/CaptchaBrotherhood.py
+++ b/module/plugins/hooks/CaptchaBrotherhood.py
@@ -3,10 +3,11 @@
from __future__ import with_statement
import StringIO
-import pycurl
import time
import urllib
+import pycurl
+
try:
from PIL import Image
@@ -38,7 +39,7 @@ class CaptchaBrotherhoodException(Exception):
class CaptchaBrotherhood(Addon):
__name__ = "CaptchaBrotherhood"
__type__ = "hook"
- __version__ = "0.11"
+ __version__ = "0.12"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False),
@@ -57,7 +58,7 @@ class CaptchaBrotherhood(Addon):
def get_credits(self):
res = self.load(self.API_URL + "askCredits.aspx",
- get={'username': self.get_config('username'), 'password': self.get_config('password')})
+ get={'username': self.config.get('username'), 'password': self.config.get('password')})
if not res.startswith("OK"):
raise CaptchaBrotherhoodException(res)
else:
@@ -87,8 +88,8 @@ class CaptchaBrotherhood(Addon):
req = get_request()
url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL,
- urllib.urlencode({'username' : self.get_config('username'),
- 'password' : self.get_config('password'),
+ urllib.urlencode({'username' : self.config.get('username'),
+ 'password' : self.config.get('password'),
'captchaSource': "pyLoad",
'timeout' : "80"}))
@@ -122,8 +123,8 @@ class CaptchaBrotherhood(Addon):
def api_response(self, api, ticket):
res = self.load("%s%s.aspx" % (self.API_URL, api),
- get={'username': self.get_config('username'),
- 'password': self.get_config('password'),
+ get={'username': self.config.get('username'),
+ 'password': self.config.get('password'),
'captchaID': ticket})
if not res.startswith("OK"):
raise CaptchaBrotherhoodException("Unknown response: %s" % res)
@@ -138,10 +139,10 @@ class CaptchaBrotherhood(Addon):
if not task.isTextual():
return False
- if not self.get_config('username') or not self.get_config('password'):
+ if not self.config.get('username') or not self.config.get('password'):
return False
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return False
if self.get_credits() > 10:
diff --git a/module/plugins/hooks/Checksum.py b/module/plugins/hooks/Checksum.py
index cf5ed2147..af6f2f406 100644
--- a/module/plugins/hooks/Checksum.py
+++ b/module/plugins/hooks/Checksum.py
@@ -8,7 +8,7 @@ import re
import zlib
from module.plugins.internal.Addon import Addon
-from module.plugins.internal.utils import encode, fs_join
+from module.plugins.internal.misc import encode, fsjoin
def compute_checksum(local_file, algorithm):
@@ -38,8 +38,8 @@ def compute_checksum(local_file, algorithm):
class Checksum(Addon):
__name__ = "Checksum"
__type__ = "hook"
- __version__ = "0.23"
- __status__ = "testing"
+ __version__ = "0.24"
+ __status__ = "broken"
__config__ = [("activated" , "bool" , "Activated" , False ),
("check_checksum", "bool" , "Check checksum? (If False only size will be verified)", True ),
@@ -65,7 +65,7 @@ class Checksum(Addon):
def activate(self):
- if not self.get_config('check_checksum'):
+ if not self.config.get('check_checksum'):
self.log_info(_("Checksum validation is disabled in plugin configuration"))
@@ -105,7 +105,7 @@ class Checksum(Addon):
local_file = encode(pyfile.plugin.last_download)
# dl_folder = self.pyload.config.get("general", "download_folder")
- # local_file = encode(fs_join(dl_folder, pyfile.package().folder, pyfile.name))
+ # local_file = encode(fsjoin(dl_folder, pyfile.package().folder, pyfile.name))
if not os.path.isfile(local_file):
self.check_failed(pyfile, None, "File does not exist")
@@ -122,7 +122,7 @@ class Checksum(Addon):
data.pop('size', None)
#: Validate checksum
- if data and self.get_config('check_checksum'):
+ if data and self.config.get('check_checksum'):
if not 'md5' in data:
for type in ("checksum", "hashsum", "hash"):
@@ -149,14 +149,14 @@ class Checksum(Addon):
def check_failed(self, pyfile, local_file, msg):
- check_action = self.get_config('check_action')
+ check_action = self.config.get('check_action')
if check_action == "retry":
- max_tries = self.get_config('max_tries')
- retry_action = self.get_config('retry_action')
+ max_tries = self.config.get('max_tries')
+ retry_action = self.config.get('retry_action')
if pyfile.plugin.retries < max_tries:
if local_file:
os.remove(local_file)
- pyfile.plugin.retry(max_tries, self.get_config('wait_time'), msg)
+ pyfile.plugin.retry(max_tries, self.config.get('wait_time'), msg)
elif retry_action == "nothing":
return
elif check_action == "nothing":
@@ -166,17 +166,17 @@ class Checksum(Addon):
def package_finished(self, pypack):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder, "")
+ dl_folder = fsjoin(self.pyload.config.get("general", "download_folder"), pypack.folder, "")
- for link in pypack.getChildren().values():
- file_type = os.path.splitext(link['name'])[1][1:].lower()
+ for fid, fdata in pypack.getChildren().items():
+ file_type = os.path.splitext(fdata['name'])[1][1:].lower()
if file_type not in self.formats:
continue
- hash_file = encode(fs_join(dl_folder, link['name']))
+ hash_file = encode(fsjoin(dl_folder, fdata['name']))
if not os.path.isfile(hash_file):
- self.log_warning(_("File not found"), link['name'])
+ self.log_warning(_("File not found"), fdata['name'])
continue
with open(hash_file) as f:
@@ -184,9 +184,9 @@ class Checksum(Addon):
for m in re.finditer(self.regexps.get(file_type, self.regexps['default']), text):
data = m.groupdict()
- self.log_debug(link['name'], data)
+ self.log_debug(fdata['name'], data)
- local_file = encode(fs_join(dl_folder, data['NAME']))
+ local_file = encode(fsjoin(dl_folder, data['NAME']))
algorithm = self.methods.get(file_type, file_type)
checksum = compute_checksum(local_file, algorithm)
diff --git a/module/plugins/hooks/ClickNLoad.py b/module/plugins/hooks/ClickNLoad.py
index 79bf66c09..08b16d221 100644
--- a/module/plugins/hooks/ClickNLoad.py
+++ b/module/plugins/hooks/ClickNLoad.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import socket
-import threading
import time
try:
@@ -10,17 +9,7 @@ except ImportError:
pass
from module.plugins.internal.Addon import Addon, threaded
-
-
-def forward(source, destination):
- try:
- bufsize = 1024
- bufdata = source.recv(bufsize)
- while bufdata:
- destination.sendall(bufdata)
- bufdata = source.recv(bufsize)
- finally:
- destination.shutdown(socket.SHUT_WR)
+from module.plugins.internal.misc import forward, lock
#@TODO: IPv6 support
@@ -46,8 +35,8 @@ class ClickNLoad(Addon):
if not self.pyload.config.get("webinterface", "activated"):
return
- cnlip = "" if self.get_config('extern') else "127.0.0.1"
- cnlport = self.get_config('port')
+ cnlip = "" if self.config.get('extern') else "127.0.0.1"
+ cnlport = self.config.get('port')
webip = "127.0.0.1" if any(_ip == self.pyload.config.get("webinterface", "host") for _ip in ("0.0.0.0", "")) \
else self.pyload.config.get("webinterface", "host")
webport = self.pyload.config.get("webinterface", "port")
@@ -55,6 +44,7 @@ class ClickNLoad(Addon):
self.pyload.scheduler.addJob(5, self.proxy, [cnlip, cnlport, webip, webport], threaded=False)
+ @lock
@threaded
def forward(self, source, destination, queue=False):
if queue:
@@ -71,13 +61,8 @@ class ClickNLoad(Addon):
@threaded
def proxy(self, cnlip, cnlport, webip, webport):
self.log_info(_("Proxy listening on %s:%s") % (cnlip or "0.0.0.0", cnlport))
-
self._server(cnlip, cnlport, webip, webport)
- lock = threading.Lock()
- lock.acquire()
- lock.acquire()
-
@threaded
def _server(self, cnlip, cnlport, webip, webport):
@@ -108,7 +93,7 @@ class ClickNLoad(Addon):
server_socket.connect((webip, webport))
- self.forward(client_socket, server_socket, self.get_config('dest') is "queue")
+ self.forward(client_socket, server_socket, self.config.get('dest') is "queue")
self.forward(server_socket, client_socket)
except socket.timeout:
diff --git a/module/plugins/hooks/DeathByCaptcha.py b/module/plugins/hooks/DeathByCaptcha.py
index 5c1c89c88..62cfe7d16 100644
--- a/module/plugins/hooks/DeathByCaptcha.py
+++ b/module/plugins/hooks/DeathByCaptcha.py
@@ -2,16 +2,16 @@
from __future__ import with_statement
-import pycurl
+import base64
import re
import time
-from base64 import b64encode
+import pycurl
-from module.plugins.internal.utils import json
from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getRequest as get_request
from module.plugins.internal.Addon import Addon, threaded
+from module.plugins.internal.misc import json
class DeathByCaptchaException(Exception):
@@ -51,7 +51,7 @@ class DeathByCaptchaException(Exception):
class DeathByCaptcha(Addon):
__name__ = "DeathByCaptcha"
__type__ = "hook"
- __version__ = "0.10"
+ __version__ = "0.11"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False),
@@ -75,8 +75,8 @@ class DeathByCaptcha(Addon):
if post:
if not isinstance(post, dict):
post = {}
- post.update({'username': self.get_config('username'),
- 'password': self.get_config('password')})
+ post.update({'username': self.config.get('username'),
+ 'password': self.config.get('password')})
res = None
try:
@@ -94,13 +94,13 @@ class DeathByCaptcha(Addon):
raise DeathByCaptchaException(str(res))
except BadHeader, e:
- if e.code == 403:
+ if e.code is 403:
raise DeathByCaptchaException('not-logged-in')
- elif e.code == 413:
+ elif e.code is 413:
raise DeathByCaptchaException('invalid-captcha')
- elif e.code == 503:
+ elif e.code is 503:
raise DeathByCaptchaException('service-overload')
elif e.code in (400, 405):
@@ -135,14 +135,14 @@ class DeathByCaptcha(Addon):
def submit(self, captcha, captchaType="file", match=None):
#@NOTE: Workaround multipart-post bug in HTTPRequest.py
- if re.match("^\w*$", self.get_config('password')):
+ if re.match("^\w*$", self.config.get('password')):
multipart = True
data = (pycurl.FORM_FILE, captcha)
else:
multipart = False
with open(captcha, 'rb') as f:
data = f.read()
- data = "base64:" + b64encode(data)
+ data = "base64:" + base64.b64encode(data)
res = self.api_response("captcha", {'captchafile': data}, multipart)
@@ -171,10 +171,10 @@ class DeathByCaptcha(Addon):
if not task.isTextual():
return False
- if not self.get_config('username') or not self.get_config('password'):
+ if not self.config.get('username') or not self.config.get('password'):
return False
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return False
try:
diff --git a/module/plugins/hooks/DeleteFinished.py b/module/plugins/hooks/DeleteFinished.py
index 17b85959a..67e1a1056 100644
--- a/module/plugins/hooks/DeleteFinished.py
+++ b/module/plugins/hooks/DeleteFinished.py
@@ -7,7 +7,7 @@ from module.plugins.internal.Addon import Addon
class DeleteFinished(Addon):
__name__ = "DeleteFinished"
__type__ = "hook"
- __version__ = "1.17"
+ __version__ = "1.18"
__status__ = "testing"
__config__ = [("activated" , "bool", "Activated" , False),
@@ -19,12 +19,9 @@ class DeleteFinished(Addon):
__authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
- PERIODICAL_INTERVAL = 1 * 60 * 60 #: 1 hour
-
-
- def periodical(self):
+ def periodical_task(self):
if not self.info['sleep']:
- deloffline = self.get_config('deloffline')
+ deloffline = self.config.get('deloffline')
mode = "0,1,4" if deloffline else "0,4"
msg = _('delete all finished packages in queue list (%s packages with offline links)')
self.log_info(msg % (_('including') if deloffline else _('excluding')))
@@ -39,8 +36,8 @@ class DeleteFinished(Addon):
def activate(self):
self.info['sleep'] = True
- self.set_interval(self.get_config('interval') * 60 * 60)
self.add_event('package_finished', self.wakeup)
+ self.periodical.start(self.config.get('interval') * 60 * 60)
## own methods ##
diff --git a/module/plugins/hooks/DownloadScheduler.py b/module/plugins/hooks/DownloadScheduler.py
index 9c644ab20..d4c0356fd 100644
--- a/module/plugins/hooks/DownloadScheduler.py
+++ b/module/plugins/hooks/DownloadScheduler.py
@@ -9,7 +9,7 @@ from module.plugins.internal.Addon import Addon
class DownloadScheduler(Addon):
__name__ = "DownloadScheduler"
__type__ = "hook"
- __version__ = "0.25"
+ __version__ = "0.26"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False ),
@@ -28,7 +28,7 @@ class DownloadScheduler(Addon):
def update_schedule(self, schedule=None):
if schedule is None:
- schedule = self.get_config('timetable')
+ schedule = self.config.get('timetable')
schedule = re.findall("(\d{1,2}):(\d{2})[\s]*(-?\d+)",
schedule.lower().replace("full", "-1").replace("none", "0"))
@@ -56,7 +56,7 @@ class DownloadScheduler(Addon):
def set_download_speed(self, speed):
if speed == 0:
- abort = self.get_config('abort')
+ abort = self.config.get('abort')
self.log_info(_("Stopping download server. (Running downloads will %sbe aborted.)") % '' if abort else _('not '))
self.pyload.api.pauseServer()
if abort:
diff --git a/module/plugins/hooks/EventMapper.py b/module/plugins/hooks/EventMapper.py
new file mode 100644
index 000000000..ca1be2bdd
--- /dev/null
+++ b/module/plugins/hooks/EventMapper.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+from module.plugins.internal.Addon import Addon
+
+
+class EventMapper(Addon):
+ __name__ = "EventMapper"
+ __type__ = "hook"
+ __version__ = "0.01"
+ __status__ = "testing"
+
+ __config__ = [("activated", "bool", "Activated", True)]
+
+ __description__ = """Map old events to new events"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def activate(self, *args):
+ self.manager.dispatchEvent("activate", *args)
+
+
+ def exit(self, *args):
+ self.manager.dispatchEvent("exit", *args)
+
+
+ def config_changed(self, *args):
+ self.manager.dispatchEvent("config_changed", *args)
+
+
+ def all_downloads_finished(self, *args):
+ self.manager.dispatchEvent("all_downloads_finished", *args)
+
+
+ def all_downloads_processed(self, *args):
+ self.manager.dispatchEvent("all_downloads_processed", *args)
+
+
+ def links_added(self, *args):
+ self.manager.dispatchEvent("links_added", *args)
+
+
+ def download_preparing(self, *args):
+ self.manager.dispatchEvent("download_preparing", *args)
+
+
+ def download_finished(self, *args):
+ self.manager.dispatchEvent("download_finished", *args)
+
+
+ def download_failed(self, *args):
+ self.manager.dispatchEvent("download_failed", *args)
+
+
+ def package_deleted(self, *args):
+ self.manager.dispatchEvent("package_deleted", *args)
+
+
+ def package_finished(self, *args):
+ self.manager.dispatchEvent("package_finished", *args)
+
+
+ def before_reconnect(self, *args):
+ self.manager.dispatchEvent("before_reconnect", *args)
+
+
+ def after_reconnect(self, *args):
+ self.manager.dispatchEvent("after_reconnect", *args)
+
+
+ def captcha_task(self, *args):
+ self.manager.dispatchEvent("captcha_task", *args)
+
+
+ def captcha_correct(self, *args):
+ self.manager.dispatchEvent("captcha_correct", *args)
+
+
+ def captcha_invalid(self, *args):
+ self.manager.dispatchEvent("captcha_invalid", *args)
diff --git a/module/plugins/hooks/ExpertDecoders.py b/module/plugins/hooks/ExpertDecoders.py
index 55c07d4b9..9b29aa8c5 100644
--- a/module/plugins/hooks/ExpertDecoders.py
+++ b/module/plugins/hooks/ExpertDecoders.py
@@ -2,10 +2,10 @@
from __future__ import with_statement
-import pycurl
+import base64
import uuid
-from base64 import b64encode
+import pycurl
from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getRequest as get_request
@@ -15,7 +15,7 @@ from module.plugins.internal.Addon import Addon, threaded
class ExpertDecoders(Addon):
__name__ = "ExpertDecoders"
__type__ = "hook"
- __version__ = "0.07"
+ __version__ = "0.08"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False),
@@ -32,7 +32,7 @@ class ExpertDecoders(Addon):
def get_credits(self):
- res = self.load(self.API_URL, post={'key': self.get_config('passkey'), 'action': "balance"})
+ res = self.load(self.API_URL, post={'key': self.config.get('passkey'), 'action': "balance"})
if res.isdigit():
self.log_info(_("%s credits left") % res)
@@ -58,8 +58,8 @@ class ExpertDecoders(Addon):
try:
result = self.load(self.API_URL,
post={'action' : "upload",
- 'key' : self.get_config('passkey'),
- 'file' : b64encode(data),
+ 'key' : self.config.get('passkey'),
+ 'file' : base64.b64encode(data),
'gen_task_id': ticket},
req=req)
finally:
@@ -73,10 +73,10 @@ class ExpertDecoders(Addon):
if not task.isTextual():
return False
- if not self.get_config('passkey'):
+ if not self.config.get('passkey'):
return False
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return False
if self.get_credits() > 0:
@@ -93,7 +93,7 @@ class ExpertDecoders(Addon):
try:
res = self.load(self.API_URL,
- post={'action': "refund", 'key': self.get_config('passkey'), 'gen_task_id': task.data['ticket']})
+ post={'action': "refund", 'key': self.config.get('passkey'), 'gen_task_id': task.data['ticket']})
self.log_info(_("Request refund"), res)
except BadHeader, e:
diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py
index 99427dfab..3f4fa74db 100644
--- a/module/plugins/hooks/ExternalScripts.py
+++ b/module/plugins/hooks/ExternalScripts.py
@@ -4,17 +4,17 @@ import os
import subprocess
from module.plugins.internal.Addon import Addon, Expose
-from module.plugins.internal.utils import encode, fs_join
+from module.plugins.internal.misc import encode
class ExternalScripts(Addon):
__name__ = "ExternalScripts"
__type__ = "hook"
- __version__ = "0.55"
+ __version__ = "0.60"
__status__ = "testing"
- __config__ = [("activated", "bool", "Activated" , True ),
- ("lock" , "bool", "Wait for script to terminate", False)]
+ __config__ = [("activated", "bool", "Activated" , True ),
+ ("unlock" , "bool", "Execute script concurrently", False)]
__description__ = """Run external scripts"""
__license__ = "GPLv3"
@@ -32,8 +32,14 @@ class ExternalScripts(Addon):
'package_extract_failed': "package_extract_failed" ,
'package_extracted' : "package_extracted" ,
'all_archives_extracted': "all_archives_extracted" ,
- 'all_archives_processed': "all_archives_processed" }
+ 'all_archives_processed': "all_archives_processed" ,
+ 'pyload_updated' : "pyload_updated" }
+ self.periodical.start(60)
+ self.pyload_start()
+
+
+ def make_folders(self):
folders = ["pyload_start", "pyload_restart", "pyload_stop",
"before_reconnect", "after_reconnect",
"download_preparing", "download_failed", "download_finished",
@@ -43,176 +49,187 @@ class ExternalScripts(Addon):
"all_archives_extracted", "all_archives_processed"]
for folder in folders:
- path = os.path.join("scripts", folder)
- self.init_folder(folder, path)
+ dir = os.path.join("scripts", folder)
- for folder, scripts in self.scripts.items():
- if scripts:
- self.log_info(_("Installed scripts in folder `%s`: %s")
- % (folder, ", ".join(scripts)))
+ if os.path.isdir(dir):
+ continue
- self.pyload_start()
+ try:
+ os.makedirs(dir)
+ except OSError, e:
+ self.log_debug(e, trace=True)
- def init_folder(self, name, path):
- self.scripts[name] = []
- if not os.path.isdir(path):
- try:
- os.makedirs(path)
+ def periodical_task(self):
+ self.make_folders()
- except OSError, e:
- self.log_debug(e)
- return
+ folders = [entry for entry in os.listdir("scripts") \
+ if os.path.isdir(os.path.join("scripts", entry))]
- for filename in os.listdir(path):
- file = fs_join(path, filename)
- if not os.path.isfile(file):
- continue
+ for folder in folders:
+ self.scripts[folder] = []
- if file[0] in ("#", "_") or file.endswith("~") or file.endswith(".swp"):
- continue
+ dirname = os.path.join("scripts", folder)
+
+ for entry in os.listdir(dirname):
+ file = os.path.join(dirname, entry)
+
+ if not os.path.isfile(file):
+ continue
+
+ if file[0] in ("#", "_") or file.endswith("~") or file.endswith(".swp"):
+ continue
+
+ if not os.access(file, os.X_OK):
+ self.log_warning(_("Script `%s` is not executable") % entry)
- if not os.access(file, os.X_OK):
- self.log_warning(_("Script not executable: [%s] %s") % (name, file))
+ self.scripts[folder].append(file)
- self.scripts[name].append(file)
- self.log_info(_("Registered script: [%s] %s") % (name, file))
+ script_names = map(os.path.basename, self.scripts[folder])
+ self.log_info(_("Activated %s scripts: %s")
+ % (folder, ", ".join(script_names) or None))
+
+
+ def call_cmd(self, command, *args, **kwargs):
+ call = [command] + args
+ self.log_debug("EXECUTE " + " ".join(call))
+
+ call = map(encode, call)
+ p = subprocess.Popen(call, bufsize=-1) #@NOTE: output goes to pyload
+
+ return p
@Expose
- def call(self, script, args=[], lock=None):
- if lock is None:
- lock = self.get_config('lock')
+ def call_script(self, folder, *args, **kwargs):
+ scripts = self.scripts.get(folder)
+
+ if folder not in scripts:
+ self.log_debug("Folder `%s` not found" % folder)
+ return
+
+ scripts = self.scripts.get(folder)
+
+ if not scripts:
+ self.log_debug("No script found under folder `%s`" % folder)
+ return
+
+ self.log_info(_("Executing %s scripts...") % folder)
- try:
- script = os.path.abspath(script)
- args = [script] + map(lambda arg: encode(arg) if isinstance(arg, basestring) else encode(str(arg)), args)
+ for file in scripts:
+ try:
+ p = self.call_cmd(file, args)
- self.log_info(_("EXECUTE [%s] %s") % (os.path.dirname(script), args))
- p = subprocess.Popen(args, bufsize=-1) #@NOTE: output goes to pyload
- if lock:
- p.communicate()
+ except Exception, e:
+ self.log_error(_("Runtime error: %s") % file,
+ e or _("Unknown error"))
- except Exception, e:
- self.log_error(_("Runtime error: %s") % script,
- e or _("Unknown error"))
+ else:
+ if kwargs.get('lock') or not self.config.get('unlock'):
+ p.communicate()
- def _call(self, folder, args=[], lock=None):
- for script in self.scripts[folder]:
- self.call(script, args, lock)
+ def pyload_updated(self, etag):
+ self.call_script("pyload_updated", etag)
def pyload_start(self):
- self._call('pyload_start')
+ self.call_script('pyload_start')
def exit(self):
- folder = "pyload_restart" if self.pyload.do_restart else "pyload_stop"
- self._call(folder, lock=True)
+ event = "restart" if self.pyload.do_restart else "stop"
+ self.call_script("pyload_" + event, lock=True)
def before_reconnect(self, ip):
- args = [ip]
- self._call("before_reconnect", args)
+ self.call_script("before_reconnect", ip)
def after_reconnect(self, ip, oldip):
- args = [ip, oldip]
- self._call("after_reconnect", args)
+ self.call_script("after_reconnect", ip, oldip)
def download_preparing(self, pyfile):
args = [pyfile.id, pyfile.name, None, pyfile.pluginname, pyfile.url]
- self._call("download_preparing", args)
+ self.call_script("download_preparing", *args)
def download_failed(self, pyfile):
- if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pyfile.package().folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
-
- file = fs_join(dl_folder, pyfile.name)
+ file = pyfile.plugin.last_download
args = [pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url]
- self._call("download_failed", args)
+ self.call_script("download_failed", *args)
def download_finished(self, pyfile):
- if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pyfile.package().folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
-
- file = fs_join(dl_folder, pyfile.name)
+ file = pyfile.plugin.last_download
args = [pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url]
- self._call("download_finished", args)
+ self.call_script("download_finished", *args)
def archive_extract_failed(self, pyfile, archive):
args = [pyfile.id, pyfile.name, archive.filename, archive.out, archive.files]
- self._call("archive_extract_failed", args)
+ self.call_script("archive_extract_failed", *args)
def archive_extracted(self, pyfile, archive):
args = [pyfile.id, pyfile.name, archive.filename, archive.out, archive.files]
- self._call("archive_extracted", args)
+ self.call_script("archive_extracted", *args)
def package_finished(self, pypack):
+ dl_folder = self.pyload.config.get("general", "download_folder")
+
if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
+ dl_folder = os.path.join(dl_folder, pypack.folder)
args = [pypack.id, pypack.name, dl_folder, pypack.password]
- self._call("package_finished", args)
+ self.call_script("package_finished", *args)
def package_deleted(self, pid):
+ dl_folder = self.pyload.config.get("general", "download_folder")
pdata = self.pyload.api.getPackageInfo(pid)
if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pdata.folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
+ dl_folder = os.path.join(dl_folder, pdata.folder)
args = [pdata.pid, pdata.name, dl_folder, pdata.password]
- self._call("package_deleted", args)
+ self.call_script("package_deleted", *args)
def package_extract_failed(self, pypack):
+ dl_folder = self.pyload.config.get("general", "download_folder")
+
if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
+ dl_folder = os.path.join(dl_folder, pypack.folder)
args = [pypack.id, pypack.name, dl_folder, pypack.password]
- self._call("package_extract_failed", args)
+ self.call_script("package_extract_failed", *args)
def package_extracted(self, pypack):
+ dl_folder = self.pyload.config.get("general", "download_folder")
+
if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder)
- else:
- dl_folder = self.pyload.config.get("general", "download_folder")
+ dl_folder = os.path.join(dl_folder, pypack.folder)
args = [pypack.id, pypack.name, dl_folder]
- self._call("package_extracted", args)
+ self.call_script("package_extracted", *args)
def all_downloads_finished(self):
- self._call("all_downloads_finished")
+ self.call_script("all_downloads_finished")
def all_downloads_processed(self):
- self._call("all_downloads_processed")
+ self.call_script("all_downloads_processed")
def all_archives_extracted(self):
- self._call("all_archives_extracted")
+ self.call_script("all_archives_extracted")
def all_archives_processed(self):
- self._call("all_archives_processed")
+ self.call_script("all_archives_processed")
diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py
index c001000c8..a60205f20 100644
--- a/module/plugins/hooks/ExtractArchive.py
+++ b/module/plugins/hooks/ExtractArchive.py
@@ -51,7 +51,7 @@ except ImportError:
from module.plugins.internal.Addon import Addon, Expose, threaded
from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError
-from module.plugins.internal.utils import encode, exists, fs_join, replace_patterns, uniqify
+from module.plugins.internal.misc import encode, exists, fsjoin, replace_patterns, uniqify
class ArchiveQueue(object):
@@ -98,8 +98,8 @@ class ArchiveQueue(object):
class ExtractArchive(Addon):
__name__ = "ExtractArchive"
__type__ = "hook"
- __version__ = "1.53"
- __status__ = "testing"
+ __version__ = "1.54"
+ __status__ = "broken"
__config__ = [("activated" , "bool" , "Activated" , True ),
("fullpath" , "bool" , "Extract with full paths" , True ),
@@ -142,14 +142,14 @@ class ExtractArchive(Addon):
def activate(self):
- for p in ("UnRar", "SevenZip", "UnZip"):
+ for p in ("UnRar", "SevenZip", "UnZip", "UnTar"):
try:
module = self.pyload.pluginManager.loadModule("internal", p)
klass = getattr(module, p)
if klass.find():
self.extractors.append(klass)
if klass.REPAIR:
- self.repair = self.get_config('repair')
+ self.repair = self.config.get('repair')
except OSError, e:
if e.errno == 2:
@@ -206,7 +206,7 @@ class ExtractArchive(Addon):
"""
for id in ids:
self.queue.add(id)
- if not self.get_config('waitall') and not self.extracting:
+ if not self.config.get('waitall') and not self.extracting:
self.extract_queued()
@@ -216,13 +216,13 @@ class ExtractArchive(Addon):
def package_finished(self, pypack):
self.queue.add(pypack.id)
- if not self.get_config('waitall') and not self.extracting:
+ if not self.config.get('waitall') and not self.extracting:
self.extract_queued()
def all_downloads_processed(self):
self.last_package = True
- if self.get_config('waitall') and not self.extracting:
+ if self.config.get('waitall') and not self.extracting:
self.extract_queued()
@@ -237,16 +237,16 @@ class ExtractArchive(Addon):
toList = lambda string: string.replace(' ', '').replace(',', '|').replace(';', '|').split('|')
- destination = self.get_config('destination')
- subfolder = self.get_config('subfolder')
- fullpath = self.get_config('fullpath')
- overwrite = self.get_config('overwrite')
- priority = self.get_config('priority')
- recursive = self.get_config('recursive')
- keepbroken = self.get_config('keepbroken')
+ destination = self.config.get('destination')
+ subfolder = self.config.get('subfolder')
+ fullpath = self.config.get('fullpath')
+ overwrite = self.config.get('overwrite')
+ priority = self.config.get('priority')
+ recursive = self.config.get('recursive')
+ keepbroken = self.config.get('keepbroken')
- extensions = [x.lstrip('.').lower() for x in toList(self.get_config('extensions'))]
- excludefiles = toList(self.get_config('excludefiles'))
+ extensions = [x.lstrip('.').lower() for x in toList(self.config.get('extensions'))]
+ excludefiles = toList(self.config.get('excludefiles'))
if extensions:
self.log_debug("Use for extensions: %s" % "|.".join(extensions))
@@ -267,18 +267,18 @@ class ExtractArchive(Addon):
self.log_info(_("Check package: %s") % pypack.name)
#: Determine output folder
- out = fs_join(dl_folder, pypack.folder, destination, "") #: Force trailing slash
+ out = fsjoin(dl_folder, pypack.folder, destination, "") #: Force trailing slash
if subfolder:
- out = fs_join(out, pypack.folder)
+ out = fsjoin(out, pypack.folder)
if not exists(out):
os.makedirs(out)
matched = False
success = True
- files_ids = dict((pylink['name'], ((fs_join(dl_folder, pypack.folder, pylink['name'])), pylink['id'], out)) for pylink \
- in sorted(pypack.getChildren().values(), key=lambda k: k['name'])).values() #: Remove duplicates
+ files_ids = dict((fdata['name'], ((fsjoin(dl_folder, pypack.folder, fdata['name'])), fid, out)) for fid, fdata \
+ in sorted(pypack.getChildren().values(), key=lambda k: k['name'])).items() #: Remove duplicates
#: Check as long there are unseen files
while files_ids:
@@ -338,7 +338,7 @@ class ExtractArchive(Addon):
self.set_permissions(file)
for filename in new_files:
- file = encode(fs_join(os.path.dirname(archive.filename), filename))
+ file = encode(fsjoin(os.path.dirname(archive.filename), filename))
if not exists(file):
self.log_debug("New file %s does not exists" % filename)
continue
@@ -383,7 +383,7 @@ class ExtractArchive(Addon):
encrypted = False
try:
self.log_debug("Password: %s" % (password or "None provided"))
- passwords = uniqify([password] + self.get_passwords(False)) if self.get_config('usepasswordfile') else [password]
+ passwords = uniqify([password] + self.get_passwords(False)) if self.config.get('usepasswordfile') else [password]
for pw in passwords:
try:
pyfile.setCustomStatus(_("archive testing"))
@@ -410,7 +410,7 @@ class ExtractArchive(Addon):
repaired = archive.repair()
pyfile.setProgress(100)
- if not repaired and not self.get_config('keepbroken'):
+ if not repaired and not self.config.get('keepbroken'):
raise CRCError("Archive damaged")
else:
@@ -427,7 +427,7 @@ class ExtractArchive(Addon):
pyfile.setCustomStatus(_("archive extracting"))
pyfile.setProgress(0)
- if not encrypted or not self.get_config('usepasswordfile'):
+ if not encrypted or not self.config.get('usepasswordfile'):
self.log_debug("Extracting using password: %s" % (password or "None"))
archive.extract(password)
else:
@@ -450,10 +450,10 @@ class ExtractArchive(Addon):
delfiles = archive.items()
self.log_debug("Would delete: " + ", ".join(delfiles))
- if self.get_config('delete'):
+ if self.config.get('delete'):
self.log_info(_("Deleting %s files") % len(delfiles))
- deltotrash = self.get_config('deltotrash')
+ deltotrash = self.config.get('deltotrash')
for f in delfiles:
file = encode(f)
if not exists(file):
@@ -523,7 +523,7 @@ class ExtractArchive(Addon):
try:
passwords = []
- file = encode(self.get_config('passwordfile'))
+ file = encode(self.config.get('passwordfile'))
with open(file) as f:
for pw in f.read().splitlines():
passwords.append(pw)
@@ -552,7 +552,7 @@ class ExtractArchive(Addon):
try:
self.passwords = uniqify([password] + self.passwords)
- file = encode(self.get_config('passwordfile'))
+ file = encode(self.config.get('passwordfile'))
with open(file, "wb") as f:
for pw in self.passwords:
f.write(pw + '\n')
diff --git a/module/plugins/hooks/HotFolder.py b/module/plugins/hooks/HotFolder.py
index c89083fb1..26217c0f8 100644
--- a/module/plugins/hooks/HotFolder.py
+++ b/module/plugins/hooks/HotFolder.py
@@ -3,17 +3,16 @@
from __future__ import with_statement
import os
-import shutil
import time
from module.plugins.internal.Addon import Addon
-from module.plugins.internal.utils import encode, fs_join
+from module.plugins.internal.misc import encode, fsjoin, move_tree
class HotFolder(Addon):
__name__ = "HotFolder"
__type__ = "hook"
- __version__ = "0.20"
+ __version__ = "0.21"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False ),
@@ -28,18 +27,18 @@ class HotFolder(Addon):
def activate(self):
- self.start_periodical(30, threaded=True)
+ self.periodical.start(30, threaded=True)
- def periodical(self):
- folder = encode(self.get_config('folder'))
- file = encode(self.get_config('file'))
+ def periodical_task(self):
+ folder = encode(self.config.get('folder'))
+ file = encode(self.config.get('file'))
try:
if not os.path.isdir(os.path.join(folder, "finished")):
os.makedirs(os.path.join(folder, "finished"))
- if self.get_config('watchfile'):
+ if self.config.get('watchfile'):
with open(file, "a+") as f:
f.seek(0)
content = f.read().strip()
@@ -50,7 +49,7 @@ class HotFolder(Addon):
name = "%s_%s.txt" % (file, time.strftime("%H-%M-%S_%d%b%Y"))
- with open(fs_join(folder, "finished", name), "wb") as f:
+ with open(fsjoin(folder, "finished", name), "wb") as f:
f.write(content)
self.pyload.api.addPackage(f.name, [f.name], 1)
@@ -61,8 +60,8 @@ class HotFolder(Addon):
if not os.path.isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."):
continue
- newpath = os.path.join(folder, "finished", "tmp_" + f if self.get_config('delete') else f)
- shutil.move(path, newpath)
+ newpath = os.path.join(folder, "finished", "tmp_" + f if self.config.get('delete') else f)
+ move_tree(path, newpath)
self.log_info(_("Added %s from HotFolder") % f)
self.pyload.api.addPackage(f, [newpath], 1)
diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRC.py
index 1f337d686..7dec4b798 100644
--- a/module/plugins/hooks/IRCInterface.py
+++ b/module/plugins/hooks/IRC.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
-import pycurl
import re
import select
import socket
@@ -8,17 +7,19 @@ import ssl
import time
import traceback
+import pycurl
+
from threading import Thread
from module.Api import PackageDoesNotExists, FileDoesNotExists
-from module.plugins.internal.Addon import Addon
-from module.utils import formatSize
+from module.plugins.internal.Notifier import Notifier
+from module.internal.misc import formatSize
-class IRCInterface(Thread, Addon):
- __name__ = "IRCInterface"
+class IRC(Thread, Notifier):
+ __name__ = "IRC"
__type__ = "hook"
- __version__ = "0.18"
+ __version__ = "0.19"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False ),
@@ -54,7 +55,7 @@ class IRCInterface(Thread, Addon):
def package_finished(self, pypack):
try:
- if self.get_config('info_pack'):
+ if self.config.get('info_pack'):
self.response(_("Package finished: %s") % pypack.name)
except Exception:
@@ -63,7 +64,7 @@ class IRCInterface(Thread, Addon):
def download_finished(self, pyfile):
try:
- if self.get_config('info_file'):
+ if self.config.get('info_file'):
self.response(
_("Download finished: %(name)s @ %(plugin)s ") % {'name': pyfile.name, 'plugin': pyfile.pluginname})
@@ -72,7 +73,7 @@ class IRCInterface(Thread, Addon):
def captcha_task(self, task):
- if self.get_config('captcha') and task.isTextual():
+ if self.config.get('captcha') and task.isTextual():
task.handler.append(self)
task.setWaiting(60)
@@ -87,16 +88,16 @@ class IRCInterface(Thread, Addon):
def run(self):
#: Connect to IRC etc.
self.sock = socket.socket()
- host = self.get_config('host')
- self.sock.connect((host, self.get_config('port')))
+ host = self.config.get('host')
+ self.sock.connect((host, self.config.get('port')))
- if self.get_config('ssl'):
+ if self.config.get('ssl'):
self.sock = ssl.wrap_socket(self.sock, cert_reqs=ssl.CERT_NONE) #@TODO: support certificate
- nick = self.get_config('nick')
+ nick = self.config.get('nick')
self.sock.send("NICK %s\r\n" % nick)
self.sock.send("USER %s %s bla :%s\r\n" % (nick, host, nick))
- for t in self.get_config('owner').split():
+ for t in self.config.get('owner').split():
if t.strip().startswith("#"):
self.sock.send("JOIN %s\r\n" % t.strip())
self.log_info(_("Connected to"), host)
@@ -151,10 +152,10 @@ class IRCInterface(Thread, Addon):
def handle_events(self, msg):
- if not msg['origin'].split("!", 1)[0] in self.get_config('owner').split():
+ if not msg['origin'].split("!", 1)[0] in self.config.get('owner').split():
return
- if msg['target'].split("!", 1)[0] is not self.get_config('nick'):
+ if msg['target'].split("!", 1)[0] is not self.config.get('nick'):
return
if msg['action'] != "PRIVMSG":
@@ -197,7 +198,7 @@ class IRCInterface(Thread, Addon):
def response(self, msg, origin=""):
if origin == "":
- for t in self.get_config('owner').split():
+ for t in self.config.get('owner').split():
self.sock.send("PRIVMSG %s :%s\r\n" % (t.strip(), msg))
else:
self.sock.send("PRIVMSG %s :%s\r\n" % (origin.split("!", 1)[0], msg))
@@ -218,7 +219,7 @@ class IRCInterface(Thread, Addon):
lines = ["ID - Name - Status - Speed - ETA - Progress"]
for data in downloads:
- if data.status == 5:
+ if data.status is 5:
temp_progress = data.format_wait
else:
temp_progress = "%d%% (%s)" % (data.percent, data.format_size)
@@ -236,25 +237,25 @@ class IRCInterface(Thread, Addon):
def event_queue(self, args):
- ps = self.pyload.api.getQueueData()
+ pdata = self.pyload.api.getQueueData()
- if not ps:
+ if not pdata:
return ["INFO: There are no packages in queue."]
lines = []
- for pack in ps:
+ for pack in pdata:
lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.links)))
return lines
def event_collector(self, args):
- ps = self.pyload.api.getCollectorData()
- if not ps:
+ pdata = self.pyload.api.getCollectorData()
+ if not pdata:
return ["INFO: No packages in collector!"]
lines = []
- for pack in ps:
+ for pack in pdata:
lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.links)))
return lines
diff --git a/module/plugins/hooks/ImageTyperz.py b/module/plugins/hooks/ImageTyperz.py
index 656ad0c25..5afeb4a78 100644
--- a/module/plugins/hooks/ImageTyperz.py
+++ b/module/plugins/hooks/ImageTyperz.py
@@ -2,10 +2,10 @@
from __future__ import with_statement
-import pycurl
+import base64
import re
-from base64 import b64encode
+import pycurl
from module.network.RequestFactory import getRequest as get_request
from module.plugins.internal.Addon import Addon, threaded
@@ -32,7 +32,7 @@ class ImageTyperzException(Exception):
class ImageTyperz(Addon):
__name__ = "ImageTyperz"
__type__ = "hook"
- __version__ = "0.09"
+ __version__ = "0.10"
__status__ = "testing"
__config__ = [("activated" , "bool" , "Activated" , False),
@@ -54,8 +54,8 @@ class ImageTyperz(Addon):
def get_credits(self):
res = self.load(self.GETCREDITS_URL,
post={'action': "REQUESTBALANCE",
- 'username': self.get_config('username'),
- 'password': self.get_config('password')})
+ 'username': self.config.get('username'),
+ 'password': self.config.get('password')})
if res.startswith('ERROR'):
raise ImageTyperzException(res)
@@ -77,19 +77,19 @@ class ImageTyperz(Addon):
try:
#@NOTE: Workaround multipart-post bug in HTTPRequest.py
- if re.match("^\w*$", self.get_config('password')):
+ if re.match("^\w*$", self.config.get('password')):
multipart = True
data = (pycurl.FORM_FILE, captcha)
else:
multipart = False
with open(captcha, 'rb') as f:
data = f.read()
- data = b64encode(data)
+ data = base64.b64encode(data)
res = self.load(self.SUBMIT_URL,
post={'action': "UPLOADCAPTCHA",
- 'username': self.get_config('username'),
- 'password': self.get_config('password'), 'file': data},
+ 'username': self.config.get('username'),
+ 'password': self.config.get('password'), 'file': data},
multipart=multipart,
req=req)
finally:
@@ -99,7 +99,7 @@ class ImageTyperz(Addon):
raise ImageTyperzException(res)
else:
data = res.split('|')
- if len(data) == 2:
+ if len(data) is 2:
ticket, result = data
else:
raise ImageTyperzException("Unknown response: %s" % res)
@@ -114,10 +114,10 @@ class ImageTyperz(Addon):
if not task.isTextual():
return False
- if not self.get_config('username') or not self.get_config('password'):
+ if not self.config.get('username') or not self.config.get('password'):
return False
- if self.pyload.isClientConnected() and self.get_config('check_client'):
+ if self.pyload.isClientConnected() and self.config.get('check_client'):
return False
if self.get_credits() > 0:
@@ -134,8 +134,8 @@ class ImageTyperz(Addon):
if task.data['service'] is self.classname and "ticket" in task.data:
res = self.load(self.RESPOND_URL,
post={'action': "SETBADIMAGE",
- 'username': self.get_config('username'),
- 'password': self.get_config('password'),
+ 'username': self.config.get('username'),
+ 'password': self.config.get('password'),
'imageid': task.data['ticket']})
if res == "SUCCESS":
diff --git a/module/plugins/hooks/JustPremium.py b/module/plugins/hooks/JustPremium.py
index 3f7388020..2492498cb 100644
--- a/module/plugins/hooks/JustPremium.py
+++ b/module/plugins/hooks/JustPremium.py
@@ -8,7 +8,7 @@ from module.plugins.internal.Addon import Addon
class JustPremium(Addon):
__name__ = "JustPremium"
__type__ = "hook"
- __version__ = "0.25"
+ __version__ = "0.26"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False),
@@ -37,9 +37,9 @@ class JustPremium(Addon):
and hosterdict[hoster]['new_name'] in premiumplugins)
excluded = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'),
- self.get_config('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
+ self.config.get('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
included = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'),
- self.get_config('included').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
+ self.config.get('included').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
hosterlist = (premiumplugins | multihosters).union(excluded).difference(included)
diff --git a/module/plugins/hooks/LogMarker.py b/module/plugins/hooks/LogMarker.py
index 829db4d41..80f7b17fb 100644
--- a/module/plugins/hooks/LogMarker.py
+++ b/module/plugins/hooks/LogMarker.py
@@ -3,13 +3,13 @@
import datetime
from module.plugins.internal.Addon import Addon, Expose
-from module.plugins.internal.utils import seconds_to_nexthour
+from module.plugins.internal.misc import seconds_to_nexthour
class LogMarker(Addon):
__name__ = "LogMarker"
__type__ = "hook"
- __version__ = "0.04"
+ __version__ = "0.05"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False),
@@ -22,16 +22,16 @@ class LogMarker(Addon):
def activated(self):
- self.start_periodical(1 * 60 * 60 - 1, delay=seconds_to_nexthour(strict=True) - 1)
+ self.periodical.start(1 * 60 * 60 - 1, delay=seconds_to_nexthour(strict=True) - 1)
- def periodical(self):
- if self.get_config('mark_day') and datetime.datetime.today().hour is 0:
+ def periodical_task(self):
+ if self.config.get('mark_day') and datetime.datetime.today().hour is 0:
self.log_info("------------------------------------------------")
self.log_info(_("------------------- DAY MARK -------------------"))
self.log_info("------------------------------------------------")
- elif self.get_config('mark_hour'):
+ elif self.config.get('mark_hour'):
self.log_info("------------------------------------------------")
self.log_info(_("------------------- HOUR MARK ------------------"))
self.log_info("------------------------------------------------")
diff --git a/module/plugins/hooks/MergeFiles.py b/module/plugins/hooks/MergeFiles.py
index dbe7b1f5f..963f8c15b 100644
--- a/module/plugins/hooks/MergeFiles.py
+++ b/module/plugins/hooks/MergeFiles.py
@@ -6,13 +6,13 @@ import os
import re
from module.plugins.internal.Addon import Addon, threaded
-from module.plugins.internal.utils import fs_join
+from module.plugins.internal.misc import fsjoin
class MergeFiles(Addon):
__name__ = "MergeFiles"
__type__ = "hook"
- __version__ = "0.18"
+ __version__ = "0.19"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated", True)]
@@ -40,12 +40,12 @@ class MergeFiles(Addon):
dl_folder = self.pyload.config.get("general", "download_folder")
if self.pyload.config.get("general", "folder_per_package"):
- dl_folder = fs_join(dl_folder, pack.folder)
+ dl_folder = fsjoin(dl_folder, pack.folder)
for name, file_list in files.items():
self.log_info(_("Starting merging of"), name)
- with open(fs_join(dl_folder, name), "wb") as final_file:
+ with open(fsjoin(dl_folder, name), "wb") as final_file:
for splitted_file in file_list:
self.log_debug("Merging part", splitted_file)
@@ -54,7 +54,7 @@ class MergeFiles(Addon):
pyfile.setStatus("processing")
try:
- with open(fs_join(dl_folder, splitted_file), "rb") as s_file:
+ with open(fsjoin(dl_folder, splitted_file), "rb") as s_file:
size_written = 0
s_file_size = int(os.path.getsize(os.path.join(dl_folder, splitted_file)))
while True:
diff --git a/module/plugins/hooks/MultiHome.py b/module/plugins/hooks/MultiHome.py
index 353753c1a..c8c5f4fa7 100644
--- a/module/plugins/hooks/MultiHome.py
+++ b/module/plugins/hooks/MultiHome.py
@@ -44,7 +44,7 @@ class Interface(object):
class MultiHome(Addon):
__name__ = "MultiHome"
__type__ = "hook"
- __version__ = "0.15"
+ __version__ = "0.16"
__status__ = "testing"
__config__ = [("activated" , "bool", "Activated" , False ),
@@ -59,11 +59,11 @@ class MultiHome(Addon):
self.register = {}
self.interfaces = []
- self.parse_interfaces(self.get_config('interfaces').split(";"))
+ self.parse_interfaces(self.config.get('interfaces').split(";"))
if not self.interfaces:
self.parse_interfaces([self.pyload.config.get("download", "interface")])
- self.set_config("interfaces", self.to_config())
+ self.config.set("interfaces", self.to_config())
def to_config(self):
diff --git a/module/plugins/hooks/PushBullet.py b/module/plugins/hooks/PushBullet.py
index 6cf7dc173..47a0f594e 100644
--- a/module/plugins/hooks/PushBullet.py
+++ b/module/plugins/hooks/PushBullet.py
@@ -9,19 +9,22 @@ from module.plugins.internal.Notifier import Notifier
class PushBullet(Notifier):
__name__ = "PushBullet"
__type__ = "hook"
- __version__ = "0.02"
+ __version__ = "0.04"
__status__ = "testing"
- __config__ = [("activated" , "bool", "Activated" , False),
- ("tokenkey" , "str" , "Access Token" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify packages processed" , True ),
- ("notifyupdate" , "bool", "Notify plugin updates" , True ),
- ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ),
- ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ),
- ("sendpermin" , "int" , "Max notifications per minute" , 12 ),
- ("ignoreclient" , "bool", "Send notifications if client is connected", False)]
+ __config__ = [("activated" , "bool", "Activated" , False),
+ ("tokenkey" , "str" , "Access Token" , "" ),
+ ("captcha" , "bool", "Notify captcha request" , True ),
+ ("reconnection" , "bool", "Notify reconnection request" , False),
+ ("downloadfinished", "bool", "Notify download finished" , True ),
+ ("downloadfailed" , "bool", "Notify download failed" , True ),
+ ("packagefinished" , "bool", "Notify package finished" , True ),
+ ("packagefailed" , "bool", "Notify package failed" , True ),
+ ("update" , "bool", "Notify pyLoad update" , False),
+ ("exit" , "bool", "Notify pyLoad shutdown/restart" , False),
+ ("sendinterval" , "int" , "Interval in seconds between notifications", 1 ),
+ ("sendpermin" , "int" , "Max notifications per minute" , 60 ),
+ ("ignoreclient" , "bool", "Send notifications if client is connected", True )]
__description__ = """Send push notifications to your phone using pushbullet.com"""
__license__ = "GPLv3"
@@ -29,7 +32,7 @@ class PushBullet(Notifier):
def get_key(self):
- return self.get_config('tokenkey')
+ return self.config.get('tokenkey')
def send(self, event, msg, key):
diff --git a/module/plugins/hooks/PushOver.py b/module/plugins/hooks/PushOver.py
index 5d5e927ac..418f7a133 100644
--- a/module/plugins/hooks/PushOver.py
+++ b/module/plugins/hooks/PushOver.py
@@ -8,20 +8,23 @@ from module.plugins.internal.Notifier import Notifier
class PushOver(Notifier):
__name__ = "PushOver"
__type__ = "hook"
- __version__ = "0.04"
+ __version__ = "0.06"
__status__ = "testing"
- __config__ = [("activated" , "bool", "Activated" , False),
- ("tokenkey" , "str" , "Token key" , "" ),
- ("userkey" , "str" , "User key" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify packages processed" , True ),
- ("notifyupdate" , "bool", "Notify plugin updates" , True ),
- ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ),
- ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ),
- ("sendpermin" , "int" , "Max notifications per minute" , 12 ),
- ("ignoreclient" , "bool", "Send notifications if client is connected", False)]
+ __config__ = [("activated" , "bool", "Activated" , False),
+ ("tokenkey" , "str" , "Token key" , "" ),
+ ("userkey" , "str" , "User key" , "" ),
+ ("captcha" , "bool", "Notify captcha request" , True ),
+ ("reconnection" , "bool", "Notify reconnection request" , False),
+ ("downloadfinished", "bool", "Notify download finished" , True ),
+ ("downloadfailed" , "bool", "Notify download failed" , True ),
+ ("packagefinished" , "bool", "Notify package finished" , True ),
+ ("packagefailed" , "bool", "Notify package failed" , True ),
+ ("update" , "bool", "Notify pyLoad update" , False),
+ ("exit" , "bool", "Notify pyLoad shutdown/restart" , False),
+ ("sendinterval" , "int" , "Interval in seconds between notifications", 1 ),
+ ("sendpermin" , "int" , "Max notifications per minute" , 60 ),
+ ("ignoreclient" , "bool", "Send notifications if client is connected", True )]
__description__ = """Send push notifications to your phone using pushover.net"""
__license__ = "GPLv3"
@@ -29,7 +32,7 @@ class PushOver(Notifier):
def get_key(self):
- return self.get_config('tokenkey'), self.get_config('userkey')
+ return self.config.get('tokenkey'), self.config.get('userkey')
def send(self, event, msg, key):
diff --git a/module/plugins/hooks/RestartFailed.py b/module/plugins/hooks/RestartFailed.py
index 0e35c4629..62298ea14 100644
--- a/module/plugins/hooks/RestartFailed.py
+++ b/module/plugins/hooks/RestartFailed.py
@@ -6,7 +6,7 @@ from module.plugins.internal.Addon import Addon
class RestartFailed(Addon):
__name__ = "RestartFailed"
__type__ = "hook"
- __version__ = "1.63"
+ __version__ = "1.64"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False),
@@ -17,13 +17,10 @@ class RestartFailed(Addon):
__authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
- PERIODICAL_INTERVAL = 15 * 60 #: 15 minutes
-
-
- def periodical(self):
+ def periodical_task(self):
self.log_info(_("Restarting all failed downloads..."))
self.pyload.api.restartFailed()
def activate(self):
- self.set_interval(self.get_config('interval') * 60)
+ self.periodical.start(self.config.get('interval') * 60)
diff --git a/module/plugins/hooks/SkipRev.py b/module/plugins/hooks/SkipRev.py
index 6ce1750d3..429737e94 100644
--- a/module/plugins/hooks/SkipRev.py
+++ b/module/plugins/hooks/SkipRev.py
@@ -1,9 +1,6 @@
# -*- coding: utf-8 -*-
import re
-import urllib
-
-from types import MethodType
from module.PyFile import PyFile
from module.plugins.internal.Addon import Addon
@@ -12,7 +9,7 @@ from module.plugins.internal.Addon import Addon
class SkipRev(Addon):
__name__ = "SkipRev"
__type__ = "hook"
- __version__ = "0.35"
+ __version__ = "0.36"
__status__ = "testing"
__config__ = [("activated", "bool" , "Activated" , False ),
@@ -28,17 +25,18 @@ class SkipRev(Addon):
return pyfile.pluginclass.get_info(pyfile.url)['name']
- def _pyfile(self, link):
+ def _create_pyFile(self, data):
+ pylink = self.pyload.api._convertPyFile(data)
return PyFile(self.pyload.files,
- link.fid,
- link.url,
- link.name,
- link.size,
- link.status,
- link.error,
- link.plugin,
- link.packageID,
- link.order)
+ pylink.fid,
+ pylink.url,
+ pylink.name,
+ pylink.size,
+ pylink.status,
+ pylink.error,
+ pylink.plugin,
+ pylink.packageID,
+ pylink.order)
def download_preparing(self, pyfile):
@@ -47,14 +45,14 @@ class SkipRev(Addon):
if pyfile.statusname is _("unskipped") or not name.endswith(".rev") or not ".part" in name:
return
- revtokeep = -1 if self.get_config('mode') == "Auto" else self.get_config('revtokeep')
+ revtokeep = -1 if self.config.get('mode') == "Auto" else self.config.get('revtokeep')
if revtokeep:
status_list = (1, 4, 8, 9, 14) if revtokeep < 0 else (1, 3, 4, 8, 9, 14)
pyname = re.compile(r'%s\.part\d+\.rev$' % name.rsplit('.', 2)[0].replace('.', '\.'))
- queued = [True for link in self.pyload.api.getPackageData(pyfile.package().id).links \
- if link.status not in status_list and pyname.match(link.name)].count(True)
+ queued = [True for fid, fdata in pyfile.package().getChildren().items() \
+ if fdata['status'] not in status_list and pyname.match(fdata['name'])].count(True)
if not queued or queued < revtokeep: #: Keep one rev at least in auto mode
return
@@ -63,26 +61,25 @@ class SkipRev(Addon):
def download_failed(self, pyfile):
- #: Check if pyfile is still "failed", maybe might has been restarted in meantime
- if pyfile.status != 8 or pyfile.name.rsplit('.', 1)[-1].strip() not in ("rar", "rev"):
+ if pyfile.name.rsplit('.', 1)[-1].strip() not in ("rar", "rev"):
return
- revtokeep = -1 if self.get_config('mode') == "Auto" else self.get_config('revtokeep')
+ revtokeep = -1 if self.config.get('mode') == "Auto" else self.config.get('revtokeep')
if not revtokeep:
return
pyname = re.compile(r'%s\.part\d+\.rev$' % pyfile.name.rsplit('.', 2)[0].replace('.', '\.'))
- for link in self.pyload.api.getPackageData(pyfile.package().id).links:
- if link.status is 4 and pyname.match(link.name):
- pylink = self._pyfile(link)
+ for fid, fdata in pyfile.package().getChildren().items():
+ if fdata['status'] is 4 and pyname.match(fdata['name']):
+ pyfile_new = self._create_pyFile(fdata)
if revtokeep > -1 or pyfile.name.endswith(".rev"):
- pylink.setStatus("queued")
+ pyfile_new.setStatus("queued")
else:
- pylink.setCustomStatus(_("unskipped"), "queued")
+ pyfile_new.setCustomStatus(_("unskipped"), "queued")
self.pyload.files.save()
- pylink.release()
+ pyfile_new.release()
return
diff --git a/module/plugins/hooks/TransmissionRPC.py b/module/plugins/hooks/TransmissionRPC.py
index 7914d5c44..f0ef2e9b1 100644
--- a/module/plugins/hooks/TransmissionRPC.py
+++ b/module/plugins/hooks/TransmissionRPC.py
@@ -5,19 +5,19 @@ import re
import pycurl
-from module.plugins.internal.utils import json
from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getRequest as get_request
from module.plugins.internal.Addon import Addon
+from module.plugins.internal.misc import json
class TransmissionRPC(Addon):
__name__ = "TransmissionRPC"
__type__ = "hook"
- __version__ = "0.16"
+ __version__ = "0.17"
__status__ = "testing"
- __pattern__ = r"https?://.+\.torrent|magnet:\?.+"
+ __pattern__ = r'https?://.+\.torrent|magnet:\?.+'
__config__ = [("activated", "bool", "Activated" , False ),
("rpc_url" , "str" , "Transmission RPC URL", "http://127.0.0.1:9091/transmission/rpc")]
@@ -41,7 +41,7 @@ class TransmissionRPC(Addon):
def send_to_transmission(self, url):
- transmission_rpc_url = self.get_config('rpc_url')
+ transmission_rpc_url = self.config.get('rpc_url')
client_request_id = self.classname + "".join(random.choice('0123456789ABCDEF') for _i in xrange(4))
req = get_request()
@@ -53,7 +53,7 @@ class TransmissionRPC(Addon):
req=req)
except Exception, e:
- if isinstance(e, BadHeader) and e.code == 409:
+ if isinstance(e, BadHeader) and e.code is 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])
diff --git a/module/plugins/hooks/UnSkipOnFail.py b/module/plugins/hooks/UnSkipOnFail.py
index 6842cbc51..db43bca2b 100644
--- a/module/plugins/hooks/UnSkipOnFail.py
+++ b/module/plugins/hooks/UnSkipOnFail.py
@@ -7,7 +7,7 @@ from module.plugins.internal.Addon import Addon
class UnSkipOnFail(Addon):
__name__ = "UnSkipOnFail"
__type__ = "hook"
- __version__ = "0.10"
+ __version__ = "0.11"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated", True)]
@@ -18,10 +18,6 @@ class UnSkipOnFail(Addon):
def download_failed(self, pyfile):
- #: Check if pyfile is still "failed", maybe might has been restarted in meantime
- if pyfile.status != 8:
- return
-
msg = _("Looking for skipped duplicates of: %s (pid:%s)")
self.log_info(msg % (pyfile.name, pyfile.package().id))
@@ -36,12 +32,12 @@ class UnSkipOnFail(Addon):
#: It creates a temporary PyFile object using
#: "link" data, changes its status, and tells
#: The pyload.files-manager to save its data.
- pylink = self._pyfile(link)
+ pyfile_new = self._create_pyFile(link)
- pylink.setCustomStatus(_("unskipped"), "queued")
+ pyfile_new.setCustomStatus(_("unskipped"), "queued")
self.pyload.files.save()
- pylink.release()
+ pyfile_new.release()
else:
self.log_info(_("No duplicates found"))
@@ -57,18 +53,16 @@ class UnSkipOnFail(Addon):
the data for "pyfile" iotselöf.
It does MOT check the link's status.
"""
- queue = self.pyload.api.getQueue() #: Get packages (w/o files, as most file data is useless here)
-
- for package in queue:
+ for pinfo in self.pyload.api.getQueue():
#: Check if package-folder equals pyfile's package folder
- if package.folder is not pyfile.package().folder:
+ if pinfo.folder is not pyfile.package().folder:
continue
#: Now get packaged data w/ files/links
- pdata = self.pyload.api.getPackageData(package.pid)
+ pdata = self.pyload.api.getPackageData(pinfo.pid)
for link in pdata.links:
#: Check if link == "skipped"
- if link.status != 4:
+ if link.status is not 4:
continue
#: Check if link name collides with pdata's name
@@ -77,14 +71,14 @@ class UnSkipOnFail(Addon):
return link
- def _pyfile(self, link):
+ def _create_pyFile(self, pylink):
return PyFile(self.pyload.files,
- link.fid,
- link.url,
- link.name,
- link.size,
- link.status,
- link.error,
- link.plugin,
- link.packageID,
- link.order)
+ pylink.fid,
+ pylink.url,
+ pylink.name,
+ pylink.size,
+ pylink.status,
+ pylink.error,
+ pylink.plugin,
+ pylink.packageID,
+ pylink.order)
diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py
index e235b0e47..cf36a6d40 100644
--- a/module/plugins/hooks/UpdateManager.py
+++ b/module/plugins/hooks/UpdateManager.py
@@ -9,13 +9,13 @@ import sys
import time
from module.plugins.internal.Addon import Expose, Addon, threaded
-from module.plugins.internal.utils import encode, exists, fs_join
+from module.plugins.internal.misc import encode, exists, fsjoin
class UpdateManager(Addon):
__name__ = "UpdateManager"
__type__ = "hook"
- __version__ = "1.04"
+ __version__ = "1.05"
__status__ = "testing"
__config__ = [("activated" , "bool", "Activated" , True ),
@@ -45,7 +45,7 @@ class UpdateManager(Addon):
if self.do_restart is False:
self.pyload.api.unpauseServer()
- self.start_periodical(10)
+ self.periodical.start(10)
def init(self):
@@ -53,7 +53,7 @@ class UpdateManager(Addon):
self.mtimes = {} #: Store modification time for each plugin
self.event_map = {'allDownloadsProcessed': "all_downloads_processed"}
- if self.get_config('checkonstart'):
+ if self.config.get('checkonstart'):
self.pyload.api.pauseServer()
self.checkonstart = True
else:
@@ -67,16 +67,16 @@ class UpdateManager(Addon):
self.pyload.api.restart()
- def periodical(self):
+ def periodical_task(self):
if self.pyload.debug:
- if self.get_config('reloadplugins'):
+ if self.config.get('reloadplugins'):
self.autoreload_plugins()
- if self.get_config('nodebugupdate'):
+ if self.config.get('nodebugupdate'):
return
- if self.get_config('checkperiod') and \
- time.time() - max(self.CHECK_INTERVAL, self.get_config('checkinterval') * 60 * 60) > self.info['last_check']:
+ if self.config.get('checkperiod') and \
+ time.time() - max(self.CHECK_INTERVAL, self.config.get('checkinterval') * 60 * 60) > self.info['last_check']:
self.update()
@@ -146,7 +146,7 @@ class UpdateManager(Addon):
"""
Check for updates
"""
- if self._update() is not 2 or not self.get_config('autorestart'):
+ if self._update() is not 2 or not self.config.get('autorestart'):
return
if not self.pyload.api.statusDownloads():
@@ -304,7 +304,7 @@ class UpdateManager(Addon):
m = self._VERSION.search(content)
if m and m.group(2) == plugin_version:
- with open(fs_join("userplugins", plugin_type, plugin_name + ".py"), "wb") as f:
+ with open(fsjoin("userplugins", plugin_type, plugin_name + ".py"), "wb") as f:
f.write(encode(content))
updated.append((plugin_type, plugin_name))
@@ -342,7 +342,7 @@ class UpdateManager(Addon):
rootplugins = os.path.join(pypath, "module", "plugins")
for basedir in ("userplugins", rootplugins):
- py_filename = fs_join(basedir, plugin_type, plugin_name + ".py")
+ py_filename = fsjoin(basedir, plugin_type, plugin_name + ".py")
pyc_filename = py_filename + "c"
if plugin_type is "hook":
diff --git a/module/plugins/hooks/UserAgentSwitcher.py b/module/plugins/hooks/UserAgentSwitcher.py
index 402dd001d..4b0b13c93 100644
--- a/module/plugins/hooks/UserAgentSwitcher.py
+++ b/module/plugins/hooks/UserAgentSwitcher.py
@@ -3,13 +3,13 @@
import pycurl
from module.plugins.internal.Addon import Addon
-from module.plugins.internal.utils import encode
+from module.plugins.internal.misc import encode
class UserAgentSwitcher(Addon):
__name__ = "UserAgentSwitcher"
__type__ = "hook"
- __version__ = "0.12"
+ __version__ = "0.13"
__status__ = "testing"
__config__ = [("activated" , "bool", "Activated" , True ),
@@ -23,9 +23,9 @@ class UserAgentSwitcher(Addon):
def download_preparing(self, pyfile):
- connecttimeout = self.get_config('connecttimeout')
- maxredirs = self.get_config('maxredirs')
- useragent = self.get_config('useragent')
+ connecttimeout = self.config.get('connecttimeout')
+ maxredirs = self.config.get('maxredirs')
+ useragent = self.config.get('useragent')
if connecttimeout:
pyfile.plugin.req.http.c.setopt(pycurl.CONNECTTIMEOUT, connecttimeout)
diff --git a/module/plugins/hooks/WarezWorld.py b/module/plugins/hooks/WarezWorld.py
deleted file mode 100644
index b097af8b2..000000000
--- a/module/plugins/hooks/WarezWorld.py
+++ /dev/null
@@ -1,277 +0,0 @@
-import httplib
-import re
-import StringIO
-import sys
-import traceback
-import urllib
-import urllib2
-from bs4 import BeautifulSoup as Soup
-from datetime import datetime
-from module.plugins.internal.Addon import Addon
-from pytz import timezone
-
-
-UNIX_EPOCH = timezone('UTC').localize(datetime(1970, 1, 1))
-
-
-def notifyPushover(**kwargs):
- Data = kwargs
- Connection = httplib.HTTPSConnection('api.pushover.net:443')
- Connection.request('POST', '/1/messages.json', urllib.urlencode(Data),
- {'Content-type': 'application/x-www-form-urlencoded'})
- Response = Connection.getresponse()
-
-def replaceUmlauts(title):
- title = title.replace(unichr(228), 'ae').replace(unichr(196), 'Ae')
- title = title.replace(unichr(252), 'ue').replace(unichr(220), 'Ue')
- title = title.replace(unichr(246), 'oe').replace(unichr(214), 'Oe')
- title = title.replace(unichr(223), 'ss')
- title = title.replace('&amp;', '&')
- return title
-
-def getUnixTimestamp(String):
- String = re.search(r'^.*(\d{2}.\d{2}.\d{4})(\d{1,2}):(\d{2}).*$', String)
- if String:
- String = String.group(1) + \
- ('0' + String.group(2) if String.group(2) < '10' else String.group(2)) + \
- String.group(3)
- String = String.replace('.', '')
-
- UnixTimestamp = (
- timezone('Europe/Berlin').localize(datetime.strptime(String, '%d%m%Y%H%M')).astimezone(timezone('UTC'))
- - UNIX_EPOCH
- ).total_seconds()
- return UnixTimestamp
-
-
-class WarezWorld(Addon):
- __name__ = 'WarezWorld'
- __type__ = 'hook'
- __status__ = 'testing'
- __author_name__ = ('Arno-Nymous')
- __author_mail__ = ('Arno-Nymous@users.noreply.github.com')
- __version__ = '1.2'
- __description__ = 'Get new movies from Warez-World.org'
- __config__ = [
- ('activated', 'bool', 'Active', 'False'),
- ('interval', 'int', 'Waiting time until next run in minutes', '60'),
- ('minYear', 'long', 'No movies older than year', '1970'),
- ('pushoverAppToken', 'str', 'Pushover app token', ''),
- ('pushoverUserToken', 'str', 'Pushover user token', ''),
- ('preferredHosters', 'str', 'Preferred hosters (seperated by;)','Share-online.biz'),
- ('quality', '720p;1080p', 'Video quality', '720p'),
- ('ratingCollector', 'float', 'Send releases to link collector with an IMDb rating of (or higher)', '6.5'),
- ('ratingQueue', 'float', 'Send releases to queue with an IMDb rating of (or higher)', '8.0'),
- ('rejectGenres', 'str', 'Reject movies of an of the following genres (seperated by ;)', 'Anime;Documentary;Family'),
- ('rejectReleaseTokens', 'str', 'Reject releases containing any of the following tokens (seperated by ;)', '.ts.;.hdts.'),
- ('soundError', ';none;alien;bike;bugle;cashregister;classical;climb;cosmic;echo;falling;gamelan;incoming;intermission;magic;mechanical;persistent;pianobar;pushover;siren;spacealarm;tugboat;updown', 'Use this sound for errors pushed via Pushover (empty for default)', ''),
- ('soundNotification', ';none;alien;bike;bugle;cashregister;classical;climb;cosmic;echo;falling;gamelan;incoming;intermission;magic;mechanical;persistent;pianobar;pushover;siren;spacealarm;tugboat;updown', 'Use this sound for notifications pushed via Pushover (empty for default)', '')
- ]
-
- UrlOpener = urllib2.build_opener()
- RejectGenres = []
- RejectReleaseTokens = []
- LastReleaseTimestamp = None
- # Initialize dictionary keys here to enable quick access on keys via augmented operators
- # in later code without further code magic
- Statistics = {'Total': 0, 'Added': 0, 'Skipped': 0, 'AlreadyProcessed': 0}
-
- def __init__(self, *args, **kwargs):
- super(WarezWorld, self).__init__(*args, **kwargs)
- self.start_periodical(self.get_config('interval'))
-
- def periodical(self):
- self.log_info(u'Start periodical run...')
-
- self.interval = self.get_config('interval') * 60
- self.RejectGenres = self.get_config('rejectGenres').split(';')
- self.PreferredHosters = self.get_config('preferredHosters').lower().split(';')
- self.RejectReleaseTokens = self.get_config('rejectReleaseTokens').lower().split(';')
- self.LastReleaseTimestamp = float(self.retrieve('LastReleaseTimestamp', 0))
- # Setting statistics to 0 by iterating over dictionary items
- # instead of recreating dictionary over and over
- for Key in self.Statistics:
- self.Statistics[Key] = 0
-
- try:
- Request = urllib2.Request('http://warez-world.org/kategorie/filme', 'html5lib')
- Request.add_header('User-Agent', 'Mozilla/5.0')
- Page = Soup(self.UrlOpener.open(Request).read())
- Items = Page.findAll('li', class_='main-single')
- Releases = []
-
- for Item in Items:
- Releases.append({
- 'MovieName': Item.find('span', class_='main-rls').text,
- 'ReleaseName': re.search(r'<br/>(.*)</span>', unicode(Item.find('span', class_='main-rls'))).group(1),
- 'ReleaseLink': unicode(Item.find('span', class_='main-rls').a['href']),
- 'ReleaseDate': getUnixTimestamp(unicode(Item.find(class_='main-date').text))
- })
- self.log_info(u'{0} releases found'.format(len(Releases)))
-
- for Release in Releases[::-1]:
- if (Release['ReleaseDate'] < self.LastReleaseTimestamp):
- self.log_debug(u'Release already processed \"{0}\"'.format (Release['ReleaseName']))
- self.Statistics['AlreadyProcessed'] += 1
- continue
- self.log_debug(u'Processing release \"{0}\"'.format(Release['ReleaseName']))
- Release['MovieYear'] = 1900
- Release['MovieRating'] = 0
- Release['MovieGenres'] = []
- if self.parseRelease(Release):
- self.downloadRelease(Release)
-
- self.store('LastReleaseTimestamp', Releases[0]['ReleaseDate'])
- self.log_debug(u'Last parsed release timestamp is {0}'.format(Releases[0]['ReleaseDate']))
-
- self.Statistics['Total'] = sum(self.Statistics.itervalues())
- self.log_info(u'Periodical run finished. Statistics: {0} total, {1} added, {2} skipped, {3} already processed'.format(
- self.Statistics['Total'],
- self.Statistics['Added'],
- self.Statistics['Skipped'],
- self.Statistics['AlreadyProcessed']
- ))
- except:
- exc_type, exc_value, exc_traceback = sys.exc_info()
- output = StringIO.StringIO()
- traceback.print_exception(exc_type, exc_value, exc_traceback, file=output)
- if 'Release' in locals():
- msg = '<b>Stacktrace</b>\n{0}\n<b>Release</b>\n{1}\n\n<b>Date</b>\n{2}'.format(
- output.getvalue(), Release['ReleaseName'].encode('utf-8'), Release['ReleaseDate']
- )
- else:
- msg = '<b>Stacktrace</b>\n{0}'.format(output.getvalue())
- notifyPushover(
- token=self.get_config('pushoverAppToken'),
- user=self.get_config('pushoverUserToken'),
- title='Error in script \"WarezWorld.py\"',
- message=msg,
- sound=self.get_config('soundError'),
- html=1
- )
- raise
-
- def parseRelease(self, Release):
- if any([
- set(re.split(r'[\. ]', Release['ReleaseName'].lower())) & set(self.RejectReleaseTokens),
- not(self.get_config('quality').lower() in Release['ReleaseName'].lower())
- ]):
- self.log_debug(u'...Skip release ({0})'.format("Release name contains unwanted tokens or quality mismatch"))
- self.Statistics['Skipped'] += 1
- return False
-
- Request = urllib2.Request(Release['ReleaseLink'], 'html5lib')
- Request.add_header('User-Agent', 'Mozilla/5.0')
- ReleasePage = Soup(self.UrlOpener.open(Request).read())
-
- DownloadLinks = ReleasePage.findAll('div', id='download-links')
- if DownloadLinks:
- for DownloadLink in DownloadLinks:
- if DownloadLink.a.string and DownloadLink.a.string.lower() in self.PreferredHosters:
- Release['DownloadLink'] = DownloadLink.a['href']
- break
- if 'DownloadLink' not in Release:
- self.log_debug('...No download link of preferred hoster found')
- return False
-
- ReleaseNfo = ReleasePage.find('div', class_='spoiler')
- ImdbUrl = re.search(r'(http://)?.*(imdb\.com/title/tt\d+)\D', unicode(ReleaseNfo))
- if ImdbUrl:
- Release['ImdbUrl'] = 'http://www.' + ImdbUrl.group(2)
- self.addImdbData(Release)
- else:
- for Div in ReleasePage.findAll('div', class_='ui2'):
- if Div.a and Div.a.string == 'IMDb-Seite':
- Request = urllib2.Request(urllib.quote_plus(Div.a['href'].encode('utf-8'), '/:?='))
- ImdbPage = Soup(self.UrlOpener.open(Request).read())
- if ImdbPage.find('table', class_='findList'):
- Release['ImdbUrl'] = 'http://www.imdb.com' + \
- ImdbPage.find('td', class_='result_text').a['href']
- self.addImdbData(Release)
- else:
- self.log_debug(u'...Could not obtain IMDb data for release...Send to link collector')
- self.Statistics['Added'] += 1
- break
-
- if all([Release['MovieYear'] >= self.get_config('minYear'),
- Release['MovieRating'] >= self.get_config('ratingCollector'),
- not(set(Release['MovieGenres']) & set(self.RejectGenres))]):
- return True
- else:
- self.log_debug(u'...Skip release ({0})'.format('Movie too old, poor IMDb rating or unwanted genres'))
- self.Statistics['Skipped'] += 1
- return False
-
- def addImdbData(self, Release):
- self.log_debug(u'...Fetching IMDb data for release ({0})'.format(Release['ImdbUrl']))
-
- Request = urllib2.Request(Release['ImdbUrl'])
- Request.add_header('User-Agent', 'Mozilla/5.0')
- ImdbPage = Soup(self.UrlOpener.open(Request).read())
-
- MovieName = ImdbPage.find('span', {'itemprop': 'name'}).string
- # For the year it has to be done a tiny bit of BeautifulSoup magic as it sometimes can
- # be formatted as a link on IMDb and sometimes not
- try:
- MovieYear = ImdbPage.find('h1', class_='header').find('span', class_='nobr').find(
- text=re.compile(r'\d{4}')
- ).strip(u' ()\u2013')
- except:
- MovieYear = 0
- self.log_debug('...Could not parse movie year ({0})'.format(Release['ImdbUrl']))
- try:
- MovieRating = ImdbPage.find('span', {'itemprop': 'ratingValue'}).string.replace(',', '.')
- except:
- MovieRating = 0
- self.log_debug(u'...Could not parse movie rating ({0})'.format(MovieName, Release['ImdbUrl']))
- MovieGenres = []
- try:
- for Genre in ImdbPage.find('div', {'itemprop': 'genre'}).findAll('a'):
- MovieGenres.append(Genre.string.strip())
- except:
- self.log_debug(u'...Could not parse movie genres ({0})'.format(Release['ImdbUrl']))
-
- Release['MovieName'] = MovieName
- Release['MovieYear'] = MovieYear
- Release['MovieRating'] = MovieRating
- Release['MovieGenres'] = MovieGenres
-
- def downloadRelease(self, Release):
- Storage = self.retrieve(u'{0} ({1})'.format(Release['MovieName'], Release['MovieYear']))
-
- if Storage == '1':
- self.log_debug(u'Skip release ({0})'.format('already downloaded'))
- self.Statistics['Skipped'] += 1
- else:
- Storage = u'{0} ({1})'.format(Release['MovieName'], Release['MovieYear'])
- if Release['MovieRating'] >= self.get_config('ratingQueue'):
- self.pyload.api.addPackage(Storage + ' IMDb: ' + Release['MovieRating'],
- [Release['DownloadLink']], 1)
- PushoverTitle = 'New movie added to queue'
- self.log_info(u'New movie added to queue ({0})'.format(Storage))
- else:
- self.pyload.api.addPackage(Storage + ' IMDb: ' + Release['MovieRating'],
- [Release['DownloadLink']], 0)
- PushoverTitle = 'New movie added to link collector'
- self.log_info(u'New movie added to link collector ({0})'.format(Storage))
-
- self.Statistics['Added'] += 1
-
- notifyPushover(
- token=self.get_config('pushoverAppToken'),
- user=self.get_config('pushoverUserToken'),
- title=PushoverTitle,
- message='<b>{0} ({1})</b>\n<i>Rating:</i> {2}\n<i>Genres:</i> {3}\n\n<i>{4}</i>'.format(
- Release['MovieName'].encode('utf-8'),
- Release['MovieYear'].encode('utf-8'),
- Release['MovieRating'].encode('utf-8'),
- ', '.join(Release['MovieGenres']).encode('utf-8'),
- Release['ReleaseName'].encode('utf-8')
- ),
- sound=self.get_config('soundNotification'),
- url=(Release['ImdbUrl'].encode('utf-8') if 'ImdbUrl' in Release else ''),
- url_title='View on IMDb',
- html=1
- )
-
- self.store(Storage, '1')
diff --git a/module/plugins/hooks/WindowsPhoneNotify.py b/module/plugins/hooks/WindowsPhoneNotify.py
index cd5f5dea4..84d122811 100644
--- a/module/plugins/hooks/WindowsPhoneNotify.py
+++ b/module/plugins/hooks/WindowsPhoneNotify.py
@@ -9,20 +9,23 @@ from module.plugins.internal.Notifier import Notifier
class WindowsPhoneNotify(Notifier):
__name__ = "WindowsPhoneNotify"
__type__ = "hook"
- __version__ = "0.15"
+ __version__ = "0.17"
__status__ = "testing"
- __config__ = [("activated" , "bool", "Activated" , False),
- ("push-id" , "str" , "Push ID" , "" ),
- ("push-url" , "str" , "Push url" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify packages processed" , True ),
- ("notifyupdate" , "bool", "Notify plugin updates" , True ),
- ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ),
- ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ),
- ("sendpermin" , "int" , "Max notifications per minute" , 12 ),
- ("ignoreclient" , "bool", "Send notifications if client is connected", False)]
+ __config__ = [("activated" , "bool", "Activated" , False),
+ ("pushid" , "str" , "Push ID" , "" ),
+ ("pushurl" , "str" , "Push url" , "" ),
+ ("captcha" , "bool", "Notify captcha request" , True ),
+ ("reconnection" , "bool", "Notify reconnection request" , False),
+ ("downloadfinished", "bool", "Notify download finished" , True ),
+ ("downloadfailed" , "bool", "Notify download failed" , True ),
+ ("packagefinished" , "bool", "Notify package finished" , True ),
+ ("packagefailed" , "bool", "Notify package failed" , True ),
+ ("update" , "bool", "Notify pyLoad update" , False),
+ ("exit" , "bool", "Notify pyLoad shutdown/restart" , False),
+ ("sendinterval" , "int" , "Interval in seconds between notifications", 1 ),
+ ("sendpermin" , "int" , "Max notifications per minute" , 60 ),
+ ("ignoreclient" , "bool", "Send notifications if client is connected", True )]
__description__ = """Send push notifications to Windows Phone"""
__license__ = "GPLv3"
@@ -31,7 +34,7 @@ class WindowsPhoneNotify(Notifier):
def get_key(self):
- return self.get_config('push-id'), self.get_config('push-url')
+ return self.config.get('pushid'), self.config.get('pushurl')
def format_request(self, msg):
diff --git a/module/plugins/hooks/XFileSharing.py b/module/plugins/hooks/XFileSharing.py
index 26dea3ec6..4af246da8 100644
--- a/module/plugins/hooks/XFileSharing.py
+++ b/module/plugins/hooks/XFileSharing.py
@@ -9,10 +9,10 @@ from module.plugins.internal.Addon import Addon
class XFileSharing(Addon):
__name__ = "XFileSharing"
__type__ = "hook"
- __version__ = "0.52"
+ __version__ = "0.55"
__status__ = "testing"
- __config__ = [("activated" , "bool", "Activated" , True ),
+ __config__ = [("activated" , "bool", "Activated" , False),
("use_hoster_list" , "bool", "Load listed hosters only" , False),
("use_crypter_list", "bool", "Load listed crypters only" , False),
("use_builtin_list", "bool", "Load built-in plugin list" , True ),
@@ -24,9 +24,9 @@ class XFileSharing(Addon):
__authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
- regexp = {'hoster' : (r'(?:https?://(?:www\.)?)(?!%s)(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,63}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)',
+ regexp = {'hoster' : (r'(?:https?://(?:www\.)?)(?!(?:www\.)?(?:%s))(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,63}(?:\.[a-zA-Z]{2,})+)(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)',
r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:embed-)?\w+'),
- 'crypter': (r'(?:https?://(?:www\.)?)(?!%s)(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,63}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:user|folder)s?/\w+',
+ 'crypter': (r'(?:https?://(?:www\.)?)(?!(?:www\.)?(?:%s))(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,63}(?:\.[a-zA-Z]{2,})+)(?:\:\d+)?)/(?:user|folder)s?/\w+',
r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')}
BUILTIN_HOSTERS = [# WORKING HOSTERS:
@@ -60,15 +60,15 @@ class XFileSharing(Addon):
def get_pattern(self, type, plugin):
- if self.get_config("use_%s_list" % type):
- plugin_list = self.get_config('%s_list' % type)
+ if self.config.get("use_%s_list" % type):
+ plugin_list = self.config.get('%s_list' % type)
plugin_list = plugin_list.replace(' ', '').replace('\\', '')
plugin_list = plugin_list.replace('|', ',').replace(';', ',')
plugin_list = plugin_list.lower().split(',')
plugin_set = set(plugin_list)
- if self.get_config('use_builtin_list'):
+ if self.config.get('use_builtin_list'):
builtin_list = getattr(self, "BUILTIN_%sS" % type.upper())
plugin_set.update(builtin_list)
@@ -91,7 +91,13 @@ class XFileSharing(Addon):
isXFS = lambda klass: any(k.__name__.startswith("XFS") for k in inspect.getmro(klass))
for p in self.pyload.pluginManager.plugins[type].values():
- klass = self.pyload.pluginManager.loadClass(type, p['name'])
+ try:
+ klass = self.pyload.pluginManager.loadClass(type, p['name'])
+
+ except AttributeError, e:
+ self.log_debug(e, trace=True)
+ continue
+
if hasattr(klass, "PLUGIN_DOMAIN") and klass.PLUGIN_DOMAIN and isXFS(klass):
plugin_list.append(klass.PLUGIN_DOMAIN)
@@ -101,7 +107,7 @@ class XFileSharing(Addon):
else:
pattern = self.regexp[type][0]
- self.log_info(_("Handle any %s site on the web!") % type)
+ self.log_info(_("Auto-discover new %ss") % type)
return pattern
@@ -116,13 +122,10 @@ class XFileSharing(Addon):
dict['pattern'] = pattern
dict['re'] = re.compile(pattern)
- self.log_debug("Loaded %s pattern: %s" % (type, pattern))
+ self.log_debug("Pattern for %ss: %s" % (type, pattern))
def _unload(self, type, plugin):
dict = self.pyload.pluginManager.plugins[type][plugin]
dict['pattern'] = r'^unmatchable$'
dict['re'] = re.compile(dict['pattern'])
-
-
-
diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPP.py
index b8fe14239..1e0eda59b 100644
--- a/module/plugins/hooks/XMPPInterface.py
+++ b/module/plugins/hooks/XMPP.py
@@ -1,18 +1,16 @@
# -*- coding: utf-8 -*-
-from pyxmpp import streamtls
-from pyxmpp.all import JID, Message
-from pyxmpp.interface import implements
-from pyxmpp.interfaces import *
+import pyxmpp
+
from pyxmpp.jabber.client import JabberClient
-from module.plugins.hooks.IRCInterface import IRCInterface
+from module.plugins.hooks.IRC import IRC
-class XMPPInterface(IRCInterface, JabberClient):
- __name__ = "XMPPInterface"
+class XMPP(IRC, JabberClient):
+ __name__ = "XMPP"
__type__ = "hook"
- __version__ = "0.14"
+ __version__ = "0.15"
__status__ = "testing"
__config__ = [("activated", "bool", "Activated" , False ),
@@ -29,21 +27,21 @@ class XMPPInterface(IRCInterface, JabberClient):
__authors__ = [("RaNaN", "RaNaN@pyload.org")]
- implements(IMessageHandlersProvider)
+ pyxmpp.interface.implements(IMessageHandlersProvider)
def __init__(self, *args, **kwargs):
- IRCInterface.__init__(self, *args, **kwargs)
+ IRC.__init__(self, *args, **kwargs)
- self.jid = JID(self.get_config('jid'))
- password = self.get_config('pw')
+ self.jid = pyxmpp.all.JID(self.config.get('jid'))
+ password = self.config.get('pw')
#: If bare JID is provided add a resource -- it is required
if not self.jid.resource:
- self.jid = JID(self.jid.node, self.jid.domain, "pyLoad")
+ self.jid = pyxmpp.all.JID(self.jid.node, self.jid.domain, "pyLoad")
- if self.get_config('tls'):
- tls_settings = streamtls.TLSSettings(require=True, verify_peer=False)
+ if self.config.get('tls'):
+ tls_settings = pyxmpp.streamtls.TLSSettings(require=True, verify_peer=False)
auth = ("sasl:PLAIN", "sasl:DIGEST-MD5")
else:
tls_settings = None
@@ -69,7 +67,7 @@ class XMPPInterface(IRCInterface, JabberClient):
def package_finished(self, pypack):
try:
- if self.get_config('info_pack'):
+ if self.config.get('info_pack'):
self.announce(_("Package finished: %s") % pypack.name)
except Exception:
@@ -78,7 +76,7 @@ class XMPPInterface(IRCInterface, JabberClient):
def download_finished(self, pyfile):
try:
- if self.get_config('info_file'):
+ if self.config.get('info_file'):
self.announce(
_("Download finished: %(name)s @ %(plugin)s") % {'name': pyfile.name, 'plugin': pyfile.pluginname})
@@ -146,11 +144,11 @@ class XMPPInterface(IRCInterface, JabberClient):
to_jid = stanza.get_from()
from_jid = stanza.get_to()
- # j = JID()
+ # j = pyxmpp.all.JID()
to_name = to_jid.as_utf8()
from_name = from_jid.as_utf8()
- names = self.get_config('owners').split(";")
+ names = self.config.get('owners').split(";")
if to_name in names or to_jid.node + "@" + to_jid.domain in names:
messages = []
@@ -171,7 +169,7 @@ class XMPPInterface(IRCInterface, JabberClient):
try:
res = handler(args)
for line in res:
- m = Message(
+ m = pyxmpp.all.Message(
to_jid=to_jid,
from_jid=from_jid,
stanza_type=stanza.get_type(),
@@ -197,15 +195,15 @@ class XMPPInterface(IRCInterface, JabberClient):
"""
Send message to all owners
"""
- for user in self.get_config('owners').split(";"):
+ for user in self.config.get('owners').split(";"):
self.log_debug("Send message to", user)
- to_jid = JID(user)
+ to_jid = pyxmpp.all.JID(user)
- m = Message(from_jid=self.jid,
- to_jid=to_jid,
- stanza_type="chat",
- body=message)
+ m = pyxmpp.all.Message(from_jid=self.jid,
+ to_jid=to_jid,
+ stanza_type="chat",
+ body=message)
stream = self.get_stream()
if not stream:
@@ -230,7 +228,7 @@ class VersionHandler(object):
This class will answer version query and announce 'jabber:iq:version' namespace
in the client's disco#info results.
"""
- implements(IIqHandlersProvider, IFeaturesProvider)
+ pyxmpp.interface.implements(IIqHandlersProvider, IFeaturesProvider)
def __init__(self, client):