From 5499be89203a18ca61a21cfc7266cf0f4ebe6547 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Thu, 15 Dec 2011 23:18:21 +0100 Subject: refractoring --- module/interaction/InteractionManager.py | 89 ++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 module/interaction/InteractionManager.py (limited to 'module/interaction/InteractionManager.py') diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py new file mode 100644 index 000000000..8bb500f3b --- /dev/null +++ b/module/interaction/InteractionManager.py @@ -0,0 +1,89 @@ +# -*- 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: RaNaN +""" +from time import time +from utils import lock +from traceback import print_exc +from threading import Lock + + + + +class InteractionManager: + """ + Class that gives ability to interact with the user. + Arbitary task with predefined output and input type can be set off. + Asyncronous callbacks and default values keeps the ability to fallback if no user is present. + """ + def __init__(self, core): + self.lock = Lock() + self.core = core + self.tasks = [] #task store, for outgoing tasks only + + self.ids = 0 #only for internal purpose + + def work(self): + """Mainloop that gets the work done""" + + def newTask(self, img, format, file, result_type): + task = CaptchaTask(self.ids, img, format, file, result_type) + self.ids += 1 + return task + + @lock + def removeTask(self, task): + if task in self.tasks: + self.tasks.remove(task) + + @lock + def getTask(self): + for task in self.tasks: + if task.status in ("waiting", "shared-user"): + return task + + @lock + def getTaskByID(self, tid): + for task in self.tasks: + if task.id == str(tid): #task ids are strings + self.lock.release() + return task + + def handleCaptcha(self, task): + cli = self.core.isClientConnected() + + if cli: #client connected -> should solve the captcha + task.setWaiting(50) #wait 50 sec for response + + for plugin in self.core.hookManager.activePlugins(): + try: + plugin.newCaptchaTask(task) + except: + if self.core.debug: + print_exc() + + if task.handler or cli: #the captcha was handled + self.tasks.append(task) + return True + + task.error = _("No Client connected for captcha decrypting") + + return False + + +if __name__ == "__main__": + + it = InteractionTask() \ No newline at end of file -- cgit v1.2.3 From 4a3a81b63cd85cc3dcd9669868a2079da65838a2 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 3 Jan 2012 20:41:23 +0100 Subject: fixes for old style decrypter --- module/interaction/InteractionManager.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'module/interaction/InteractionManager.py') diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py index 8bb500f3b..5ebcd1fcd 100644 --- a/module/interaction/InteractionManager.py +++ b/module/interaction/InteractionManager.py @@ -15,14 +15,10 @@ @author: RaNaN """ -from time import time from utils import lock from traceback import print_exc from threading import Lock - - - class InteractionManager: """ Class that gives ability to interact with the user. -- cgit v1.2.3 From 4df2b77fdf42046fe19bd371be7c7255986b5980 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 6 Mar 2012 13:36:39 +0100 Subject: renamed hooks to addons, new filemanager and database, many new api methods you will loose ALL your LINKS, webinterface will NOT work --- module/interaction/InteractionManager.py | 33 ++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'module/interaction/InteractionManager.py') diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py index 5ebcd1fcd..c547e1c97 100644 --- a/module/interaction/InteractionManager.py +++ b/module/interaction/InteractionManager.py @@ -15,10 +15,13 @@ @author: RaNaN """ -from utils import lock from traceback import print_exc from threading import Lock +from module.utils import lock, bits_set + +from InteractionTask import InteractionTask + class InteractionManager: """ Class that gives ability to interact with the user. @@ -30,13 +33,25 @@ class InteractionManager: self.core = core self.tasks = [] #task store, for outgoing tasks only + self.last_clients = {} + self.ids = 0 #only for internal purpose + def work(self): - """Mainloop that gets the work done""" + pass + + @lock + def newNotification(self): + pass + + @lock + def newQueryTask(self): + pass - def newTask(self, img, format, file, result_type): - task = CaptchaTask(self.ids, img, format, file, result_type) + @lock + def newCaptchaTask(self, img, format, file, result_type): + task = InteractionTask(self.ids, img, format, file, result_type) self.ids += 1 return task @@ -48,14 +63,12 @@ class InteractionManager: @lock def getTask(self): for task in self.tasks: - if task.status in ("waiting", "shared-user"): - return task + return task @lock - def getTaskByID(self, tid): + def getTaskByID(self, iid): for task in self.tasks: - if task.id == str(tid): #task ids are strings - self.lock.release() + if task.id == iid: return task def handleCaptcha(self, task): @@ -64,7 +77,7 @@ class InteractionManager: if cli: #client connected -> should solve the captcha task.setWaiting(50) #wait 50 sec for response - for plugin in self.core.hookManager.activePlugins(): + for plugin in self.core.addonManager.activePlugins(): try: plugin.newCaptchaTask(task) except: -- cgit v1.2.3 From 50d4df8b4d48b855bd18e9922355b7f3f2b4da4e Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 20 Mar 2012 14:57:45 +0100 Subject: captcha decrypting for all plugin types, new interaction manager --- module/interaction/InteractionManager.py | 127 +++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 33 deletions(-) (limited to 'module/interaction/InteractionManager.py') diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py index c547e1c97..0c125bdd4 100644 --- a/module/interaction/InteractionManager.py +++ b/module/interaction/InteractionManager.py @@ -15,10 +15,13 @@ @author: RaNaN """ -from traceback import print_exc from threading import Lock +from time import time -from module.utils import lock, bits_set +from new_collections import OrderedDict + +from module.utils import lock, bits_set, to_list +from module.Api import Input, Output from InteractionTask import InteractionTask @@ -28,69 +31,127 @@ class InteractionManager: Arbitary task with predefined output and input type can be set off. Asyncronous callbacks and default values keeps the ability to fallback if no user is present. """ + + # number of seconds a client is classified as active + CLIENT_THRESHOLD = 60 + def __init__(self, core): self.lock = Lock() self.core = core - self.tasks = [] #task store, for outgoing tasks only + self.tasks = OrderedDict() #task store, for outgoing tasks only + self.notifications = [] #list of notifications - self.last_clients = {} + self.last_clients = { + Output.Notification : 0, + Output.Captcha : 0, + Output.Query : 0, + } self.ids = 0 #only for internal purpose + def isClientConnected(self, mode=Output.All): + if mode == Output.All: + return max(self.last_clients.values()) + self.CLIENT_THRESHOLD <= time() + else: + self.last_clients.get(mode, 0) + self.CLIENT_THRESHOLD <= time() + + def updateClient(self, mode): + t = time() + for output in self.last_clients: + if bits_set(output, mode): + self.last_clients[output] = t + + @lock def work(self): - pass + # old notifications will be removed + for n in [x for x in self.notifications if x.timedOut()]: + self.notifications.remove(n) + + # store at most 100 notifications + del self.notifications[50:] + @lock - def newNotification(self): - pass + def createNotification(self, title, content, desc="", plugin=""): + """ Creates and queues a new Notification + + :param title: short title + :param content: text content + :param desc: short form of the notification + :param plugin: plugin name + :return: :class:`InteractionTask` + """ + task = InteractionTask(self.ids, Input.Text, [content], Output.Notification, "", title, desc, plugin) + self.ids += 1 + self.notifications.insert(0, task) + self.handleTask(task) + return task @lock - def newQueryTask(self): - pass + def newQueryTask(self, input, data, desc, default="", plugin=""): + task = InteractionTask(self.ids, input, to_list(data), Output.Query, default, _("Query"), desc, plugin) + self.ids += 1 + return task @lock - def newCaptchaTask(self, img, format, file, result_type): - task = InteractionTask(self.ids, img, format, file, result_type) + def newCaptchaTask(self, img, format, filename, plugin="", input=Input.Text): + #todo: title desc plugin + task = InteractionTask(self.ids, input, [img, format, filename],Output.Captcha, + "", _("Captcha request"), _("Please solve the captcha."), plugin) self.ids += 1 return task @lock def removeTask(self, task): - if task in self.tasks: - self.tasks.remove(task) + if task.iid in self.tasks: + del self.tasks[task.iid] @lock - def getTask(self): - for task in self.tasks: - return task + def getTask(self, mode=Output.All): + self.updateClient(mode) + + for task in self.tasks.itervalues(): + if mode == Output.All or bits_set(task.output, mode): + return task + + @lock + def getNotifications(self): + """retrieves notifications, old ones are only deleted after a while\ + client has to make sure itself to dont display it twice""" + for n in self.notifications: + n.setWaiting(self.CLIENT_THRESHOLD * 5, True) + #store notification for shorter period, lock the timeout + + return self.notifications + + def isTaskWaiting(self, mode=Output.All): + return self.getTask(mode) is not None @lock def getTaskByID(self, iid): - for task in self.tasks: - if task.id == iid: - return task + if iid in self.tasks: + task = self.tasks[iid] + del self.tasks[iid] + return task - def handleCaptcha(self, task): - cli = self.core.isClientConnected() + def handleTask(self, task): + cli = self.isClientConnected(task.output) - if cli: #client connected -> should solve the captcha - task.setWaiting(50) #wait 50 sec for response + if cli: #client connected -> should handle the task + task.setWaiting(self.CLIENT_THRESHOLD) # wait for response + + if task.output == Output.Notification: + task.setWaiting(60 * 60 * 30) # notifications are valid for 30h for plugin in self.core.addonManager.activePlugins(): try: - plugin.newCaptchaTask(task) + plugin.newInteractionTask(task) except: - if self.core.debug: - print_exc() - - if task.handler or cli: #the captcha was handled - self.tasks.append(task) - return True - - task.error = _("No Client connected for captcha decrypting") + self.core.print_exc() - return False + if task.output != Output.Notification: + self.tasks[task.iid] = task if __name__ == "__main__": -- cgit v1.2.3 From b40b32ee05f611323a7827fad2a25fa0a28dcb24 Mon Sep 17 00:00:00 2001 From: X3n0m0rph59 Date: Sun, 22 Apr 2012 19:56:17 +0200 Subject: a huge pile of spelling fixes --- module/interaction/InteractionManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/interaction/InteractionManager.py') diff --git a/module/interaction/InteractionManager.py b/module/interaction/InteractionManager.py index 0c125bdd4..1d26b1665 100644 --- a/module/interaction/InteractionManager.py +++ b/module/interaction/InteractionManager.py @@ -28,8 +28,8 @@ from InteractionTask import InteractionTask class InteractionManager: """ Class that gives ability to interact with the user. - Arbitary task with predefined output and input type can be set off. - Asyncronous callbacks and default values keeps the ability to fallback if no user is present. + Arbitrary tasks with predefined output and input types can be set off. + Asynchronous callbacks and default values keep the ability to fallback if no user is present. """ # number of seconds a client is classified as active -- cgit v1.2.3