From 681deb7ff09956be0bee04453e33ac6e9d6dab4a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 8 Jun 2015 05:56:10 +0200 Subject: Move base plugins to internal folder --- module/plugins/internal/Account.py | 292 +++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 module/plugins/internal/Account.py (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py new file mode 100644 index 000000000..c147404e0 --- /dev/null +++ b/module/plugins/internal/Account.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: mkaay +""" + +from random import choice +from time import time +from traceback import print_exc +from threading import RLock + +from Plugin import Base +from module.utils import compare_time, parseFileSize, lock + +class WrongPassword(Exception): + pass + + +class Account(Base): + """ + Base class for every Account plugin. + Just overwrite `login` and cookies will be stored and account becomes accessible in\ + associated hoster plugin. Plugin should also provide `loadAccountInfo` + """ + __name__ = "Account" + __version__ = "0.2" + __type__ = "account" + __description__ = """Account Plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + + #: after that time [in minutes] pyload will relogin the account + login_timeout = 600 + #: account data will be reloaded after this time + info_threshold = 600 + + + def __init__(self, manager, accounts): + Base.__init__(self, manager.core) + + self.manager = manager + self.accounts = {} + self.infos = {} # cache for account information + self.lock = RLock() + + self.timestamps = {} + self.setAccounts(accounts) + self.init() + + def init(self): + pass + + def login(self, user, data, req): + """login into account, the cookies will be saved so user can be recognized + + :param user: loginname + :param data: data dictionary + :param req: `Request` instance + """ + pass + + @lock + def _login(self, user, data): + # set timestamp for login + self.timestamps[user] = time() + + req = self.getAccountRequest(user) + try: + self.login(user, data, req) + except WrongPassword: + self.logWarning( + _("Could not login with account %(user)s | %(msg)s") % {"user": user + , "msg": _("Wrong Password")}) + data["valid"] = False + + except Exception, e: + self.logWarning( + _("Could not login with account %(user)s | %(msg)s") % {"user": user + , "msg": e}) + data["valid"] = False + if self.core.debug: + print_exc() + finally: + if req: req.close() + + def relogin(self, user): + req = self.getAccountRequest(user) + if req: + req.cj.clear() + req.close() + if user in self.infos: + del self.infos[user] #delete old information + + self._login(user, self.accounts[user]) + + def setAccounts(self, accounts): + self.accounts = accounts + for user, data in self.accounts.iteritems(): + self._login(user, data) + self.infos[user] = {} + + def updateAccounts(self, user, password=None, options={}): + """ updates account and return true if anything changed """ + + if user in self.accounts: + self.accounts[user]["valid"] = True #do not remove or accounts will not login + if password: + self.accounts[user]["password"] = password + self.relogin(user) + return True + if options: + before = self.accounts[user]["options"] + self.accounts[user]["options"].update(options) + return self.accounts[user]["options"] != before + else: + self.accounts[user] = {"password": password, "options": options, "valid": True} + self._login(user, self.accounts[user]) + return True + + def removeAccount(self, user): + if user in self.accounts: + del self.accounts[user] + if user in self.infos: + del self.infos[user] + if user in self.timestamps: + del self.timestamps[user] + + @lock + def getAccountInfo(self, name, force=False): + """retrieve account infos for an user, do **not** overwrite this method!\\ + just use it to retrieve infos in hoster plugins. see `loadAccountInfo` + + :param name: username + :param force: reloads cached account information + :return: dictionary with information + """ + data = Account.loadAccountInfo(self, name) + + if force or name not in self.infos: + self.logDebug("Get Account Info for %s" % name) + req = self.getAccountRequest(name) + + try: + infos = self.loadAccountInfo(name, req) + if not type(infos) == dict: + raise Exception("Wrong return format") + except Exception, e: + infos = {"error": str(e)} + + if req: req.close() + + self.logDebug("Account Info: %s" % str(infos)) + + infos["timestamp"] = time() + self.infos[name] = infos + elif "timestamp" in self.infos[name] and self.infos[name][ + "timestamp"] + self.info_threshold * 60 < time(): + self.logDebug("Reached timeout for account data") + self.scheduleRefresh(name) + + data.update(self.infos[name]) + return data + + def isPremium(self, user): + info = self.getAccountInfo(user) + return info["premium"] + + def loadAccountInfo(self, name, req=None): + """this should be overwritten in account plugin,\ + and retrieving account information for user + + :param name: + :param req: `Request` instance + :return: + """ + return { + "validuntil": None, # -1 for unlimited + "login": name, + #"password": self.accounts[name]["password"], #@XXX: security + "options": self.accounts[name]["options"], + "valid": self.accounts[name]["valid"], + "trafficleft": None, # in kb, -1 for unlimited + "maxtraffic": None, + "premium": True, #useful for free accounts + "timestamp": 0, #time this info was retrieved + "type": self.__name__, + } + + def getAllAccounts(self, force=False): + return [self.getAccountInfo(user, force) for user, data in self.accounts.iteritems()] + + def getAccountRequest(self, user=None): + if not user: + user, data = self.selectAccount() + if not user: + return None + + req = self.core.requestFactory.getRequest(self.__name__, user) + return req + + def getAccountCookies(self, user=None): + if not user: + user, data = self.selectAccount() + if not user: + return None + + cj = self.core.requestFactory.getCookieJar(self.__name__, user) + return cj + + def getAccountData(self, user): + return self.accounts[user] + + def selectAccount(self): + """ returns an valid account name and data""" + usable = [] + for user, data in self.accounts.iteritems(): + if not data["valid"]: continue + + if "time" in data["options"] and data["options"]["time"]: + time_data = "" + try: + time_data = data["options"]["time"][0] + start, end = time_data.split("-") + if not compare_time(start.split(":"), end.split(":")): + continue + except: + self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) + + if user in self.infos: + if "validuntil" in self.infos[user]: + if self.infos[user]["validuntil"] > 0 and time() > self.infos[user]["validuntil"]: + continue + if "trafficleft" in self.infos[user]: + if self.infos[user]["trafficleft"] == 0: + continue + + usable.append((user, data)) + + if not usable: return None, None + return choice(usable) + + def canUse(self): + return False if self.selectAccount() == (None, None) else True + + def parseTraffic(self, string): #returns kbyte + return parseFileSize(string) / 1024 + + def wrongPassword(self): + raise WrongPassword + + def empty(self, user): + if user in self.infos: + self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % user) + + self.infos[user].update({"trafficleft": 0}) + self.scheduleRefresh(user, 30 * 60) + + def expired(self, user): + if user in self.infos: + self.logWarning(_("Account %s is expired, checking again in 1h") % user) + + self.infos[user].update({"validuntil": time() - 1}) + self.scheduleRefresh(user, 60 * 60) + + def scheduleRefresh(self, user, time=0, force=True): + """ add task to refresh account info to sheduler """ + self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) + self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) + + @lock + def checkLogin(self, user): + """ checks if user is still logged in """ + if user in self.timestamps: + if self.timestamps[user] + self.login_timeout * 60 < time(): + self.logDebug("Reached login timeout for %s" % user) + self.relogin(user) + return False + + return True -- cgit v1.2.3 From 0e1ef9bc01579328e17e79416fa3c1c7b77adcc8 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 8 Jun 2015 06:08:01 +0200 Subject: Update everything --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index c147404e0..7632d15c2 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, see . - + @author: mkaay """ @@ -36,7 +36,7 @@ class Account(Base): associated hoster plugin. Plugin should also provide `loadAccountInfo` """ __name__ = "Account" - __version__ = "0.2" + __version__ = "0.02" __type__ = "account" __description__ = """Account Plugin""" __author_name__ = ("mkaay") @@ -76,7 +76,7 @@ class Account(Base): def _login(self, user, data): # set timestamp for login self.timestamps[user] = time() - + req = self.getAccountRequest(user) try: self.login(user, data, req) -- cgit v1.2.3 From 3eff29b8f0c6feca5657220f19f6a3ca37a7ec2e Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 14 Jun 2015 19:27:37 +0200 Subject: Update Account --- module/plugins/internal/Account.py | 212 ++++++++++++++++++++----------------- 1 file changed, 116 insertions(+), 96 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 7632d15c2..654296f32 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -1,29 +1,13 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. +import random +import threading +import time +import traceback - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. +from module.plugins.internal.Plugin import Base +from module.utils import compare_time, lock, parse_size - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - @author: mkaay -""" - -from random import choice -from time import time -from traceback import print_exc -from threading import RLock - -from Plugin import Base -from module.utils import compare_time, parseFileSize, lock class WrongPassword(Exception): pass @@ -35,36 +19,37 @@ class Account(Base): Just overwrite `login` and cookies will be stored and account becomes accessible in\ associated hoster plugin. Plugin should also provide `loadAccountInfo` """ - __name__ = "Account" - __version__ = "0.02" - __type__ = "account" - __description__ = """Account Plugin""" - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") + __name__ = "Account" + __type__ = "account" + __version__ = "0.03" - #: after that time [in minutes] pyload will relogin the account - login_timeout = 600 - #: account data will be reloaded after this time - info_threshold = 600 + __description__ = """Base account plugin""" + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] def __init__(self, manager, accounts): - Base.__init__(self, manager.core) - self.manager = manager self.accounts = {} - self.infos = {} # cache for account information - self.lock = RLock() - + self.infos = {} #: cache for account information + self.lock = threading.RLock() self.timestamps = {} - self.setAccounts(accounts) + + self.login_timeout = 10 * 60 #: after that time (in minutes) pyload will relogin the account + self.info_threshold = 10 * 60 #: after that time (in minutes) account data will be reloaded + self.init() + self.setAccounts(accounts) + + def init(self): pass + def login(self, user, data, req): - """login into account, the cookies will be saved so user can be recognized + """ + Login into account, the cookies will be saved so user can be recognized :param user: loginname :param data: data dictionary @@ -72,29 +57,38 @@ class Account(Base): """ pass + @lock def _login(self, user, data): # set timestamp for login - self.timestamps[user] = time() + self.timestamps[user] = time.time() req = self.getAccountRequest(user) try: self.login(user, data, req) + except WrongPassword: self.logWarning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user - , "msg": _("Wrong Password")}) - data["valid"] = False + _("Could not login with account %(user)s | %(msg)s") % {"user": user, + "msg": _("Wrong Password")}) + success = data['valid'] = False except Exception, e: self.logWarning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user - , "msg": e}) - data["valid"] = False + _("Could not login with account %(user)s | %(msg)s") % {"user": user, + "msg": e}) + success = data['valid'] = False if self.core.debug: - print_exc() + traceback.print_exc() + + else: + success = True + finally: - if req: req.close() + if req: + req.close() + return success + def relogin(self, user): req = self.getAccountRequest(user) @@ -102,9 +96,10 @@ class Account(Base): req.cj.clear() req.close() if user in self.infos: - del self.infos[user] #delete old information + del self.infos[user] #: delete old information + + return self._login(user, self.accounts[user]) - self._login(user, self.accounts[user]) def setAccounts(self, accounts): self.accounts = accounts @@ -112,24 +107,26 @@ class Account(Base): self._login(user, data) self.infos[user] = {} + def updateAccounts(self, user, password=None, options={}): - """ updates account and return true if anything changed """ + """Updates account and return true if anything changed""" if user in self.accounts: - self.accounts[user]["valid"] = True #do not remove or accounts will not login + self.accounts[user]['valid'] = True #: do not remove or accounts will not login if password: - self.accounts[user]["password"] = password + self.accounts[user]['password'] = password self.relogin(user) return True if options: - before = self.accounts[user]["options"] - self.accounts[user]["options"].update(options) - return self.accounts[user]["options"] != before + before = self.accounts[user]['options'] + self.accounts[user]['options'].update(options) + return self.accounts[user]['options'] != before else: self.accounts[user] = {"password": password, "options": options, "valid": True} self._login(user, self.accounts[user]) return True + def removeAccount(self, user): if user in self.accounts: del self.accounts[user] @@ -138,9 +135,11 @@ class Account(Base): if user in self.timestamps: del self.timestamps[user] + @lock def getAccountInfo(self, name, force=False): - """retrieve account infos for an user, do **not** overwrite this method!\\ + """ + Retrieve account infos for an user, do **not** overwrite this method!\\ just use it to retrieve infos in hoster plugins. see `loadAccountInfo` :param name: username @@ -159,49 +158,54 @@ class Account(Base): raise Exception("Wrong return format") except Exception, e: infos = {"error": str(e)} + if self.core.debug: + traceback.print_exc() - if req: req.close() + if req: + req.close() - self.logDebug("Account Info: %s" % str(infos)) + self.logDebug("Account Info: %s" % infos) - infos["timestamp"] = time() + infos['timestamp'] = time.time() self.infos[name] = infos - elif "timestamp" in self.infos[name] and self.infos[name][ - "timestamp"] + self.info_threshold * 60 < time(): + elif "timestamp" in self.infos[name] and self.infos[name]['timestamp'] + self.info_threshold * 60 < time.time(): self.logDebug("Reached timeout for account data") self.scheduleRefresh(name) data.update(self.infos[name]) return data + def isPremium(self, user): info = self.getAccountInfo(user) - return info["premium"] + return info['premium'] + def loadAccountInfo(self, name, req=None): - """this should be overwritten in account plugin,\ + """ + This should be overwritten in account plugin,\ and retrieving account information for user :param name: :param req: `Request` instance :return: """ - return { - "validuntil": None, # -1 for unlimited - "login": name, - #"password": self.accounts[name]["password"], #@XXX: security - "options": self.accounts[name]["options"], - "valid": self.accounts[name]["valid"], - "trafficleft": None, # in kb, -1 for unlimited - "maxtraffic": None, - "premium": True, #useful for free accounts - "timestamp": 0, #time this info was retrieved - "type": self.__name__, - } + return {"validuntil" : None, #: -1 for unlimited + "login" : name, + # "password" : self.accounts[name]['password'], #: commented due security reason + "options" : self.accounts[name]['options'], + "valid" : self.accounts[name]['valid'], + "trafficleft": None, #: in bytes, -1 for unlimited + "maxtraffic" : None, + "premium" : None, + "timestamp" : 0, #: time this info was retrieved + "type" : self.__name__} + def getAllAccounts(self, force=False): return [self.getAccountInfo(user, force) for user, data in self.accounts.iteritems()] + def getAccountRequest(self, user=None): if not user: user, data = self.selectAccount() @@ -211,6 +215,7 @@ class Account(Base): req = self.core.requestFactory.getRequest(self.__name__, user) return req + def getAccountCookies(self, user=None): if not user: user, data = self.selectAccount() @@ -220,47 +225,58 @@ class Account(Base): cj = self.core.requestFactory.getCookieJar(self.__name__, user) return cj + def getAccountData(self, user): return self.accounts[user] + def selectAccount(self): - """ returns an valid account name and data""" + """Returns an valid account name and data""" usable = [] for user, data in self.accounts.iteritems(): - if not data["valid"]: continue + if not data['valid']: + continue - if "time" in data["options"] and data["options"]["time"]: + if "time" in data['options'] and data['options']['time']: time_data = "" try: - time_data = data["options"]["time"][0] + time_data = data['options']['time'][0] start, end = time_data.split("-") if not compare_time(start.split(":"), end.split(":")): continue - except: + except Exception: self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) if user in self.infos: if "validuntil" in self.infos[user]: - if self.infos[user]["validuntil"] > 0 and time() > self.infos[user]["validuntil"]: + if self.infos[user]['validuntil'] > 0 and time.time() > self.infos[user]['validuntil']: continue if "trafficleft" in self.infos[user]: - if self.infos[user]["trafficleft"] == 0: + if self.infos[user]['trafficleft'] == 0: continue usable.append((user, data)) - if not usable: return None, None - return choice(usable) + if not usable: + return None, None + + return random.choice(usable) + def canUse(self): - return False if self.selectAccount() == (None, None) else True + return self.selectAccount() != (None, None) + + + def parseTraffic(self, value, unit=None): #: return bytes + if not unit and not isinstance(value, basestring): + unit = "KB" + return parseFileSize(value, unit) - def parseTraffic(self, string): #returns kbyte - return parseFileSize(string) / 1024 def wrongPassword(self): raise WrongPassword + def empty(self, user): if user in self.infos: self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % user) @@ -268,25 +284,29 @@ class Account(Base): self.infos[user].update({"trafficleft": 0}) self.scheduleRefresh(user, 30 * 60) + def expired(self, user): if user in self.infos: self.logWarning(_("Account %s is expired, checking again in 1h") % user) - self.infos[user].update({"validuntil": time() - 1}) + self.infos[user].update({"validuntil": time.time() - 1}) self.scheduleRefresh(user, 60 * 60) + def scheduleRefresh(self, user, time=0, force=True): - """ add task to refresh account info to sheduler """ + """Add task to refresh account info to sheduler""" self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) + @lock def checkLogin(self, user): - """ checks if user is still logged in """ + """Checks if user is still logged in""" if user in self.timestamps: - if self.timestamps[user] + self.login_timeout * 60 < time(): + if self.login_timeout > 0 and self.timestamps[user] + self.login_timeout * 60 < time.time(): self.logDebug("Reached login timeout for %s" % user) - self.relogin(user) - return False - - return True + return self.relogin(user) + else: + return True + else: + return False -- cgit v1.2.3 From 71d5584e82050a66aa5306ce99e43e7cbc3a62a7 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 15 Jun 2015 00:17:49 +0200 Subject: Fix new internal plugins --- module/plugins/internal/Account.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 654296f32..27a040e24 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -6,7 +6,7 @@ import time import traceback from module.plugins.internal.Plugin import Base -from module.utils import compare_time, lock, parse_size +from module.utils import compare_time, lock, parseFileSize class WrongPassword(Exception): @@ -14,11 +14,6 @@ class WrongPassword(Exception): class Account(Base): - """ - Base class for every Account plugin. - Just overwrite `login` and cookies will be stored and account becomes accessible in\ - associated hoster plugin. Plugin should also provide `loadAccountInfo` - """ __name__ = "Account" __type__ = "account" __version__ = "0.03" @@ -29,6 +24,8 @@ class Account(Base): def __init__(self, manager, accounts): + super(Account, self).__init__(manager.core) + self.manager = manager self.accounts = {} self.infos = {} #: cache for account information -- cgit v1.2.3 From 5a139055ae658d3a05cbb658cbd66aeae0d01db5 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 15 Jun 2015 21:06:10 +0200 Subject: Spare code cosmetics --- module/plugins/internal/Account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 27a040e24..aa472f297 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -5,7 +5,7 @@ import threading import time import traceback -from module.plugins.internal.Plugin import Base +from module.plugins.internal.Plugin import Plugin from module.utils import compare_time, lock, parseFileSize @@ -13,7 +13,7 @@ class WrongPassword(Exception): pass -class Account(Base): +class Account(Plugin): __name__ = "Account" __type__ = "account" __version__ = "0.03" -- cgit v1.2.3 From c1764e2fea0bb05164c83a876e8cd58b97f58f25 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Jun 2015 17:31:38 +0200 Subject: Update all --- module/plugins/internal/Account.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index aa472f297..0e2996aaa 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -154,7 +154,9 @@ class Account(Plugin): if not type(infos) == dict: raise Exception("Wrong return format") except Exception, e: - infos = {"error": str(e)} + infos = super(self.__class__, self).loadAccountInfo(name, req) + infos['error'] = str(e) + if self.core.debug: traceback.print_exc() @@ -206,11 +208,8 @@ class Account(Plugin): def getAccountRequest(self, user=None): if not user: user, data = self.selectAccount() - if not user: - return None - req = self.core.requestFactory.getRequest(self.__name__, user) - return req + return self.core.requestFactory.getRequest(self.__name__, user) def getAccountCookies(self, user=None): @@ -264,7 +263,7 @@ class Account(Plugin): return self.selectAccount() != (None, None) - def parseTraffic(self, value, unit=None): #: return bytes + def parseTraffic(self, value, unit=None): #: return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" return parseFileSize(value, unit) -- cgit v1.2.3 From 164512b6a74c94a731fcee7435dce1ccfa2f71e7 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 17 Jun 2015 18:29:50 +0200 Subject: Spare code cosmetics --- module/plugins/internal/Account.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 0e2996aaa..0595da20b 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -106,8 +106,9 @@ class Account(Plugin): def updateAccounts(self, user, password=None, options={}): - """Updates account and return true if anything changed""" - + """ + Updates account and return true if anything changed + """ if user in self.accounts: self.accounts[user]['valid'] = True #: do not remove or accounts will not login if password: @@ -227,7 +228,9 @@ class Account(Plugin): def selectAccount(self): - """Returns an valid account name and data""" + """ + Returns an valid account name and data + """ usable = [] for user, data in self.accounts.iteritems(): if not data['valid']: @@ -290,14 +293,18 @@ class Account(Plugin): def scheduleRefresh(self, user, time=0, force=True): - """Add task to refresh account info to sheduler""" + """ + Add task to refresh account info to sheduler + """ self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) @lock def checkLogin(self, user): - """Checks if user is still logged in""" + """ + Checks if user is still logged in + """ if user in self.timestamps: if self.login_timeout > 0 and self.timestamps[user] + self.login_timeout * 60 < time.time(): self.logDebug("Reached login timeout for %s" % user) -- cgit v1.2.3 From 20b6a2ec022202b0efb6cb69415239fb8f4d1445 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 17 Jun 2015 18:59:20 +0200 Subject: Spare code cosmetics (2) --- module/plugins/internal/Account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 0595da20b..d2efe7996 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -57,7 +57,7 @@ class Account(Plugin): @lock def _login(self, user, data): - # set timestamp for login + #: set timestamp for login self.timestamps[user] = time.time() req = self.getAccountRequest(user) @@ -192,7 +192,7 @@ class Account(Plugin): """ return {"validuntil" : None, #: -1 for unlimited "login" : name, - # "password" : self.accounts[name]['password'], #: commented due security reason + #: "password" : self.accounts[name]['password'], #: commented due security reason "options" : self.accounts[name]['options'], "valid" : self.accounts[name]['valid'], "trafficleft": None, #: in bytes, -1 for unlimited -- cgit v1.2.3 From b1759bc440cd6013837697eb8de540914f693ffd Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 7 Jul 2015 01:23:55 +0200 Subject: No camelCase style anymore --- module/plugins/internal/Account.py | 108 ++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 44 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index d2efe7996..9e0efaee6 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -16,7 +16,7 @@ class WrongPassword(Exception): class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" __description__ = """Base account plugin""" __license__ = "GPLv3" @@ -37,7 +37,7 @@ class Account(Plugin): self.init() - self.setAccounts(accounts) + self.set_accounts(accounts) def init(self): @@ -60,18 +60,18 @@ class Account(Plugin): #: set timestamp for login self.timestamps[user] = time.time() - req = self.getAccountRequest(user) + req = self.get_account_request(user) try: self.login(user, data, req) except WrongPassword: - self.logWarning( + self.log_warning( _("Could not login with account %(user)s | %(msg)s") % {"user": user, "msg": _("Wrong Password")}) success = data['valid'] = False except Exception, e: - self.logWarning( + self.log_warning( _("Could not login with account %(user)s | %(msg)s") % {"user": user, "msg": e}) success = data['valid'] = False @@ -88,7 +88,7 @@ class Account(Plugin): def relogin(self, user): - req = self.getAccountRequest(user) + req = self.get_account_request(user) if req: req.cj.clear() req.close() @@ -98,14 +98,14 @@ class Account(Plugin): return self._login(user, self.accounts[user]) - def setAccounts(self, accounts): + def set_accounts(self, accounts): self.accounts = accounts for user, data in self.accounts.iteritems(): self._login(user, data) self.infos[user] = {} - def updateAccounts(self, user, password=None, options={}): + def update_accounts(self, user, password=None, options={}): """ Updates account and return true if anything changed """ @@ -125,7 +125,12 @@ class Account(Plugin): return True - def removeAccount(self, user): + #: Deprecated method, use `update_accounts` instead + def updateAccounts(self, *args, **kwargs): + return self.update_accounts(*args, **kwargs) + + + def remove_account(self, user): if user in self.accounts: del self.accounts[user] if user in self.infos: @@ -134,28 +139,33 @@ class Account(Plugin): del self.timestamps[user] + #: Deprecated method, use `remove_account` instead + def removeAccount(self, *args, **kwargs): + return self.remove_account(*args, **kwargs) + + @lock - def getAccountInfo(self, name, force=False): + def get_account_info(self, name, force=False): """ Retrieve account infos for an user, do **not** overwrite this method!\\ - just use it to retrieve infos in hoster plugins. see `loadAccountInfo` + just use it to retrieve infos in hoster plugins. see `load_account_info` :param name: username :param force: reloads cached account information :return: dictionary with information """ - data = Account.loadAccountInfo(self, name) + data = Account.load_account_info(self, name) if force or name not in self.infos: - self.logDebug("Get Account Info for %s" % name) - req = self.getAccountRequest(name) + self.log_debug("Get Account Info for %s" % name) + req = self.get_account_request(name) try: - infos = self.loadAccountInfo(name, req) + infos = self.load_account_info(name, req) if not type(infos) == dict: raise Exception("Wrong return format") except Exception, e: - infos = super(self.__class__, self).loadAccountInfo(name, req) + infos = super(self.__class__, self).load_account_info(name, req) infos['error'] = str(e) if self.core.debug: @@ -164,24 +174,24 @@ class Account(Plugin): if req: req.close() - self.logDebug("Account Info: %s" % infos) + self.log_debug("Account Info: %s" % infos) infos['timestamp'] = time.time() self.infos[name] = infos elif "timestamp" in self.infos[name] and self.infos[name]['timestamp'] + self.info_threshold * 60 < time.time(): - self.logDebug("Reached timeout for account data") - self.scheduleRefresh(name) + self.log_debug("Reached timeout for account data") + self.schedule_refresh(name) data.update(self.infos[name]) return data - def isPremium(self, user): - info = self.getAccountInfo(user) + def is_premium(self, user): + info = self.get_account_info(user) return info['premium'] - def loadAccountInfo(self, name, req=None): + def load_account_info(self, name, req=None): """ This should be overwritten in account plugin,\ and retrieving account information for user @@ -202,20 +212,25 @@ class Account(Plugin): "type" : self.__name__} - def getAllAccounts(self, force=False): - return [self.getAccountInfo(user, force) for user, data in self.accounts.iteritems()] + def get_all_accounts(self, force=False): + return [self.get_account_info(user, force) for user, data in self.accounts.iteritems()] - def getAccountRequest(self, user=None): + #: Deprecated method, use `get_all_accounts` instead + def getAllAccounts(self, *args, **kwargs): + return self.get_all_accounts(*args, **kwargs) + + + def get_account_request(self, user=None): if not user: - user, data = self.selectAccount() + user, data = self.select_account() return self.core.requestFactory.getRequest(self.__name__, user) - def getAccountCookies(self, user=None): + def get_account_cookies(self, user=None): if not user: - user, data = self.selectAccount() + user, data = self.select_account() if not user: return None @@ -223,11 +238,11 @@ class Account(Plugin): return cj - def getAccountData(self, user): + def get_account_data(self, user): return self.accounts[user] - def selectAccount(self): + def select_account(self): """ Returns an valid account name and data """ @@ -244,7 +259,7 @@ class Account(Plugin): if not compare_time(start.split(":"), end.split(":")): continue except Exception: - self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) + self.log_warning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) if user in self.infos: if "validuntil" in self.infos[user]: @@ -262,52 +277,57 @@ class Account(Plugin): return random.choice(usable) - def canUse(self): - return self.selectAccount() != (None, None) + def can_use(self): + return self.select_account() != (None, None) - def parseTraffic(self, value, unit=None): #: return kilobytes + def parse_traffic(self, value, unit=None): #: return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" return parseFileSize(value, unit) - def wrongPassword(self): + def wrong_password(self): raise WrongPassword def empty(self, user): if user in self.infos: - self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % user) + self.log_warning(_("Account %s has not enough traffic, checking again in 30min") % user) self.infos[user].update({"trafficleft": 0}) - self.scheduleRefresh(user, 30 * 60) + self.schedule_refresh(user, 30 * 60) def expired(self, user): if user in self.infos: - self.logWarning(_("Account %s is expired, checking again in 1h") % user) + self.log_warning(_("Account %s is expired, checking again in 1h") % user) self.infos[user].update({"validuntil": time.time() - 1}) - self.scheduleRefresh(user, 60 * 60) + self.schedule_refresh(user, 60 * 60) - def scheduleRefresh(self, user, time=0, force=True): + def schedule_refresh(self, user, time=0, force=True): """ Add task to refresh account info to sheduler """ - self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) - self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) + self.log_debug("Scheduled Account refresh for %s in %s seconds." % (user, time)) + self.core.scheduler.addJob(time, self.get_account_info, [user, force]) + + + #: Deprecated method, use `schedule_refresh` instead + def scheduleRefresh(self, *args, **kwargs): + return self.schedule_refresh(*args, **kwargs) @lock - def checkLogin(self, user): + def check_login(self, user): """ Checks if user is still logged in """ if user in self.timestamps: if self.login_timeout > 0 and self.timestamps[user] + self.login_timeout * 60 < time.time(): - self.logDebug("Reached login timeout for %s" % user) + self.log_debug("Reached login timeout for %s" % user) return self.relogin(user) else: return True -- cgit v1.2.3 From d2e2b127651a5a44b56337eb6d9ca246c97a208a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 17 Jul 2015 03:03:26 +0200 Subject: Spare fixes and code cosmetics --- module/plugins/internal/Account.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 9e0efaee6..8fd16bba9 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -60,9 +60,9 @@ class Account(Plugin): #: set timestamp for login self.timestamps[user] = time.time() - req = self.get_account_request(user) + self.req = self.get_account_request(user) try: - self.login(user, data, req) + self.login(user, data, self.req) except WrongPassword: self.log_warning( @@ -82,8 +82,10 @@ class Account(Plugin): success = True finally: - if req: - req.close() + if hasattr(self, "req"): + if self.req: + self.req.close() + del self.req return success @@ -158,26 +160,31 @@ class Account(Plugin): if force or name not in self.infos: self.log_debug("Get Account Info for %s" % name) - req = self.get_account_request(name) + self.req = self.get_account_request(name) try: - infos = self.load_account_info(name, req) + infos = self.load_account_info(name, self.req) if not type(infos) == dict: raise Exception("Wrong return format") + except Exception, e: - infos = super(self.__class__, self).load_account_info(name, req) + infos = super(self.__class__, self).load_account_info(name, self.req) infos['error'] = str(e) if self.core.debug: traceback.print_exc() - if req: - req.close() + finally: + if hasattr(self, "req"): + if self.req: + self.req.close() + del self.req self.log_debug("Account Info: %s" % infos) infos['timestamp'] = time.time() self.infos[name] = infos + elif "timestamp" in self.infos[name] and self.infos[name]['timestamp'] + self.info_threshold * 60 < time.time(): self.log_debug("Reached timeout for account data") self.schedule_refresh(name) -- cgit v1.2.3 From 9e5d813d7721e351ac02ba72bdc473a7d77ba6b7 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 18 Jul 2015 20:04:36 +0200 Subject: Code cosmetics --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 8fd16bba9..b437b4a55 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -6,7 +6,7 @@ import time import traceback from module.plugins.internal.Plugin import Plugin -from module.utils import compare_time, lock, parseFileSize +from module.utils import compare_time, lock, parseFileSize as parse_size class WrongPassword(Exception): @@ -266,7 +266,7 @@ class Account(Plugin): if not compare_time(start.split(":"), end.split(":")): continue except Exception: - self.log_warning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) + self.log_warning(_("Your Time %s has wrong format, use 1:22-3:44") % time_data) if user in self.infos: if "validuntil" in self.infos[user]: @@ -291,7 +291,7 @@ class Account(Plugin): def parse_traffic(self, value, unit=None): #: return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" - return parseFileSize(value, unit) + return parse_size(value, unit) def wrong_password(self): -- cgit v1.2.3 From 1bc7db9098967a166b17df59065861fbe3cd41d8 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 18 Jul 2015 23:26:48 +0200 Subject: [Hoster] Fix the http request issue --- module/plugins/internal/Account.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index b437b4a55..951d279be 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -16,7 +16,7 @@ class WrongPassword(Exception): class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.04" + __version__ = "0.05" __description__ = """Base account plugin""" __license__ = "GPLv3" @@ -92,8 +92,9 @@ class Account(Plugin): def relogin(self, user): req = self.get_account_request(user) if req: - req.cj.clear() + req.clearCookies() req.close() + if user in self.infos: del self.infos[user] #: delete old information -- cgit v1.2.3 From dad722ac7255640e7e0541c4094a4d2e4de79cd3 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 19 Jul 2015 00:05:58 +0200 Subject: Code cosmetics (2) --- module/plugins/internal/Account.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 951d279be..534f5607d 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -28,12 +28,12 @@ class Account(Plugin): self.manager = manager self.accounts = {} - self.infos = {} #: cache for account information + self.infos = {} #: Cache for account information self.lock = threading.RLock() self.timestamps = {} - self.login_timeout = 10 * 60 #: after that time (in minutes) pyload will relogin the account - self.info_threshold = 10 * 60 #: after that time (in minutes) account data will be reloaded + self.login_timeout = 10 * 60 #: After that time (in minutes) pyload will relogin the account + self.info_threshold = 10 * 60 #: After that time (in minutes) account data will be reloaded self.init() @@ -57,7 +57,7 @@ class Account(Plugin): @lock def _login(self, user, data): - #: set timestamp for login + #: Set timestamp for login self.timestamps[user] = time.time() self.req = self.get_account_request(user) @@ -96,7 +96,7 @@ class Account(Plugin): req.close() if user in self.infos: - del self.infos[user] #: delete old information + del self.infos[user] #: Delete old information return self._login(user, self.accounts[user]) @@ -113,7 +113,7 @@ class Account(Plugin): Updates account and return true if anything changed """ if user in self.accounts: - self.accounts[user]['valid'] = True #: do not remove or accounts will not login + self.accounts[user]['valid'] = True #: Do not remove or accounts will not login if password: self.accounts[user]['password'] = password self.relogin(user) @@ -210,13 +210,13 @@ class Account(Plugin): """ return {"validuntil" : None, #: -1 for unlimited "login" : name, - #: "password" : self.accounts[name]['password'], #: commented due security reason + # "password" : self.accounts[name]['password'], #: Commented due security reason "options" : self.accounts[name]['options'], "valid" : self.accounts[name]['valid'], - "trafficleft": None, #: in bytes, -1 for unlimited + "trafficleft": None, #: In bytes, -1 for unlimited "maxtraffic" : None, "premium" : None, - "timestamp" : 0, #: time this info was retrieved + "timestamp" : 0, #: Time this info was retrieved "type" : self.__name__} @@ -289,7 +289,7 @@ class Account(Plugin): return self.select_account() != (None, None) - def parse_traffic(self, value, unit=None): #: return kilobytes + def parse_traffic(self, value, unit=None): #: Return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" return parse_size(value, unit) -- cgit v1.2.3 From 502517f37c7540b0bddb092e69386d9d6f08800c Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 19 Jul 2015 09:42:34 +0200 Subject: Fix addons --- module/plugins/internal/Account.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 534f5607d..7bf8964ad 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -41,6 +41,9 @@ class Account(Plugin): def init(self): + """ + Initialize additional data structures + """ pass -- cgit v1.2.3 From ff9383bfe06d14d23bc0ed6af79aa8967965d078 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 19 Jul 2015 10:59:52 +0200 Subject: Code cosmetics (3) --- module/plugins/internal/Account.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 7bf8964ad..db0002d09 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -69,14 +69,14 @@ class Account(Plugin): except WrongPassword: self.log_warning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user, - "msg": _("Wrong Password")}) + _("Could not login with account %(user)s | %(msg)s") % {'user': user, + 'msg': _("Wrong Password")}) success = data['valid'] = False except Exception, e: self.log_warning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user, - "msg": e}) + _("Could not login with account %(user)s | %(msg)s") % {'user': user, + 'msg': e}) success = data['valid'] = False if self.core.debug: traceback.print_exc() @@ -126,7 +126,7 @@ class Account(Plugin): self.accounts[user]['options'].update(options) return self.accounts[user]['options'] != before else: - self.accounts[user] = {"password": password, "options": options, "valid": True} + self.accounts[user] = {'password': password, 'options': options, 'valid': True} self._login(user, self.accounts[user]) return True @@ -211,16 +211,16 @@ class Account(Plugin): :param req: `Request` instance :return: """ - return {"validuntil" : None, #: -1 for unlimited - "login" : name, - # "password" : self.accounts[name]['password'], #: Commented due security reason - "options" : self.accounts[name]['options'], - "valid" : self.accounts[name]['valid'], - "trafficleft": None, #: In bytes, -1 for unlimited - "maxtraffic" : None, - "premium" : None, - "timestamp" : 0, #: Time this info was retrieved - "type" : self.__name__} + return {'validuntil' : None, #: -1 for unlimited + 'login' : name, + # 'password' : self.accounts[name]['password'], #: Commented due security reason + 'options' : self.accounts[name]['options'], + 'valid' : self.accounts[name]['valid'], + 'trafficleft': None, #: In bytes, -1 for unlimited + 'maxtraffic' : None, + 'premium' : None, + 'timestamp' : 0, #: Time this info was retrieved + 'type' : self.__name__} def get_all_accounts(self, force=False): @@ -306,7 +306,7 @@ class Account(Plugin): if user in self.infos: self.log_warning(_("Account %s has not enough traffic, checking again in 30min") % user) - self.infos[user].update({"trafficleft": 0}) + self.infos[user].update({'trafficleft': 0}) self.schedule_refresh(user, 30 * 60) @@ -314,7 +314,7 @@ class Account(Plugin): if user in self.infos: self.log_warning(_("Account %s is expired, checking again in 1h") % user) - self.infos[user].update({"validuntil": time.time() - 1}) + self.infos[user].update({'validuntil': time.time() - 1}) self.schedule_refresh(user, 60 * 60) -- cgit v1.2.3 From 56389e28ba5d2f5658278bc7f486d73be747f135 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 19 Jul 2015 11:44:49 +0200 Subject: Rename self.core to self.pyload (plugins only) --- module/plugins/internal/Account.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index db0002d09..72981a108 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -24,7 +24,8 @@ class Account(Plugin): def __init__(self, manager, accounts): - super(Account, self).__init__(manager.core) + self.pyload = manager.core + self.info = {} #: Provide information in dict here self.manager = manager self.accounts = {} @@ -78,7 +79,7 @@ class Account(Plugin): _("Could not login with account %(user)s | %(msg)s") % {'user': user, 'msg': e}) success = data['valid'] = False - if self.core.debug: + if self.pyload.debug: traceback.print_exc() else: @@ -175,7 +176,7 @@ class Account(Plugin): infos = super(self.__class__, self).load_account_info(name, self.req) infos['error'] = str(e) - if self.core.debug: + if self.pyload.debug: traceback.print_exc() finally: @@ -236,7 +237,7 @@ class Account(Plugin): if not user: user, data = self.select_account() - return self.core.requestFactory.getRequest(self.__name__, user) + return self.pyload.requestFactory.getRequest(self.__name__, user) def get_account_cookies(self, user=None): @@ -245,7 +246,7 @@ class Account(Plugin): if not user: return None - cj = self.core.requestFactory.getCookieJar(self.__name__, user) + cj = self.pyload.requestFactory.getCookieJar(self.__name__, user) return cj @@ -323,7 +324,7 @@ class Account(Plugin): Add task to refresh account info to sheduler """ self.log_debug("Scheduled Account refresh for %s in %s seconds." % (user, time)) - self.core.scheduler.addJob(time, self.get_account_info, [user, force]) + self.pyload.scheduler.addJob(time, self.get_account_info, [user, force]) #: Deprecated method, use `schedule_refresh` instead -- cgit v1.2.3 From d38e830b7c0b3c6561a0072c74bbccb5fcdf4a61 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 19 Jul 2015 14:43:42 +0200 Subject: New __status__ magic key --- module/plugins/internal/Account.py | 1 + 1 file changed, 1 insertion(+) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 72981a108..27525e1d2 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -17,6 +17,7 @@ class Account(Plugin): __name__ = "Account" __type__ = "account" __version__ = "0.05" + __status__ = "stable" __description__ = """Base account plugin""" __license__ = "GPLv3" -- cgit v1.2.3 From 4fc28dc09f9632eb4a15a1ef48778427f9dcae33 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Thu, 23 Jul 2015 18:53:06 +0200 Subject: Code cosmetics --- module/plugins/internal/Account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 27525e1d2..96f1cb533 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -206,7 +206,7 @@ class Account(Plugin): def load_account_info(self, name, req=None): """ - This should be overwritten in account plugin,\ + This should be overwritten in account plugin and retrieving account information for user :param name: -- cgit v1.2.3 From 94d017cd2a5c1f194960827a8c7e46afc3682008 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 24 Jul 2015 06:55:49 +0200 Subject: Hotfixes (2) --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 96f1cb533..158a5c7bc 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -17,7 +17,7 @@ class Account(Plugin): __name__ = "Account" __type__ = "account" __version__ = "0.05" - __status__ = "stable" + __status__ = "testing" __description__ = """Base account plugin""" __license__ = "GPLv3" @@ -170,7 +170,7 @@ class Account(Plugin): try: infos = self.load_account_info(name, self.req) - if not type(infos) == dict: + if not type(infos) is dict: raise Exception("Wrong return format") except Exception, e: @@ -279,7 +279,7 @@ class Account(Plugin): if self.infos[user]['validuntil'] > 0 and time.time() > self.infos[user]['validuntil']: continue if "trafficleft" in self.infos[user]: - if self.infos[user]['trafficleft'] == 0: + if self.infos[user]['trafficleft'] is 0: continue usable.append((user, data)) -- cgit v1.2.3 From 761ca5c66e07559925ebbdbc6531f9ca658b12ce Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 24 Jul 2015 16:11:58 +0200 Subject: Code cosmetics --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 158a5c7bc..eaf988974 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -126,7 +126,7 @@ class Account(Plugin): if options: before = self.accounts[user]['options'] self.accounts[user]['options'].update(options) - return self.accounts[user]['options'] != before + return self.accounts[user]['options'] not is before else: self.accounts[user] = {'password': password, 'options': options, 'valid': True} self._login(user, self.accounts[user]) @@ -279,7 +279,7 @@ class Account(Plugin): if self.infos[user]['validuntil'] > 0 and time.time() > self.infos[user]['validuntil']: continue if "trafficleft" in self.infos[user]: - if self.infos[user]['trafficleft'] is 0: + if self.infos[user]['trafficleft'] == 0: continue usable.append((user, data)) @@ -291,7 +291,7 @@ class Account(Plugin): def can_use(self): - return self.select_account() != (None, None) + return self.select_account() not is (None, None) def parse_traffic(self, value, unit=None): #: Return kilobytes -- cgit v1.2.3 From dd13825fbd3df9e441200638cd2a92e3924dfff6 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 24 Jul 2015 23:57:04 +0200 Subject: Fix typo --- module/plugins/internal/Account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index eaf988974..03521a0ea 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -126,7 +126,7 @@ class Account(Plugin): if options: before = self.accounts[user]['options'] self.accounts[user]['options'].update(options) - return self.accounts[user]['options'] not is before + return self.accounts[user]['options'] is not before else: self.accounts[user] = {'password': password, 'options': options, 'valid': True} self._login(user, self.accounts[user]) @@ -291,7 +291,7 @@ class Account(Plugin): def can_use(self): - return self.select_account() not is (None, None) + return self.select_account() is not (None, None) def parse_traffic(self, value, unit=None): #: Return kilobytes -- cgit v1.2.3 From 8f17f875f6e28f73ddb10da59c6464bd04922222 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 25 Jul 2015 04:59:27 +0200 Subject: Account rewritten --- module/plugins/internal/Account.py | 328 ++++++++++++++++++------------------- 1 file changed, 160 insertions(+), 168 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 03521a0ea..3a3fd4768 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- +from __future__ import with_statement + import random -import threading import time import traceback @@ -9,10 +10,6 @@ from module.plugins.internal.Plugin import Plugin from module.utils import compare_time, lock, parseFileSize as parse_size -class WrongPassword(Exception): - pass - - class Account(Plugin): __name__ = "Account" __type__ = "account" @@ -21,25 +18,20 @@ class Account(Plugin): __description__ = """Base account plugin""" __license__ = "GPLv3" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __authors__ = [("mkaay" , "mkaay@mkaay.de" ), + ("Walter Purcaro", "vuolter@gmail.com")] + + + LOGIN_TIMEOUT = 10 * 60 #: After that time (in minutes) pyload will relogin the account + INFO_THRESHOLD = 10 * 60 #: After that time (in minutes) account data will be reloaded def __init__(self, manager, accounts): self.pyload = manager.core self.info = {} #: Provide information in dict here - self.manager = manager - self.accounts = {} - self.infos = {} #: Cache for account information - self.lock = threading.RLock() - self.timestamps = {} - - self.login_timeout = 10 * 60 #: After that time (in minutes) pyload will relogin the account - self.info_threshold = 10 * 60 #: After that time (in minutes) account data will be reloaded - self.init() - - self.set_accounts(accounts) + self.init_accounts(accounts) def init(self): @@ -49,240 +41,239 @@ class Account(Plugin): pass - def login(self, user, data, req): + def login(self, user, password, data, req): """ Login into account, the cookies will be saved so user can be recognized - - :param user: loginname - :param data: data dictionary - :param req: `Request` instance """ pass @lock - def _login(self, user, data): - #: Set timestamp for login - self.timestamps[user] = time.time() - - self.req = self.get_account_request(user) + def _login(self, user): try: - self.login(user, data, self.req) + info = self.info[user] + info['login']['timestamp'] = time.time() #: Set timestamp for login - except WrongPassword: - self.log_warning( - _("Could not login with account %(user)s | %(msg)s") % {'user': user, - 'msg': _("Wrong Password")}) - success = data['valid'] = False + self.req = self.get_request(user) + self.login(user, info['login']['password'], info['data'], self.req) except Exception, e: self.log_warning( _("Could not login with account %(user)s | %(msg)s") % {'user': user, - 'msg': e}) - success = data['valid'] = False + 'msg' : e}) + res = info['login']['valid'] = False if self.pyload.debug: traceback.print_exc() else: - success = True + res = True finally: - if hasattr(self, "req"): - if self.req: - self.req.close() - del self.req - return success + if self.req: + self.req.close() + del self.req + + return res def relogin(self, user): - req = self.get_account_request(user) - if req: + with self.get_request(user) as req: req.clearCookies() - req.close() - if user in self.infos: - del self.infos[user] #: Delete old information + if user in self.info: + self.info[user]['login'].clear() - return self._login(user, self.accounts[user]) + return self._login(user) - def set_accounts(self, accounts): - self.accounts = accounts - for user, data in self.accounts.iteritems(): - self._login(user, data) - self.infos[user] = {} + def init_accounts(self, accounts): + for user, data in accounts.iteritems(): + self.add(user, data['password'], data['options']) + self._login(user) - def update_accounts(self, user, password=None, options={}): + def add(self, user, password=None, options): + if user not in self.info: + self.info[user] = {'login': {'valid': True, 'password': password or "", 'timestamp': 0}, #@NOTE: Do not remove `'valid': True` in 0.4.9 or accounts will not login + 'data' : {'options': options, 'timestamp': 0}} + self._login(user) + return True + else: + self.log_error(_("Error adding account"), _("User already exists")) + + + def update(self, user, password=None, options): """ Updates account and return true if anything changed """ - if user in self.accounts: - self.accounts[user]['valid'] = True #: Do not remove or accounts will not login + if user not in self.info: + return self.add(user, password, options) + + elif password or options: if password: - self.accounts[user]['password'] = password + self.info[user]['login']['password'] = password self.relogin(user) return True + if options: - before = self.accounts[user]['options'] - self.accounts[user]['options'].update(options) - return self.accounts[user]['options'] is not before - else: - self.accounts[user] = {'password': password, 'options': options, 'valid': True} - self._login(user, self.accounts[user]) - return True + before = self.info[user]['data'][user]['options'] + self.info[user]['data']['options'].update(options) + return self.info[user]['data']['options'] != before - #: Deprecated method, use `update_accounts` instead + #: Deprecated method, use `update` instead (Remove in 0.4.10) def updateAccounts(self, *args, **kwargs): - return self.update_accounts(*args, **kwargs) + return self.update(*args, **kwargs) + + def remove(self, user=None): # -> def remove + if not user: + self.info.clear() - def remove_account(self, user): - if user in self.accounts: - del self.accounts[user] - if user in self.infos: - del self.infos[user] - if user in self.timestamps: - del self.timestamps[user] + elif user in self.info: + del self.info[user] - #: Deprecated method, use `remove_account` instead + #: Deprecated method, use `remove` instead (Remove in 0.4.10) def removeAccount(self, *args, **kwargs): - return self.remove_account(*args, **kwargs) + return self.remove(*args, **kwargs) + + + def get_data(self, user, reload=False): + return self.get_info(user, reload)['data'] @lock - def get_account_info(self, name, force=False): + def get_info(self, user, reload=False): """ Retrieve account infos for an user, do **not** overwrite this method!\\ - just use it to retrieve infos in hoster plugins. see `load_account_info` + just use it to retrieve infos in hoster plugins. see `load_info` - :param name: username - :param force: reloads cached account information + :param user: username + :param reload: reloads cached account information :return: dictionary with information """ - data = Account.load_account_info(self, name) + if not reload and user in self.info: + info = self.info[user] - if force or name not in self.infos: - self.log_debug("Get Account Info for %s" % name) - self.req = self.get_account_request(name) + if info['data']['timestamp'] + self.INFO_THRESHOLD * 60 < time.time(): + self.log_debug("Reached timeout for account data") + self.schedule_refresh(user) - try: - infos = self.load_account_info(name, self.req) - if not type(infos) is dict: - raise Exception("Wrong return format") + else: + self.log_debug("Get Account Info for: %s" % user) + info = self.load_info(user) - except Exception, e: - infos = super(self.__class__, self).load_account_info(name, self.req) - infos['error'] = str(e) + self.log_debug("Account Info: %s" % info) + return info - if self.pyload.debug: - traceback.print_exc() - finally: - if hasattr(self, "req"): - if self.req: - self.req.close() - del self.req + def is_premium(self, user): + return self.get_info(user)['premium'] - self.log_debug("Account Info: %s" % infos) - infos['timestamp'] = time.time() - self.infos[name] = infos + def load_info(self, user): + self.log_critical(user in self.info) ############################# - elif "timestamp" in self.infos[name] and self.infos[name]['timestamp'] + self.info_threshold * 60 < time.time(): - self.log_debug("Reached timeout for account data") - self.schedule_refresh(name) + info = self.info[user] + data = info['data'] - data.update(self.infos[name]) - return data + #@TODO: Remove in 0.4.10 + data.update({'login': user, + 'type' : self.__name__}, + 'valid': self.info[user]['login']['valid']) + try: + self.req = self.get_request(user) + extra_info = self.parse_info(user, info['login']['password'], info, req) - def is_premium(self, user): - info = self.get_account_info(user) - return info['premium'] + if extra_info and isinstance(extra_info, dict): + data.update(extra_info) + data['timestamp'] = time.time() + except Exception, e: + self.log_warning(_("Error loading info for account %(user)s | %(err)s") % + {'user': user, 'err': e}) + data['error'] = str(e) - def load_account_info(self, name, req=None): + if self.pyload.debug: + traceback.print_exc(): + + else: + for key in ('premium', 'validuntil', 'trafficleft', 'maxtraffic'): + if key not in data: + data[key] = None + + finally: + if self.req: + self.req.close() + del self.req + + self.info[user].update(info) + return info + + + def parse_info(self, user, password, info, req): """ This should be overwritten in account plugin and retrieving account information for user - :param name: + :param user: :param req: `Request` instance :return: """ - return {'validuntil' : None, #: -1 for unlimited - 'login' : name, - # 'password' : self.accounts[name]['password'], #: Commented due security reason - 'options' : self.accounts[name]['options'], - 'valid' : self.accounts[name]['valid'], - 'trafficleft': None, #: In bytes, -1 for unlimited - 'maxtraffic' : None, - 'premium' : None, - 'timestamp' : 0, #: Time this info was retrieved - 'type' : self.__name__} - - - def get_all_accounts(self, force=False): - return [self.get_account_info(user, force) for user, data in self.accounts.iteritems()] + pass - #: Deprecated method, use `get_all_accounts` instead + #: Remove in 0.4.10 def getAllAccounts(self, *args, **kwargs): - return self.get_all_accounts(*args, **kwargs) + return [self.get_data(user, reload) for user, info in self.info.iteritems()] - def get_account_request(self, user=None): + def get_request(self, user=None): if not user: - user, data = self.select_account() + user, info = self.select() return self.pyload.requestFactory.getRequest(self.__name__, user) - def get_account_cookies(self, user=None): - if not user: - user, data = self.select_account() + def get_cookies(self, user=None): if not user: + user, info = self.select() return None - cj = self.pyload.requestFactory.getCookieJar(self.__name__, user) - return cj - + return self.pyload.requestFactory.getCookieJar(self.__name__, user) - def get_account_data(self, user): - return self.accounts[user] - - def select_account(self): + #@TODO: Random account only? Simply crazy... rewrite + def select(self): """ Returns an valid account name and data """ usable = [] - for user, data in self.accounts.iteritems(): - if not data['valid']: + for user, info in self.info.iteritems(): + if not info['login']['valid']: continue - if "time" in data['options'] and data['options']['time']: + options = info['data']['options'] + if "time" in options and options['time']: time_data = "" try: - time_data = data['options']['time'][0] + time_data = options['time'][0] start, end = time_data.split("-") if not compare_time(start.split(":"), end.split(":")): continue + except Exception: - self.log_warning(_("Your Time %s has wrong format, use 1:22-3:44") % time_data) + self.log_warning(_("Your time %s has wrong format, use 1:22-3:44") % time_data) - if user in self.infos: - if "validuntil" in self.infos[user]: - if self.infos[user]['validuntil'] > 0 and time.time() > self.infos[user]['validuntil']: - continue - if "trafficleft" in self.infos[user]: - if self.infos[user]['trafficleft'] == 0: - continue + if user in self.info: + if None is not self.info[user]['validuntil'] > 0 and time.time() > self.info[user]['validuntil']: + continue + if None is not self.info[user]['trafficleft'] == 0: + continue - usable.append((user, data)) + usable.append((user, info)) if not usable: return None, None @@ -291,44 +282,45 @@ class Account(Plugin): def can_use(self): - return self.select_account() is not (None, None) + return self.select() is not (None, None) def parse_traffic(self, value, unit=None): #: Return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" - return parse_size(value, unit) - - def wrong_password(self): - raise WrongPassword + return parse_size(value, unit) def empty(self, user): - if user in self.infos: - self.log_warning(_("Account %s has not enough traffic, checking again in 30min") % user) + if user not in self.info: + return + + self.log_warning(_("Account %s has not enough traffic, checking again in 30min") % user) - self.infos[user].update({'trafficleft': 0}) - self.schedule_refresh(user, 30 * 60) + self.info[user]['data'].update({'trafficleft': 0}) + self.schedule_refresh(user, 30 * 60) def expired(self, user): - if user in self.infos: - self.log_warning(_("Account %s is expired, checking again in 1h") % user) + if user not in self.info: + return + + self.log_warning(_("Account %s is expired, checking again in 1h") % user) - self.infos[user].update({'validuntil': time.time() - 1}) - self.schedule_refresh(user, 60 * 60) + self.info[user]['data'].update({'validuntil': time.time() - 1}) + self.schedule_refresh(user, 60 * 60) - def schedule_refresh(self, user, time=0, force=True): + def schedule_refresh(self, user, time=0, reload=True): """ Add task to refresh account info to sheduler """ self.log_debug("Scheduled Account refresh for %s in %s seconds." % (user, time)) - self.pyload.scheduler.addJob(time, self.get_account_info, [user, force]) + self.pyload.scheduler.addJob(time, self.get_info, [user, reload]) - #: Deprecated method, use `schedule_refresh` instead + #: Deprecated method, use `schedule_refresh` instead (Remove in 0.4.10) def scheduleRefresh(self, *args, **kwargs): return self.schedule_refresh(*args, **kwargs) @@ -338,8 +330,8 @@ class Account(Plugin): """ Checks if user is still logged in """ - if user in self.timestamps: - if self.login_timeout > 0 and self.timestamps[user] + self.login_timeout * 60 < time.time(): + if user in self.info: + if self.LOGIN_TIMEOUT > 0 and self.info[user]['login']['timestamp'] + self.LOGIN_TIMEOUT * 60 < time.time(): self.log_debug("Reached login timeout for %s" % user) return self.relogin(user) else: -- cgit v1.2.3 From a95c217627a1cb651b24e69f20640df40797aff9 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 25 Jul 2015 09:34:18 +0200 Subject: Account rewritten (2) --- module/plugins/internal/Account.py | 95 +++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 31 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 3a3fd4768..f33d44179 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -4,6 +4,7 @@ from __future__ import with_statement import random import time +import threading import traceback from module.plugins.internal.Plugin import Plugin @@ -29,6 +30,7 @@ class Account(Plugin): def __init__(self, manager, accounts): self.pyload = manager.core self.info = {} #: Provide information in dict here + self.lock = threading.RLock() self.init() self.init_accounts(accounts) @@ -58,9 +60,7 @@ class Account(Plugin): self.login(user, info['login']['password'], info['data'], self.req) except Exception, e: - self.log_warning( - _("Could not login with account %(user)s | %(msg)s") % {'user': user, - 'msg' : e}) + self.log_warning(_("Could not login with username ") + user, e) res = info['login']['valid'] = False if self.pyload.debug: traceback.print_exc() @@ -86,13 +86,15 @@ class Account(Plugin): return self._login(user) + #@TODO: Rewrite in 0.4.10 def init_accounts(self, accounts): for user, data in accounts.iteritems(): self.add(user, data['password'], data['options']) self._login(user) - def add(self, user, password=None, options): + @lock + def add(self, user, password=None, options={}): if user not in self.info: self.info[user] = {'login': {'valid': True, 'password': password or "", 'timestamp': 0}, #@NOTE: Do not remove `'valid': True` in 0.4.9 or accounts will not login 'data' : {'options': options, 'timestamp': 0}} @@ -102,7 +104,8 @@ class Account(Plugin): self.log_error(_("Error adding account"), _("User already exists")) - def update(self, user, password=None, options): + @lock + def update(self, user, password=None, options={}): """ Updates account and return true if anything changed """ @@ -131,7 +134,7 @@ class Account(Plugin): self.info.clear() elif user in self.info: - del self.info[user] + self.info.pop(user, None) #: Deprecated method, use `remove` instead (Remove in 0.4.10) @@ -140,64 +143,88 @@ class Account(Plugin): def get_data(self, user, reload=False): - return self.get_info(user, reload)['data'] + if not user: + return + + info = self.get_info(user, reload) + if info and 'data' in info: + return info['data'] + + #: Deprecated method, use `get_data` instead (Remove in 0.4.10) + def getAccountData(self, *args, **kwargs): + if 'force' in kwargs: + kwargs['reload'] = kwargs['force'] + kwargs.pop('force', None) + data = self.get_data(*args, **kwargs) or {} + if 'options' not in data: + data['options'] = {'limitdl': ['0']} + return data @lock def get_info(self, user, reload=False): """ Retrieve account infos for an user, do **not** overwrite this method!\\ - just use it to retrieve infos in hoster plugins. see `load_info` + just use it to retrieve infos in hoster plugins. see `parse_info` :param user: username :param reload: reloads cached account information :return: dictionary with information """ - if not reload and user in self.info: - info = self.info[user] + traceback.print_exc() ###################### - if info['data']['timestamp'] + self.INFO_THRESHOLD * 60 < time.time(): - self.log_debug("Reached timeout for account data") - self.schedule_refresh(user) + if user not in self.info: + self.log_error(_("User %s not found while retrieving account info") % user) + return - else: + elif reload: self.log_debug("Get Account Info for: %s" % user) - info = self.load_info(user) + info = self._parse_info(user) - self.log_debug("Account Info: %s" % info) + else: + info = self.info[user] + + if self.INFO_THRESHOLD > 0 and info['data']['timestamp'] + self.INFO_THRESHOLD * 60 < time.time(): + self.log_debug("Reached data timeout for %s" % user) + self.schedule_refresh(user) + + safe_info = info.copy() + safe_info['login']['password'] = "**********" + self.log_debug("Account info: %s" % safe_info) return info def is_premium(self, user): - return self.get_info(user)['premium'] + if not user: + return False + info = self.get_info(user, reload) + return info['premium'] if info and 'premium' in info else False - def load_info(self, user): - self.log_critical(user in self.info) ############################# + def _parse_info(self, user): info = self.info[user] data = info['data'] #@TODO: Remove in 0.4.10 data.update({'login': user, - 'type' : self.__name__}, - 'valid': self.info[user]['login']['valid']) + 'type' : self.__name__, + 'valid': self.info[user]['login']['valid']}) try: + data['timestamp'] = time.time() #: Set timestamp for login + self.req = self.get_request(user) - extra_info = self.parse_info(user, info['login']['password'], info, req) + extra_info = self.parse_info(user, info['login']['password'], info, self.req) if extra_info and isinstance(extra_info, dict): data.update(extra_info) - data['timestamp'] = time.time() except Exception, e: - self.log_warning(_("Error loading info for account %(user)s | %(err)s") % - {'user': user, 'err': e}) - data['error'] = str(e) + self.log_warning(_("Error loading info for ") + user, e) if self.pyload.debug: - traceback.print_exc(): + traceback.print_exc() else: for key in ('premium', 'validuntil', 'trafficleft', 'maxtraffic'): @@ -227,7 +254,11 @@ class Account(Plugin): #: Remove in 0.4.10 def getAllAccounts(self, *args, **kwargs): - return [self.get_data(user, reload) for user, info in self.info.iteritems()] + return [self.getAccountData(user, *args, **kwargs) for user, info in self.info.iteritems()] + + + def login_fail(self, reason=_("Login handshake has failed")): + return self.fail(reason) def get_request(self, user=None): @@ -240,7 +271,6 @@ class Account(Plugin): def get_cookies(self, user=None): if not user: user, info = self.select() - return None return self.pyload.requestFactory.getCookieJar(self.__name__, user) @@ -316,17 +346,20 @@ class Account(Plugin): """ Add task to refresh account info to sheduler """ - self.log_debug("Scheduled Account refresh for %s in %s seconds." % (user, time)) + self.log_debug("Scheduled refresh for %s in %s seconds" % (user, time)) self.pyload.scheduler.addJob(time, self.get_info, [user, reload]) #: Deprecated method, use `schedule_refresh` instead (Remove in 0.4.10) def scheduleRefresh(self, *args, **kwargs): + if 'force' in kwargs: + kwargs['reload'] = kwargs['force'] + kwargs.pop('force', None) return self.schedule_refresh(*args, **kwargs) @lock - def check_login(self, user): + def is_logged(self, user): """ Checks if user is still logged in """ -- cgit v1.2.3 From 952001324e1faf584b1adcb01c4a0406a3722932 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 25 Jul 2015 09:42:49 +0200 Subject: =?UTF-8?q?Don't=20user=20dictionary=E2=80=99s=20iterator=20method?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index f33d44179..b59a59932 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -88,7 +88,7 @@ class Account(Plugin): #@TODO: Rewrite in 0.4.10 def init_accounts(self, accounts): - for user, data in accounts.iteritems(): + for user, data in accounts.items(): self.add(user, data['password'], data['options']) self._login(user) @@ -254,7 +254,7 @@ class Account(Plugin): #: Remove in 0.4.10 def getAllAccounts(self, *args, **kwargs): - return [self.getAccountData(user, *args, **kwargs) for user, info in self.info.iteritems()] + return [self.getAccountData(user, *args, **kwargs) for user, info in self.info.items()] def login_fail(self, reason=_("Login handshake has failed")): @@ -281,7 +281,7 @@ class Account(Plugin): Returns an valid account name and data """ usable = [] - for user, info in self.info.iteritems(): + for user, info in self.info.items(): if not info['login']['valid']: continue -- cgit v1.2.3 From f83389333ec10376452aa5f6d5ccd3963c6bafa1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 27 Jul 2015 10:28:30 +0200 Subject: Update internal plugins --- module/plugins/internal/Account.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index b59a59932..f1a30a9cb 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -14,7 +14,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.05" + __version__ = "0.06" __status__ = "testing" __description__ = """Base account plugin""" @@ -66,7 +66,7 @@ class Account(Plugin): traceback.print_exc() else: - res = True + res = info['login']['valid'] = True finally: if self.req: @@ -96,7 +96,7 @@ class Account(Plugin): @lock def add(self, user, password=None, options={}): if user not in self.info: - self.info[user] = {'login': {'valid': True, 'password': password or "", 'timestamp': 0}, #@NOTE: Do not remove `'valid': True` in 0.4.9 or accounts will not login + self.info[user] = {'login': {'valid': None, 'password': password or "", 'timestamp': 0}, 'data' : {'options': options, 'timestamp': 0}} self._login(user) return True @@ -171,8 +171,6 @@ class Account(Plugin): :param reload: reloads cached account information :return: dictionary with information """ - traceback.print_exc() ###################### - if user not in self.info: self.log_error(_("User %s not found while retrieving account info") % user) return @@ -312,7 +310,7 @@ class Account(Plugin): def can_use(self): - return self.select() is not (None, None) + return self.select() != (None, None) def parse_traffic(self, value, unit=None): #: Return kilobytes -- cgit v1.2.3 From 34f48259060656077b5cb45edd8f9d92bb0282de Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 27 Jul 2015 20:19:03 +0200 Subject: Bunch of fixups --- module/plugins/internal/Account.py | 40 ++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index f1a30a9cb..b3d9c97f9 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -60,7 +60,7 @@ class Account(Plugin): self.login(user, info['login']['password'], info['data'], self.req) except Exception, e: - self.log_warning(_("Could not login with username ") + user, e) + self.log_warning(_("Could not login user `%s`") % user, e) res = info['login']['valid'] = False if self.pyload.debug: traceback.print_exc() @@ -77,6 +77,8 @@ class Account(Plugin): def relogin(self, user): + self.log_info(_("Relogin user `%s`...") % user) + with self.get_request(user) as req: req.clearCookies() @@ -90,18 +92,27 @@ class Account(Plugin): def init_accounts(self, accounts): for user, data in accounts.items(): self.add(user, data['password'], data['options']) - self._login(user) @lock def add(self, user, password=None, options={}): if user not in self.info: - self.info[user] = {'login': {'valid': None, 'password': password or "", 'timestamp': 0}, - 'data' : {'options': options, 'timestamp': 0}} + self.info[user] = {'login': {'valid' : None, + 'password' : password or "", + 'timestamp': 0}, + 'data' : {'options' : options, + 'premium' : None, + 'validuntil' : None, + 'trafficleft': None, + 'maxtraffic' : None, + 'timestamp' : 0}} + + self.log_info(_("Login user `%s`...") % user) self._login(user) return True + else: - self.log_error(_("Error adding account"), _("User already exists")) + self.log_error(_("Error adding user `%s`") % user, _("User already exists")) @lock @@ -172,11 +183,11 @@ class Account(Plugin): :return: dictionary with information """ if user not in self.info: - self.log_error(_("User %s not found while retrieving account info") % user) + self.log_error(_("User `%s` not found while retrieving account info") % user) return elif reload: - self.log_debug("Get Account Info for: %s" % user) + self.log_info(_("Parsing account info for user `%s`...") % user) info = self._parse_info(user) else: @@ -188,7 +199,7 @@ class Account(Plugin): safe_info = info.copy() safe_info['login']['password'] = "**********" - self.log_debug("Account info: %s" % safe_info) + self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) return info @@ -219,16 +230,11 @@ class Account(Plugin): data.update(extra_info) except Exception, e: - self.log_warning(_("Error loading info for ") + user, e) + self.log_warning(_("Error loading info for user `%s`") % user, e) if self.pyload.debug: traceback.print_exc() - else: - for key in ('premium', 'validuntil', 'trafficleft', 'maxtraffic'): - if key not in data: - data[key] = None - finally: if self.req: self.req.close() @@ -324,7 +330,7 @@ class Account(Plugin): if user not in self.info: return - self.log_warning(_("Account %s has not enough traffic, checking again in 30min") % user) + self.log_warning(_("Account `%s` has not enough traffic") % user, _("Checking again in 30 minutes")) self.info[user]['data'].update({'trafficleft': 0}) self.schedule_refresh(user, 30 * 60) @@ -334,7 +340,7 @@ class Account(Plugin): if user not in self.info: return - self.log_warning(_("Account %s is expired, checking again in 1h") % user) + self.log_warning(_("Account `%s` is expired") % user, _("Checking again in 60 minutes")) self.info[user]['data'].update({'validuntil': time.time() - 1}) self.schedule_refresh(user, 60 * 60) @@ -344,7 +350,7 @@ class Account(Plugin): """ Add task to refresh account info to sheduler """ - self.log_debug("Scheduled refresh for %s in %s seconds" % (user, time)) + self.log_debug("Scheduled refresh for user `%s` in %s seconds" % (user, time)) self.pyload.scheduler.addJob(time, self.get_info, [user, reload]) -- cgit v1.2.3 From 127e42ec74b276fd43618af2a8f3d450a8437af7 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Jul 2015 04:43:10 +0200 Subject: [Account] Hotfix --- module/plugins/internal/Account.py | 94 +++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 32 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index b3d9c97f9..766fe3f71 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -from __future__ import with_statement - import random import time import threading import traceback +from operator import itemgetter + from module.plugins.internal.Plugin import Plugin from module.utils import compare_time, lock, parseFileSize as parse_size @@ -14,7 +14,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.06" + __version__ = "0.07" __status__ = "testing" __description__ = """Base account plugin""" @@ -32,6 +32,8 @@ class Account(Plugin): self.info = {} #: Provide information in dict here self.lock = threading.RLock() + self.accounts = accounts #@TODO: Remove in 0.4.10 + self.init() self.init_accounts(accounts) @@ -62,11 +64,14 @@ class Account(Plugin): except Exception, e: self.log_warning(_("Could not login user `%s`") % user, e) res = info['login']['valid'] = False + self.accounts[user]['valid'] = False #@TODO: Remove in 0.4.10 + if self.pyload.debug: traceback.print_exc() else: res = info['login']['valid'] = True + self.accounts[user]['valid'] = True #@TODO: Remove in 0.4.10 finally: if self.req: @@ -79,8 +84,10 @@ class Account(Plugin): def relogin(self, user): self.log_info(_("Relogin user `%s`...") % user) - with self.get_request(user) as req: + req = self.get_request(user) + if req: req.clearCookies() + req.close() if user in self.info: self.info[user]['login'].clear() @@ -107,6 +114,13 @@ class Account(Plugin): 'maxtraffic' : None, 'timestamp' : 0}} + #@TODO: Remove in 0.4.10 + self.accounts[user] = self.info[user]['data'] + self.accounts[user].update({'login' : user, + 'type' : self.__name__, + 'valid' : self.info[user]['login']['valid'], + 'password': self.info[user]['login']['password']}) + self.log_info(_("Login user `%s`...") % user) self._login(user) return True @@ -120,20 +134,25 @@ class Account(Plugin): """ Updates account and return true if anything changed """ + if not password or not options: + return + if user not in self.info: return self.add(user, password, options) - elif password or options: + else: if password: self.info[user]['login']['password'] = password + self.accounts[user]['password'] = password #@TODO: Remove in 0.4.10 self.relogin(user) - return True if options: before = self.info[user]['data'][user]['options'] self.info[user]['data']['options'].update(options) return self.info[user]['data']['options'] != before + return True + #: Deprecated method, use `update` instead (Remove in 0.4.10) def updateAccounts(self, *args, **kwargs): @@ -143,9 +162,11 @@ class Account(Plugin): def remove(self, user=None): # -> def remove if not user: self.info.clear() + self.accounts.clear() #@TODO: Remove in 0.4.10 elif user in self.info: self.info.pop(user, None) + self.accounts.pop(user, None) #@TODO: Remove in 0.4.10 #: Deprecated method, use `remove` instead (Remove in 0.4.10) @@ -167,11 +188,14 @@ class Account(Plugin): if 'force' in kwargs: kwargs['reload'] = kwargs['force'] kwargs.pop('force', None) + data = self.get_data(*args, **kwargs) or {} if 'options' not in data: data['options'] = {'limitdl': ['0']} + return data + @lock def get_info(self, user, reload=False): """ @@ -199,7 +223,9 @@ class Account(Plugin): safe_info = info.copy() safe_info['login']['password'] = "**********" + safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) + return info @@ -213,21 +239,15 @@ class Account(Plugin): def _parse_info(self, user): info = self.info[user] - data = info['data'] - - #@TODO: Remove in 0.4.10 - data.update({'login': user, - 'type' : self.__name__, - 'valid': self.info[user]['login']['valid']}) try: - data['timestamp'] = time.time() #: Set timestamp for login + info['data']['timestamp'] = time.time() #: Set timestamp for login self.req = self.get_request(user) extra_info = self.parse_info(user, info['login']['password'], info, self.req) if extra_info and isinstance(extra_info, dict): - data.update(extra_info) + info['data'].update(extra_info) except Exception, e: self.log_warning(_("Error loading info for user `%s`") % user, e) @@ -279,40 +299,50 @@ class Account(Plugin): return self.pyload.requestFactory.getCookieJar(self.__name__, user) - #@TODO: Random account only? Simply crazy... rewrite def select(self): """ - Returns an valid account name and data + Returns a valid account name and data """ - usable = [] + free_accounts = [] + premium_accounts = [] + for user, info in self.info.items(): if not info['login']['valid']: continue - options = info['data']['options'] - if "time" in options and options['time']: + data = info['data'] + + if "time" in data['options'] and data['options']['time']: time_data = "" try: - time_data = options['time'][0] + time_data = data['options']['time'][0] start, end = time_data.split("-") + if not compare_time(start.split(":"), end.split(":")): continue except Exception: - self.log_warning(_("Your time %s has wrong format, use 1:22-3:44") % time_data) + self.log_warning(_("Wrong time format `%s` for account `%s`, use 1:22-3:44") % (user, time_data)) - if user in self.info: - if None is not self.info[user]['validuntil'] > 0 and time.time() > self.info[user]['validuntil']: - continue - if None is not self.info[user]['trafficleft'] == 0: - continue + if data['trafficleft'] == 0: + continue + + if data['validuntil'] > 0 and time.time() > data['validuntil']: + continue + + if data['premium']: + premium_accounts.append((user, info)) + + else: + free_accounts.append((user, info)) - usable.append((user, info)) + all_accounts = premium_accounts or free_accounts + fav_accounts = [(user, info) for user, info in all_accounts if info['validuntil'] is not None] - if not usable: - return None, None + accounts = sorted(fav_accounts or all_accounts, + key=itemgetter("validuntil"), reverse=True) or [(None, None)] - return random.choice(usable) + return accounts[0] def can_use(self): @@ -332,7 +362,7 @@ class Account(Plugin): self.log_warning(_("Account `%s` has not enough traffic") % user, _("Checking again in 30 minutes")) - self.info[user]['data'].update({'trafficleft': 0}) + self.info[user]['data']['trafficleft'] = 0 self.schedule_refresh(user, 30 * 60) @@ -342,7 +372,7 @@ class Account(Plugin): self.log_warning(_("Account `%s` is expired") % user, _("Checking again in 60 minutes")) - self.info[user]['data'].update({'validuntil': time.time() - 1}) + self.info[user]['data']['validuntil'] = time.time() - 1 self.schedule_refresh(user, 60 * 60) -- cgit v1.2.3 From babf7f311d257d621a101b2d44e74c8e562629bd Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Jul 2015 17:08:59 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1578 --- module/plugins/internal/Account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 766fe3f71..15078b100 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -14,7 +14,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.07" + __version__ = "0.08" __status__ = "testing" __description__ = """Base account plugin""" @@ -327,7 +327,7 @@ class Account(Plugin): if data['trafficleft'] == 0: continue - if data['validuntil'] > 0 and time.time() > data['validuntil']: + if time.time() > data['validuntil'] > 0: continue if data['premium']: @@ -337,7 +337,7 @@ class Account(Plugin): free_accounts.append((user, info)) all_accounts = premium_accounts or free_accounts - fav_accounts = [(user, info) for user, info in all_accounts if info['validuntil'] is not None] + fav_accounts = [(user, info) for user, info in all_accounts if info['data']['validuntil'] is not None] accounts = sorted(fav_accounts or all_accounts, key=itemgetter("validuntil"), reverse=True) or [(None, None)] -- cgit v1.2.3 From 554a4ddde1115ea4fa307bddcd66aec0cbd3f8ee Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Jul 2015 18:43:26 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1578 (2) --- module/plugins/internal/Account.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 15078b100..b8230a09d 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -14,7 +14,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.08" + __version__ = "0.09" __status__ = "testing" __description__ = """Base account plugin""" @@ -301,10 +301,10 @@ class Account(Plugin): def select(self): """ - Returns a valid account name and data + Returns a valid account name and info """ - free_accounts = [] - premium_accounts = [] + free_accounts = {} + premium_accounts = {} for user, info in self.info.items(): if not info['login']['valid']: @@ -331,18 +331,24 @@ class Account(Plugin): continue if data['premium']: - premium_accounts.append((user, info)) + premium_accounts[user] = info else: - free_accounts.append((user, info)) + free_accounts[user] = info - all_accounts = premium_accounts or free_accounts - fav_accounts = [(user, info) for user, info in all_accounts if info['data']['validuntil'] is not None] + account_list = (premium_accounts or free_accounts).items() - accounts = sorted(fav_accounts or all_accounts, - key=itemgetter("validuntil"), reverse=True) or [(None, None)] + if not account_list: + return None, None - return accounts[0] + validuntil_list = [(user, info) for user, info in account_list if info['data']['validuntil']] + + if not validuntil_list: + return random.choice(account_list) #@TODO: Random account?! Recheck in 0.4.10 + + return sorted(validuntil_list, + key=lambda user, info: info['data']['validuntil'], + reverse=True)[0] def can_use(self): -- cgit v1.2.3 From 9e44724d6dda3e1f47cf4d6de4b3e521a244ba4b Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Jul 2015 19:15:28 +0200 Subject: Fix content-disposition --- module/plugins/internal/Account.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index b8230a09d..788b62e7e 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -5,8 +5,6 @@ import time import threading import traceback -from operator import itemgetter - from module.plugins.internal.Plugin import Plugin from module.utils import compare_time, lock, parseFileSize as parse_size -- cgit v1.2.3 From 9e3ef8bddc2c599403c4ac5090cd12245e802dee Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Jul 2015 22:19:52 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1578 (3) --- module/plugins/internal/Account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 788b62e7e..3084f02c7 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -12,7 +12,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.09" + __version__ = "0.10" __status__ = "testing" __description__ = """Base account plugin""" @@ -345,7 +345,7 @@ class Account(Plugin): return random.choice(account_list) #@TODO: Random account?! Recheck in 0.4.10 return sorted(validuntil_list, - key=lambda user, info: info['data']['validuntil'], + key=lambda a: a[1]['data']['validuntil'], reverse=True)[0] -- cgit v1.2.3 From d06daeb274da6d7886ab96ba639e18cebb67cc6f Mon Sep 17 00:00:00 2001 From: TodsDeath Date: Wed, 29 Jul 2015 10:44:18 +0200 Subject: Update Account.py the needed premium key is not directly in info, but in the sub-directory 'data': {'data': {'login': '***', 'maxtraffic': None, 'options': {'limitdl': ['0']}, 'password': '**********', 'premium': True, 'timestamp': 1438159062.570853, 'trafficleft': -1, 'type': 'RealdebridCom', 'valid': True, 'validuntil': 1450976583.0}, 'login': {'password': '**********', 'timestamp': 1438159044.071365, 'valid': True}} --- module/plugins/internal/Account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 3084f02c7..55ef6c5f9 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -232,7 +232,7 @@ class Account(Plugin): return False info = self.get_info(user, reload) - return info['premium'] if info and 'premium' in info else False + return info['data']['premium'] if info and 'data' in info and 'premium' in info['data'] else False def _parse_info(self, user): -- cgit v1.2.3 From fd7b164840d2bcf1af86e7eece46ada9e91e2f41 Mon Sep 17 00:00:00 2001 From: TodsDeath Date: Wed, 29 Jul 2015 11:10:04 +0200 Subject: Update Account.py better readability than conditional expression --- module/plugins/internal/Account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 55ef6c5f9..d6e4ce8ab 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -232,7 +232,7 @@ class Account(Plugin): return False info = self.get_info(user, reload) - return info['data']['premium'] if info and 'data' in info and 'premium' in info['data'] else False + return info.get('data', {}).get('premium', False) def _parse_info(self, user): -- cgit v1.2.3 From 3f2def49161ad864ae900b2902767c29cab6e3b3 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 31 Jul 2015 03:46:01 +0200 Subject: [Account] Fix ********** bug --- module/plugins/internal/Account.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index d6e4ce8ab..a33cdffac 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +import copy import random import time import threading @@ -12,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.10" + __version__ = "0.11" __status__ = "testing" __description__ = """Base account plugin""" @@ -219,7 +220,7 @@ class Account(Plugin): self.log_debug("Reached data timeout for %s" % user) self.schedule_refresh(user) - safe_info = info.copy() + safe_info = copy.deepcopy(info) safe_info['login']['password'] = "**********" safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) -- cgit v1.2.3 From cc3c575a68fd4b585f0e4af586e027fddb0fe605 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 31 Jul 2015 10:38:51 +0200 Subject: Fix and improve account logic --- module/plugins/internal/Account.py | 71 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index a33cdffac..a402c4ad7 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.11" + __version__ = "0.12" __status__ = "testing" __description__ = """Base account plugin""" @@ -23,14 +23,14 @@ class Account(Plugin): LOGIN_TIMEOUT = 10 * 60 #: After that time (in minutes) pyload will relogin the account - INFO_THRESHOLD = 10 * 60 #: After that time (in minutes) account data will be reloaded + INFO_THRESHOLD = 30 * 60 #: After that time (in minutes) account data will be reloaded def __init__(self, manager, accounts): - self.pyload = manager.core - self.info = {} #: Provide information in dict here - self.lock = threading.RLock() - + self.pyload = manager.core + self.info = {} #: Provide information in dict here + self.lock = threading.RLock() + self.req = None self.accounts = accounts #@TODO: Remove in 0.4.10 self.init() @@ -73,9 +73,7 @@ class Account(Plugin): self.accounts[user]['valid'] = True #@TODO: Remove in 0.4.10 finally: - if self.req: - self.req.close() - del self.req + self.del_request() return res @@ -86,7 +84,7 @@ class Account(Plugin): req = self.get_request(user) if req: req.clearCookies() - req.close() + self.del_request() if user in self.info: self.info[user]['login'].clear() @@ -110,8 +108,7 @@ class Account(Plugin): 'premium' : None, 'validuntil' : None, 'trafficleft': None, - 'maxtraffic' : None, - 'timestamp' : 0}} + 'maxtraffic' : None}} #@TODO: Remove in 0.4.10 self.accounts[user] = self.info[user]['data'] @@ -133,7 +130,7 @@ class Account(Plugin): """ Updates account and return true if anything changed """ - if not password or not options: + if not (password or options): return if user not in self.info: @@ -173,6 +170,7 @@ class Account(Plugin): return self.remove(*args, **kwargs) + #@NOTE: Remove in 0.4.10? def get_data(self, user, reload=False): if not user: return @@ -213,18 +211,18 @@ class Account(Plugin): self.log_info(_("Parsing account info for user `%s`...") % user) info = self._parse_info(user) + safe_info = copy.deepcopy(info) + safe_info['login']['password'] = "**********" + safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 + self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) + else: info = self.info[user] - if self.INFO_THRESHOLD > 0 and info['data']['timestamp'] + self.INFO_THRESHOLD * 60 < time.time(): + if self.INFO_THRESHOLD > 0 and info['login']['timestamp'] + self.INFO_THRESHOLD < time.time(): self.log_debug("Reached data timeout for %s" % user) self.schedule_refresh(user) - safe_info = copy.deepcopy(info) - safe_info['login']['password'] = "**********" - safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 - self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) - return info @@ -232,32 +230,31 @@ class Account(Plugin): if not user: return False - info = self.get_info(user, reload) - return info.get('data', {}).get('premium', False) + info = self.get_info(user) + return info['data']['premium'] def _parse_info(self, user): info = self.info[user] - try: - info['data']['timestamp'] = time.time() #: Set timestamp for login + if not info['login']['valid']: + return info + try: self.req = self.get_request(user) extra_info = self.parse_info(user, info['login']['password'], info, self.req) if extra_info and isinstance(extra_info, dict): info['data'].update(extra_info) - except Exception, e: + except (Fail, Exception), e: self.log_warning(_("Error loading info for user `%s`") % user, e) if self.pyload.debug: traceback.print_exc() finally: - if self.req: - self.req.close() - del self.req + self.del_request() self.info[user].update(info) return info @@ -291,6 +288,13 @@ class Account(Plugin): return self.pyload.requestFactory.getRequest(self.__name__, user) + def del_request(self): + try: + self.req.close() + finally: + self.req = None + + def get_cookies(self, user=None): if not user: user, info = self.select() @@ -350,10 +354,6 @@ class Account(Plugin): reverse=True)[0] - def can_use(self): - return self.select() != (None, None) - - def parse_traffic(self, value, unit=None): #: Return kilobytes if not unit and not isinstance(value, basestring): unit = "KB" @@ -392,20 +392,19 @@ class Account(Plugin): #: Deprecated method, use `schedule_refresh` instead (Remove in 0.4.10) def scheduleRefresh(self, *args, **kwargs): if 'force' in kwargs: - kwargs['reload'] = kwargs['force'] - kwargs.pop('force', None) + kwargs.pop('force', None) #@TODO: Recheck in 0.4.10 return self.schedule_refresh(*args, **kwargs) @lock - def is_logged(self, user): + def is_logged(self, user, relogin=False): """ Checks if user is still logged in """ if user in self.info: - if self.LOGIN_TIMEOUT > 0 and self.info[user]['login']['timestamp'] + self.LOGIN_TIMEOUT * 60 < time.time(): + if self.LOGIN_TIMEOUT > 0 and self.info[user]['login']['timestamp'] + self.LOGIN_TIMEOUT < time.time(): self.log_debug("Reached login timeout for %s" % user) - return self.relogin(user) + return self.relogin(user) if relogin else False else: return True else: -- cgit v1.2.3 From 21cf50c60a794b5ca7d54408b590f74d4567ca79 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 2 Aug 2015 07:15:28 +0200 Subject: Update some plugins --- module/plugins/internal/Account.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index a402c4ad7..021dedf60 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.12" + __version__ = "0.13" __status__ = "testing" __description__ = """Base account plugin""" @@ -73,7 +73,7 @@ class Account(Plugin): self.accounts[user]['valid'] = True #@TODO: Remove in 0.4.10 finally: - self.del_request() + self.clean() return res @@ -84,7 +84,7 @@ class Account(Plugin): req = self.get_request(user) if req: req.clearCookies() - self.del_request() + self.clean() if user in self.info: self.info[user]['login'].clear() @@ -254,7 +254,7 @@ class Account(Plugin): traceback.print_exc() finally: - self.del_request() + self.clean() self.info[user].update(info) return info @@ -288,13 +288,6 @@ class Account(Plugin): return self.pyload.requestFactory.getRequest(self.__name__, user) - def del_request(self): - try: - self.req.close() - finally: - self.req = None - - def get_cookies(self, user=None): if not user: user, info = self.select() -- cgit v1.2.3 From 84f2193d76f7c6f47c834dc8902d8ead8e45a11a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 2 Aug 2015 07:44:07 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1640 (2) --- module/plugins/internal/Account.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 021dedf60..1da31eede 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.13" + __version__ = "0.14" __status__ = "testing" __description__ = """Base account plugin""" @@ -27,10 +27,9 @@ class Account(Plugin): def __init__(self, manager, accounts): - self.pyload = manager.core - self.info = {} #: Provide information in dict here + self._init(manager.core) + self.lock = threading.RLock() - self.req = None self.accounts = accounts #@TODO: Remove in 0.4.10 self.init() -- cgit v1.2.3 From 5e15580202c44628f2fbfabad0c3f693975fb3c9 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 2 Aug 2015 17:13:17 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1663 --- module/plugins/internal/Account.py | 1 - 1 file changed, 1 deletion(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 1da31eede..e9ba5e533 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -73,7 +73,6 @@ class Account(Plugin): finally: self.clean() - return res -- cgit v1.2.3 From 8180f932262473e4f6ab46ae65846c91ada6366d Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 2 Aug 2015 21:39:11 +0200 Subject: Fix https://github.com/pyload/pyload/issues/1664 --- module/plugins/internal/Account.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index e9ba5e533..4553f3a79 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,13 +13,12 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.14" + __version__ = "0.15" __status__ = "testing" __description__ = """Base account plugin""" __license__ = "GPLv3" - __authors__ = [("mkaay" , "mkaay@mkaay.de" ), - ("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] LOGIN_TIMEOUT = 10 * 60 #: After that time (in minutes) pyload will relogin the account @@ -141,7 +140,7 @@ class Account(Plugin): self.relogin(user) if options: - before = self.info[user]['data'][user]['options'] + before = self.info[user]['data']['options'] self.info[user]['data']['options'].update(options) return self.info[user]['data']['options'] != before -- cgit v1.2.3 From 2cf928db10224b5327f918dceaa13273753620ac Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 4 Aug 2015 18:06:42 +0200 Subject: Some fixes --- module/plugins/internal/Account.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index 4553f3a79..ec89caa00 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.15" + __version__ = "0.16" __status__ = "testing" __description__ = """Base account plugin""" @@ -190,7 +190,6 @@ class Account(Plugin): return data - @lock def get_info(self, user, reload=False): """ Retrieve account infos for an user, do **not** overwrite this method!\\ @@ -213,13 +212,13 @@ class Account(Plugin): safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) + elif self.INFO_THRESHOLD > 0 and self.info[user]['login']['timestamp'] + self.INFO_THRESHOLD < time.time(): + self.log_debug("Reached data timeout for %s" % user) + info = self.get_info(user, True) + else: info = self.info[user] - if self.INFO_THRESHOLD > 0 and info['login']['timestamp'] + self.INFO_THRESHOLD < time.time(): - self.log_debug("Reached data timeout for %s" % user) - self.schedule_refresh(user) - return info @@ -371,12 +370,12 @@ class Account(Plugin): self.schedule_refresh(user, 60 * 60) - def schedule_refresh(self, user, time=0, reload=True): + def schedule_refresh(self, user, time=0): """ Add task to refresh account info to sheduler """ self.log_debug("Scheduled refresh for user `%s` in %s seconds" % (user, time)) - self.pyload.scheduler.addJob(time, self.get_info, [user, reload]) + self.pyload.scheduler.addJob(time, self.get_info, [user, True]) #: Deprecated method, use `schedule_refresh` instead (Remove in 0.4.10) -- cgit v1.2.3 From 34728780b6f4f560dbb033e8955b7c2f1dec02e5 Mon Sep 17 00:00:00 2001 From: GammaC0de Date: Tue, 4 Aug 2015 22:48:26 +0300 Subject: [Account] fix relogin not working --- module/plugins/internal/Account.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'module/plugins/internal/Account.py') diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py index ec89caa00..2713e8da4 100644 --- a/module/plugins/internal/Account.py +++ b/module/plugins/internal/Account.py @@ -13,7 +13,7 @@ from module.utils import compare_time, lock, parseFileSize as parse_size class Account(Plugin): __name__ = "Account" __type__ = "account" - __version__ = "0.16" + __version__ = "0.17" __status__ = "testing" __description__ = """Base account plugin""" @@ -83,9 +83,6 @@ class Account(Plugin): req.clearCookies() self.clean() - if user in self.info: - self.info[user]['login'].clear() - return self._login(user) -- cgit v1.2.3