def take_screenshot(self): # check screenshot preferences recording = preferences.getValueForPreference('recording') screenshots_active = preferences.getValueForPreference('screenshots') screenshot_time_min = preferences.getValueForPreference('imageTimeMin') / 1000.0 # take a screenshot if preferences allow if (screenshots_active and recording and (cfg.NOW() - self.last_screenshot) > screenshot_time_min) : try: # get filename filename = datetime.datetime.now().strftime("%y%m%d-%H%M%S%f") y = filename[0:2] m = filename[2:4] d = filename[4:6] h = filename[7:9] folder = os.path.join(cfg.CURRENT_DIR,"screenshots",y,m,d,h) if not os.path.exists(folder): os.makedirs(folder) path = os.path.join(folder,""+filename+".jpg") # take screenshot self.sniffer.screenshot(path) self.last_screenshot = cfg.NOW() except: print "There was an error with saving a screenshot"
def do_Tail(self): if self.jdtask.RunTail_isOver: self.jdtask.CurRunMode = JdComments_task_mode.RunFirst return None jdtask = self.jdtask if not jdtask.RunTail_NextPage: jdtask.RunTail_NextPage = 1 if not jdtask.RunTail or jdtask.RunTail == {} or jdtask.RunTail_createtime == None: jdtask.RunTail_createtime = config.NOW() jdtask.RunTail_StartPage = jdtask.RunTail_NextPage jdtask.RunTail_EndPage = min(100 + jdtask.RunTail_NextPage, jdtask.maxPage) pages = [] for page in range(jdtask.RunTail_StartPage, jdtask.RunTail_EndPage): pages.append(page) JdCommentTaskExec.save_task(jdtask.task) return self.make_crawl_task(pages) else: # 检查任务是否超时,如果超时,重置任务 if (JM_Time(config.NOW()) - jdtask.RunTail_createtime) >= 3600 * 2: jdtask.initRunTail() jdtask.CurRunMode = JdComments_task_mode.RunFirst return None
def __init__(self): # variables for managing loops self.last_screenshot = cfg.NOW() self.screenshotTimer = None self.last_parse = cfg.NOW() self.parseTimer = None
def firefoxCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastFirefoxTime == None: self.lastFirefoxTime = int( utils_cocoa.unix_to_firefox(cfg.NOW())) return profiles = [] profFile = open( os.path.expanduser( '~/Library/Application Support/Firefox/profiles.ini')) for line in profFile: if line[:5] == 'Path=': profiles.append(line[5:-1]) for profile in profiles: conn = sqlite3.connect( os.path.expanduser( '~/Library/Application Support/Firefox/' + profile + '/places.sqlite')) c = conn.cursor() c.execute( "SELECT visit_date, title, url FROM moz_historyvisits LEFT JOIN moz_places ON moz_historyvisits.place_id == moz_places.id where visit_date > " + str(self.lastFirefoxTime)) # offset by 10. Add an extra 0.1 sec for roundoff issues ffTimeOffset = int(utils_cocoa.unix_to_firefox( cfg.NOW())) - 9.9 if self.lastFirefoxTime < ffTimeOffset: self.lastFirefoxTime = ffTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastFirefoxTime < time: self.lastFirefoxTime = time text = '{"time": ' + str(utils_cocoa.firefox_to_unix( time)) + ', "browser": "Firefox", "url": "' + str( url) + '", "title": "' + str( title) + '", "event": ' + '"Open"' + ' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastFirefoxTime = None
def move_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: if event.type() == NSMouseMoved: loc = NSEvent.mouseLocation() # get all the image size information scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y x = int(loc.x) - xmin y = int(loc.y) - ymin # write JSON object to movelog file text = '{"time": ' + str(cfg.NOW()) + ' , "location": [' + str( x) + ',' + str(y) + ']}' utils_cocoa.write_to_file(text, cfg.MOVELOG)
def do_tail_parse(self, parses): jdtask = self.jdtask ''' 抓RunTail.NextPage,看本页最晚时间(StartTime) 如果比EndTime晚(大),说明有重复数据,继续向前抓就好了 如果比EndTime早(小),说明中间有空档,进入RunTailRev模式 如果本次执行已向前抓了100页(可并发),或遇到终点,模式返回RunFirst 如果遇到某页不足10个,说明已全部抓光,模式设置为结束,模式返回RunFirst ''' # 如果是最小的页,并且创建时间比较久,检查是不是有空档,修改EndTime minnotokpage = jdtask.RunTail_EndPage + 1 isOverPage = jdtask.RunTail_EndPage + 1 EndTime = None need2rev = False lastEndTime = jdtask.EndTime for parse in parses: if parse.isAntiSpider: minnotokpage = min(minnotokpage, parse.page) continue if parse.comments_count < 10: print(type(parse.page), page, type(isOverPage), isOverPage) isOverPage = min(parse.page, isOverPage) if parse.comments_count > 0: JdCommentTaskExec.save_comments(parse.comments, jdtask.task) if parse.page == jdtask.RunTail_StartPage: if ((JM_Time(config.NOW()) - jdtask.RunTail_createtime) > 3600): if jdtask.RunTail_StartPage > 1: if parse.StartTime < jdtask.EndTime: need2rev = True if minnotokpage > jdtask.RunTail_StartPage and ( minnotokpage != jdtask.RunTail_EndPage + 1): jdtask.EndTime = parses[minnotokpage - 1] jdtask.RunTail_NextPage = minnotokpage jdtask.EndPage = minnotokpage - 1 if isOverPage >= jdtask.RunTail_StartPage and ( isOverPage != jdtask.RunTail_EndPage + 1): jdtask.maxPage = isOverPage jdtask.RunTail_isOver = True if need2rev: jdtask.CurRunMode = JdComments_task_mode.RunTailRev jdtask.RunTailRev_EndTime = lastEndTime jdtask.RunTailRev_EndPage = jdtask.RunTail_StartPage jdtask.RunTailRev_CurEndTime = None jdtask.RunTailRev_PrevPage = jdtask.RunTailRev_EndPage - 1 else: jdtask.CurRunMode = JdComments_task_mode.RunFirst jdtask.initRunTail() JdCommentTaskExec.save_task(self.task)
def run(self): # hook up the sniffer self.sniffer = sniffer.Sniffer(self) # create object to manage database storage self.storage = Storage(self, cfg.NOW()) self.sniffer.run()
def chromeCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: # get event info t = cfg.NOW() notification_title = str( kwargs['notification'] )[2:] # remove 'AX' from front of event names before we save that info if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) return Chrome = SBApplication.applicationWithBundleIdentifier_( "com.google.Chrome") windows = Chrome.windows() oldTabList = self.tabList self.tabList = {} #TODO check if we get all tabs from multiple windows. # Is tab.id uniqe across all windows, or duplicated (i.e. window 1 # has tabs 1, 2, 3 and window 2 has tabs 1, 2, 3, 4) for window in windows: tabs = window.tabs() for tab in tabs: self.tabList[tab.id()] = { 'title': str(tab.title()), 'id': str(tab.id()), 'url': str(tab.URL()), 'host': urlparse.urlparse(str(tab.URL())).hostname } closedTabs = set(oldTabList.keys()) - set(self.tabList.keys()) openedTabs = set(self.tabList.keys()) - set(oldTabList.keys()) # take screenshot eventScreenshots = preferences.getValueForPreference( 'eventScreenshots') if eventScreenshots: self.AppRecorder.sniffer.activity_tracker.take_screenshot() # get list of urls from the database db_urls = session.query(URL).all() urls = [u.url for u in db_urls] # check if any recently opened tabs are not yet in the database for t in openedTabs: if tabList[t]['url'] not in urls: url_to_add = URL(t, app_name) session.add(url_to_add) #TODO need to find way to commit! activity_tracker.storage.sqlcommit() # update our local url list db_urls = session.query(URL).all() urls = [u.url for u in db_urls]
def recordText_(self, sender): t = cfg.NOW() message = self.experienceText.stringValue() e = Experience(t, message) self.sniffer.activity_tracker.storage.session.add(e) # may not need to commit here, but could wait till next round of parsing self.sniffer.activity_tracker.storage.sqlcommit() print 'Received experience message of: ' + message self.expController.close()
def run_screenshot_loop(self): # take a screenshot if computer is idle and appropriate amount of time has passed screenshot_time_max = preferences.getValueForPreference('imageTimeMax') periodic = preferences.getValueForPreference('periodicScreenshots') time_since_last_screenshot = cfg.NOW() - self.last_screenshot if (time_since_last_screenshot > screenshot_time_max): if periodic: self.take_screenshot() time_since_last_screenshot = 0.0 sleep_time = screenshot_time_max - time_since_last_screenshot + 0.001 # add a milisecond for good measure self.screenshotTimer = threading.Timer(sleep_time,self.run_screenshot_loop) self.screenshotTimer.start()
def safariCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastSafariTime == None: self.lastSafariTime = int(utils_cocoa.unix_to_safari( cfg.NOW())) return conn = sqlite3.connect( os.path.expanduser('~/Library/Safari/History.db')) c = conn.cursor() c.execute( "SELECT visit_time, title, url FROM history_visits LEFT JOIN history_items ON history_visits.history_item == history_items.id where visit_time > " + str(self.lastSafariTime)) # looks like safari writes every ~10 seconds so offset by 10. Add an extra 0.1 sec for roundoff issues safariTimeOffset = int(utils_cocoa.unix_to_safari(cfg.NOW())) - 9.9 if self.lastSafariTime < safariTimeOffset: self.lastSafariTime = safariTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastSafariTime < time: self.lastSafariTime = time text = '{"time": ' + str(utils_cocoa.safari_to_unix( time)) + ', "browser": "Safari", "url": "' + str( url) + '", "title": "' + str( title) + '", "event": ' + '"Open"' + ' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastSafariTime = None
def get_clipboard_contents(self): # only store data if we have new items recording = preferences.getValueForPreference('recording') if recording: clip = NSPasteboard.generalPasteboard() count = clip.changeCount() if self.last_count == None: self.last_count = count elif count != self.last_count: self.last_count = count text = "" url = "" image = None path = "" items = clip.pasteboardItems() for i in items: t = i.types() # get the textual data if 'public.utf8-plain-text' in t: text = i.stringForType_('public.utf8-plain-text') if 'public.url' in t: url = i.stringForType_('public.url') if 'public.url-name' in t: url = i.stringForType_('public.url-name') if 'public.file-url' in t: url = i.stringForType_('public.file-url') # get image data if 'public.tiff' in t: image = i.dataForType_('public.tiff') if 'public.png' in t: image = i.dataForType_('public.png') if 'public.jpeg' in t: image = i.dataForType_('public.jpeg') # save image file if we have one if image != None: folder = os.path.join(cfg.CURRENT_DIR, "clipboard") filename = datetime.datetime.now().strftime( "%y%m%d-%H%M%S%f") path = os.path.join(folder, "" + filename + ".jpg") image.writeToFile_atomically_(path, False) # clean up text and url text = json.dumps(text) url = json.dumps(url) # save to a clipboard file tex = '{"time": ' + str( cfg.NOW() ) + ' , "text": ' + text + ' , "url": ' + url + ' , "image": "' + path + '"}' utils_cocoa.write_to_file(tex, cfg.CLIPLOG)
def scroll_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: if event.type() == NSScrollWheel: # write JSON object to scrolllog file text = '{"time": ' + str(cfg.NOW()) + ' , "distance": [' + str( event.deltaX()) + ',' + str( event.deltaY()) + '], "window_number": ' + str( event.windowNumber()) + '}' utils_cocoa.write_to_file(text, cfg.SCROLLLOG)
def applicationWillTerminate_(self, application): t = cfg.NOW() # close all open app and window listeners sc.ar.stop_app_observers() # save recorder turned off event text = '{"time": '+ str(t) + ' , "type": "Exit"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) #TODO tell application to parse logs one last time before quiting sc.activity_tracker.storage.parseToSqlite() sc.activity_tracker.storage.sqlcommit() print "Exiting Traces..." sc.cancel()
def applicationDidFinishLaunching_(self, notification): print "Traces finished launching..." # save recorder turned on event t = cfg.NOW() text = '{"time": '+ str(t) + ' , "type": "Start"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) # set inital values for the preferences preferences.setInitialPreferenceValues() # create status-bar menu self.createStatusMenu() # start loops to take screenshots and parse log files self.activity_tracker.checkLoops()
def sqlcommit(self): self.last_commit = cfg.NOW() for _ in xrange(1000): try: self.session.commit() break except sqlalchemy.exc.OperationalError: # pause recording if (preferences.getValueForPreference("recording")): self.activity_tracker.sniffer.delegate.toggleLogging_(self) self.session.rollback() # show modal alert print "Database operational error. Your storage device may be full. Turning off Selfspy recording." utils_cocoa.show_alert( "Database operational error. Your storage device may be full. Turning off Selfspy recording." ) break except: raise print "Rollback database" self.session.rollback()
def toggleLogging_(self, notification): print "Toggle Recording" t = cfg.NOW() recording = preferences.getValueForPreference('recording') recording = not recording NSUserDefaultsController.sharedUserDefaultsController().defaults().setBool_forKey_(recording,'recording') self.activity_tracker.checkLoops() #change text and enabled status of screenshot menu item if recording: self.loggingMenuItem.setTitle_("Pause Recording") sc.ar.unpause_app_observers() text = '{"time": '+ str(t) + ' , "type": "Unpause"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) else: self.loggingMenuItem.setTitle_("Start Recording") sc.ar.pause_app_observers() text = '{"time": '+ str(t) + ' , "type": "Pause"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) self.changeIcon()
def toggleAudioRecording_(self, sender): if self.recordingAudio: self.recordingAudio = False print "Stop audio message" # get the right name for our audio file dt = datetime.now().strftime("%y%m%d-%H%M%S%f") audioName = str(os.path.join(cfg.CURRENT_DIR, "audio/")) + dt + '.m4a' self.audio_file = audioName audioName = string.replace(audioName, "/", ":") audioName = audioName[1:] # start the audio recording s = NSAppleScript.alloc().initWithSource_("set filePath to \"" + audioName + "\" \n set placetosaveFile to a reference to file filePath \n tell application \"QuickTime Player\" \n set mydocument to document 1 \n tell document 1 \n stop \n end tell \n set newRecordingDoc to first document whose name = \"untitled\" \n export newRecordingDoc in placetosaveFile using settings preset \"Audio Only\" \n close newRecordingDoc without saving \n quit \n end tell") s.executeAndReturnError_(None) # log the experience in our table t = cfg.NOW() e = Experience(t, dt + '.m4a') self.sniffer.activity_tracker.storage.session.add(e) # may not need to commit here, but could wait till next round of parsing self.sniffer.activity_tracker.storage.sqlcommit() # reset controls self.expController.recordButton.setTitle_("Record") self.expController.recordButton.setEnabled_(False) self.expController.playAudioButton.setHidden_(False) self.expController.deleteAudioButton.setHidden_(False) self.expController.progressBar.setHidden_(False) else: self.recordingAudio = True print "Start audio message" s = NSAppleScript.alloc().initWithSource_("tell application \"QuickTime Player\" \n set new_recording to (new audio recording) \n tell new_recording \n start \n end tell \n tell application \"System Events\" \n set visible of process \"QuickTime Player\" to false \n repeat until visible of process \"QuickTime Player\" is false \n end repeat \n end tell \n end tell") s.executeAndReturnError_(None) self.expController.recordButton.setTitle_("Stop Recording")
def click_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: # check if the clipboard has updated self.sniffer.clr.get_clipboard_contents() # get data ready to write loc = NSEvent.mouseLocation() scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y x = int(loc.x) - xmin y = int(loc.y) - ymin #get click type click_type = "Unknown" if event.type() == NSLeftMouseDown: click_type = "Left" elif event.type() == NSRightMouseDown: click_type = "Right" # write JSON object to clicklog file text = '{"time": ' + str(cfg.NOW( )) + ' , "button": "' + click_type + '", "location": [' + str( x) + ',' + str(y) + ']}' utils_cocoa.write_to_file(text, cfg.CLICKLOG)
def do_Parse(self, html, page): parse = JdCommentsParse(html, page) # print('aaaa',parse.comments) jdtask = self.jdtask if parse.comments_count > 0: JdCommentTaskExec.save_comments(parse.comments, jdtask.task) if parse.page == 0: # 修正间隔历史 jdtask.addStartTimeRecord(parse.comments) jdtask.First_Page_Scan_last_scan_time = config.NOW() jdtask.productCommentSummary = parse.productCommentSummary jdtask.hotCommentTagStatistics = parse.hotCommentTagStatistics jdtask.maxPage = parse.maxPage if jdtask.CurRunMode == JdComments_task_mode.RunInit: self.do_init_parse(parse) return if jdtask.CurRunMode == JdComments_task_mode.RunFirst: self.do_first_parse(parse) return if jdtask.CurRunMode == JdComments_task_mode.RunHead: self.do_head_parse(parse) return if jdtask.CurRunMode == JdComments_task_mode.RunTail: self.do_tail_parse([parse]) return if jdtask.CurRunMode == JdComments_task_mode.RunTailRev: self.do_tailrev_parse(parse) return
def key_handler(self, event): # neither of these is returning a valid value, just None and 0 # print event.window() # print event.windowNumber() recording = preferences.getValueForPreference('recording') record_keystrokes = preferences.getValueForPreference('keystrokes') if recording and record_keystrokes: event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if event.type() == NSKeyDown: # get list of applications that show up in the dock # workspace = NSWorkspace.sharedWorkspace() # activeApps = workspace.runningApplications() # app_name = "" # window_name = "" # for app in activeApps: # if app.isActive(): # app_name = app.localizedName() # # print type(app) # # window_name = app.windows() # # print app_name # # print window_name # # options = kCGWindowListOptionAll + kCGWindowListExcludeDesktopElements # windows = CGWindowListCopyWindowInfo(options, kCGNullWindowID) # print windows[0].keys() # for window in windows: # activeApp = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']) # not working because I'm not calling it on the app itself # print NSApp.keyWindow() # print utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keys()) # keyWindow = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keyWindow()) # get the modifier keys that were depressed when this key was pressed flags = event.modifierFlags() modifiers = [] # OS X api doesn't care it if is left or right if flags & NSControlKeyMask: modifiers.append('Ctrl') if flags & NSAlternateKeyMask: modifiers.append('Alt') if flags & NSCommandKeyMask: modifiers.append('Cmd') if flags & (NSShiftKeyMask | NSAlphaShiftKeyMask): modifiers.append('Shift') # TODO determine why we have to use keycodes here for enter and # backspace but can rely on the charachter list for the others # get the charachter of the pressed key character = event.charactersIgnoringModifiers() if event.keyCode() is 51: character = "Backspace" elif event.keyCode() is 8 and modifiers == ["Cmd"]: # trigger clipboard check self.sniffer.clr.get_clipboard_contents() elif event.keyCode() is 36: character = "Enter" elif event.keyCode() is 39 and modifiers == ["Shift"]: character = "\\\"" elif event.keyCode() is 42 and modifiers != ["Shift"]: character = "\\\\" elif event.keyCode() is 46 and modifiers == ["Cmd", "Shift"]: self.sniffer.delegate.showExperience_("Fake Notification") string = KEYCODES.get(character, character) if string in SKIP_MODIFIERS: return # write JSON object to keylog file text = '{"time": ' + str(cfg.NOW( )) + ' , "key": "' + string + '" , "modifiers": ' + str( modifiers) + '}' utils_cocoa.write_to_file(text, cfg.KEYLOG)
def clearData(self): minutes_to_delete = self.activity_tracker.sniffer.delegate.prefContr.clearDataPopup.selectedItem( ).tag() text = self.activity_tracker.sniffer.delegate.prefContr.clearDataPopup.selectedItem( ).title() if minutes_to_delete == -1: delete_from_time = datetime.datetime.min delete_from_time_unix = 0 else: delta = datetime.timedelta(minutes=minutes_to_delete) now = datetime.datetime.now() delete_from_time = now - delta now_unix = cfg.NOW() delete_from_time_unix = now_unix - 60 * minutes_to_delete # delete screenshots screenshot_directory = os.path.expanduser( os.path.join(cfg.CURRENT_DIR, "screenshots")) screenshot_files = os.listdir(screenshot_directory) for f in screenshot_files: if f[0:19] > delete_from_time.strftime("%y%m%d-%H%M%S%f"): os.remove(os.path.join(screenshot_directory, f)) # delete clipboard images clipboard_directory = os.path.expanduser( os.path.join(cfg.CURRENT_DIR, "clipboard")) clipboard_files = os.listdir(clipboard_directory) for f in clipboard_files: if f[0:19] > delete_from_time.strftime("%y%m%d-%H%M%S%f"): os.remove(os.path.join(clipboard_directory, f)) # delete audio files audio_directory = os.path.expanduser( os.path.join(cfg.CURRENT_DIR, "audio")) audio_files = os.listdir(audio_directory) for f in audio_files: if f[0:19] > delete_from_time.strftime("%y%m%d-%H%M%S%f"): os.remove(os.path.join(audio_directory, f)) # delete log files, since they only have the last 5 seconds of data, # we don't need to check if the data is later than the delete_from_time logs = os.listdir(cfg.CURRENT_DIR) for l in logs: if l[-4:] == ".log": os.remove(os.path.join(cfg.CURRENT_DIR, l)) # delete data from all database tables # TODO may be a cleaner way to iterate through this given the table names self.session.query(App).filter( App.time > delete_from_time_unix).delete() self.session.query(AppEvent).filter( AppEvent.time > delete_from_time_unix).delete() self.session.query(Arrangement).filter( Arrangement.time > delete_from_time_unix).delete() self.session.query(Click).filter( Click.time > delete_from_time_unix).delete() self.session.query(Clipboard).filter( Clipboard.time > delete_from_time_unix).delete() self.session.query(Experience).filter( Experience.time > delete_from_time_unix).delete() self.session.query(Geometry).filter( Geometry.time > delete_from_time_unix).delete() self.session.query(Keys).filter( Keys.time > delete_from_time_unix).delete() self.session.query(Move).filter( Move.time > delete_from_time_unix).delete() self.session.query(RecordingEvent).filter( RecordingEvent.time > delete_from_time_unix).delete() self.session.query(Scroll).filter( Scroll.time > delete_from_time_unix).delete() self.session.query(Window).filter( Window.time > delete_from_time_unix).delete() self.session.query(WindowEvent).filter( WindowEvent.time > delete_from_time_unix).delete() print "Deleted last " + text + " of your history"
def parseLogs(self): self.storage.parseLogs() self.last_parse = cfg.NOW() self.parseTimer = threading.Timer(cfg.PARSEDELAY, self.parseLogs) self.parseTimer.start()