diff --git a/main.py b/main.py index eac0b5d..da9f31e 100644 --- a/main.py +++ b/main.py @@ -3,8 +3,10 @@ import time from PythonQt.QtCore import QFile, QSettings from PythonQt.QtGui import QDesktopServices, QMessageBox from PythonQt.QtUiTools import QUiLoader +from multiprocessing import Pool,Process from seafapi import * +from processors import DefaultProcessor, EncryptedProcessor ############################### ## This is a temporary fix, should be removed when a newer python version is used ## import logging @@ -12,180 +14,193 @@ logging.captureWarnings(True) ############################### class SeafileUploader(): - def __init__(self): - self.uil = QUiLoader() - self.loadSettings() - self.seaf_lib = None - self.libs = None - - def showSettingsUI(self, parentWidget): - self.parentWidget = parentWidget - self.settingsDialog = self.uil.load(QFile(workingDir + "/settings.ui"), parentWidget) - self.settingsDialog.group_account.widget_loggedIn.loginButton.connect("clicked()", self.startAuthenticationProcess) - #self.settingsDialog.group_name.input_name.connect("textChanged(QString)", self.nameFormatEdited) - self.settingsDialog.group_location.widget_location.pathEdit.connect("textChanged(QString)", self.locationUpdate) - self.settingsDialog.group_location.widget_location.libraryEditDrop.connect("currentIndexChanged(QString)", self.locationUpdate) - self.settingsDialog.connect("accepted()", self.saveSettings) - - self.loadSettings() - self.updateUi() - self.settingsDialog.open() + def __init__(self): + self.uil = QUiLoader() + self.loadSettings() + self.seaf_lib = None + self.libs = None + self.pool = Pool(2) + self.processor = None + + def showSettingsUI(self, parentWidget): + self.parentWidget = parentWidget + self.settingsDialog = self.uil.load(QFile(workingDir + "/settings.ui"), parentWidget) + self.settingsDialog.group_account.widget_loggedIn.loginButton.connect("clicked()", self.startAuthenticationProcess) + #self.settingsDialog.group_name.input_name.connect("textChanged(QString)", self.nameFormatEdited) + self.settingsDialog.group_location.widget_location.pathEdit.connect("textChanged(QString)", self.locationUpdate) + self.settingsDialog.group_location.widget_location.libraryEditDrop.connect("currentIndexChanged(QString)", self.locationUpdate) + self.settingsDialog.connect("accepted()", self.saveSettings) + + self.loadSettings() + self.updateUi() + self.settingsDialog.open() - def populateLibrarySelector(self): - drop = self.settingsDialog.group_location.widget_location.libraryEditDrop - drop.clear() - drop.setEnabled(False) - if self.isConfigured(): - self.libs = (self.seaf_client or self.seaf_lib.client).libraries() - i=0 - select = 0 - for lib in self.libs: - print "%s %s <-> %s%s" % (lib.name,lib.id,self.seaf_lib.name,self.seaf_lib.id) - if self.seaf_lib is not None and lib.id == self.seaf_lib.id: - select = i - print "set %s" % lib.name - drop.addItem(lib.name) - i=i+1 - drop.setCurrentIndex(select) - drop.setEnabled(True) + def populateLibrarySelector(self): + drop = self.settingsDialog.group_location.widget_location.libraryEditDrop + drop.clear() + drop.setEnabled(False) + if self.isConfigured(): + self.libs = (self.seaf_client or self.seaf_lib.client).libraries() + i=0 + select = 0 + for lib in self.libs: + if self.seaf_lib is not None and lib.id == self.seaf_lib.id: + select = i + print "set %s" % lib.name + drop.addItem(lib.name) + i=i+1 + drop.setCurrentIndex(select) + drop.setEnabled(True) - def updateUi(self): - self.settingsDialog.group_account.widget_loggedIn.usernameEdit.setText(self.access_token.username if not (self.access_token is None) else "") - self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.setText(self.seaf_url or "https://seaf.shimun.net") - self.settingsDialog.group_account.widget_loggedIn.loginButton.setText("Logout" if self.access_token is not None else "Login") - # - if self.access_token is None and len(self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) > 0: - self.settingsDialog.group_account.widget_loggedIn.passwordEdit.setText("X" * 8) - for elm in [self.settingsDialog.group_account.widget_loggedIn.usernameEdit, self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit, self.settingsDialog.group_account.widget_loggedIn.passwordEdit]: - elm.setEnabled(self.access_token is None) - self.settingsDialog.group_location.setEnabled(self.access_token is not None) - self.settingsDialog.group_location.widget_location.pathEdit.setText(self.lib_path or "/") - self.settingsDialog.linkCopyCheck.setChecked(self.copyLink) - self.populateLibrarySelector() - self.settingsDialog.adjustSize() + def updateUi(self): + self.settingsDialog.group_account.widget_loggedIn.usernameEdit.setText(self.access_token.username if not (self.access_token is None) else "") + self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.setText(self.seaf_url or "https://seaf.shimun.net") + self.settingsDialog.group_account.widget_loggedIn.loginButton.setText("Logout" if self.access_token is not None else "Login") + # + if self.access_token is None and len(self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) > 0: + self.settingsDialog.group_account.widget_loggedIn.passwordEdit.setText("X" * 8) + for elm in [self.settingsDialog.group_account.widget_loggedIn.usernameEdit, self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit, self.settingsDialog.group_account.widget_loggedIn.passwordEdit]: + elm.setEnabled(self.access_token is None) + self.settingsDialog.group_location.setEnabled(self.access_token is not None) + self.settingsDialog.group_location.widget_location.pathEdit.setText(self.lib_path or "/") + self.settingsDialog.linkCopyCheck.setChecked(self.copyLink) + self.populateLibrarySelector() + self.settingsDialog.adjustSize() - def loadSettings(self): - settings = QSettings() - settings.beginGroup("uploaders") - settings.beginGroup("seafile") - self.seaf_url = settings.value("seafile-url", "") - (self.lib_id,self.lib_name) = str(settings.value("library", "/")).split("/") - self.lib_path = settings.value("library-path", "") - self.copyLink = settings.value("copy-link", "true") in ['true', True] - if settings.value("auth-token", False) and settings.value("auth-username", False): - self.access_token = SeafileToken(settings.value("auth-username", False),settings.value("auth-token", False)) - else: - self.access_token = None - self.nameFormat = settings.value("name-format", "Screenshot at %H:%M:%S") - settings.endGroup() - settings.endGroup() - if self.isConfigured(): - self.seaf_client = SeafileClient(self.seaf_url,self.access_token.username,token=self.access_token) - for lib in self.seaf_client.libraries(): - if lib.id == self.lib_id: - self.seaf_lib = lib + def loadSettings(self): + settings = QSettings() + settings.beginGroup("uploaders") + settings.beginGroup("seafile") + self.seaf_url = settings.value("seafile-url", "") + (self.lib_id,self.lib_name) = str(settings.value("library", "/")).split("/") + self.lib_path = settings.value("library-path", "") + self.copyLink = settings.value("copy-link", "true") in ['true', True] + if settings.value("auth-token", False) and settings.value("auth-username", False): + self.access_token = SeafileToken(settings.value("auth-username", False),settings.value("auth-token", False)) + else: + self.access_token = None + self.nameFormat = settings.value("name-format", "Screenshot %Y-%m-%d %H_%M_%S") + self.upload_scheme = settings.value("upload-scheme", "regular") + settings.endGroup() + settings.endGroup() + if self.isConfigured(): + self.seaf_client = SeafileClient(self.seaf_url,self.access_token.username,token=self.access_token) + for lib in self.seaf_client.libraries(): + if lib.id == self.lib_id: + self.seaf_lib = lib - def saveSettings(self): - settings = QSettings() - settings.beginGroup("uploaders") - settings.beginGroup("seafile") - self.copyLink = self.settingsDialog.linkCopyCheck.checked - settings.setValue("copy-link", self.copyLink) - if self.access_token is not None: - settings.setValue("auth-username", self.access_token.username ) - settings.setValue("auth-token", self.access_token.token) - settings.setValue("seafile-url", self.seaf_url) - if self.seaf_lib is not None: - settings.setValue("library", "%s/%s" % (self.seaf_lib.id,self.seaf_lib.name)) - settings.setValue("library-path", self.lib_path) - #settings.setValue("name-format", self.settingsDialog.group_name.input_name.text) - print self.seaf_lib, self.lib_path - settings.endGroup() - settings.endGroup() - - def isConfigured(self): - return self.access_token and self.seaf_url + self.processor = EncryptedProcessor(self.seaf_lib,self.lib_path)#DefaultProcessor(self.seaf_lib,self.lib_path) - def getFilename(self): - self.loadSettings() - return ScreenCloud.formatFilename(self.nameFormat) - - def upload(self, screenshot, name): - self.loadSettings() - #Make sure we have a up to date token - if not self.seaf_lib: - ScreenCloud.setError("Not configured properly") - return False - #Save to a temporary file - timestamp = time.time() - try: - tmpFilename = QDesktopServices.storageLocation(QDesktopServices.TempLocation) + "/" + ScreenCloud.formatFilename(str(timestamp)) - except AttributeError: - from PythonQt.QtCore import QStandardPaths #fix for Qt5 - tmpFilename = QStandardPaths.writableLocation(QStandardPaths.TempLocation) + "/" + ScreenCloud.formatFilename(str(timestamp)) - screenshot.save(QFile(tmpFilename), ScreenCloud.getScreenshotFormat()) - #Upload! - link=None - try: - file = self.seaf_lib.upload(tmpFilename,self.getFilename(),self.lib_path) - link = file.share() - except Exception as e: - ScreenCloud.setError("Failed to upload to seafile. " + e.message) - return False - if self.copyLink: - ScreenCloud.setUrl(link) - return True + def saveSettings(self): + settings = QSettings() + settings.beginGroup("uploaders") + settings.beginGroup("seafile") + try: + self.copyLink = self.settingsDialog.linkCopyCheck.checked + except: + pass + settings.setValue("copy-link", self.copyLink) + if self.access_token is not None: + settings.setValue("auth-username", self.access_token.username ) + settings.setValue("auth-token", self.access_token.token) + settings.setValue("seafile-url", self.seaf_url) + if self.seaf_lib is not None: + settings.setValue("library", "%s/%s" % (self.seaf_lib.id,self.seaf_lib.name)) + settings.setValue("library-path", self.lib_path) + settings.setValue("name-format", self.nameFormat) + settings.setValue("upload-scheme", self.upload_scheme) + #settings.setValue("name-format", self.settingsDialog.group_name.input_name.text) + print self.seaf_lib, self.lib_path + settings.endGroup() + settings.endGroup() + + def isConfigured(self): + return self.access_token and self.seaf_url and self.processor.is_configured() - def startAuthenticationProcess(self): - self.saveSettings() - self.loadSettings() + def getFilename(self): + self.loadSettings() + return ScreenCloud.formatFilename(self.nameFormat) + + def upload(self, screenshot, name): + self.loadSettings() + #Make sure we have a up to date token + if not self.seaf_lib: + ScreenCloud.setError("Not configured properly") + return False + #Save to a temporary file + timestamp = time.time() + def tempfile(name): + try: + return QDesktopServices.storageLocation(QDesktopServices.TempLocation) + "/" + name + except AttributeError: + from PythonQt.QtCore import QStandardPaths #fix for Qt5 + return QStandardPaths.writableLocation(QStandardPaths.TempLocation) + "/" + name - if self.access_token is not None: - self.logOut() - return + tmpFilename = tempfile(ScreenCloud.formatFilename(str(timestamp))) + screenshot.save(QFile(tmpFilename), ScreenCloud.getScreenshotFormat()) + #Upload! + link=None + if True: + #try: + link = self.processor.upload(tmpFilename,self.getFilename()) + if self.copyLink: + ScreenCloud.setUrl(link) + #except Exception as e: + # ScreenCloud.setError("Failed to upload to seafile. " + e.message) + # return False + return True - if self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text \ - and self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text \ - and self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text: - self.seaf_url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text - if True: - #try: - self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) - self.saveSettings() - self.loadSettings() - self.populateLibrarySelector() - #except Exception as e: - #QMessageBox.critical(self.settingsDialog, "Failed to login", "Verify your server url and credentials" + e.message) - self.saveSettings() - self.updateUi() + def startAuthenticationProcess(self): + self.saveSettings() + self.loadSettings() - def locationUpdate(self): - drop = self.settingsDialog.group_location.widget_location.libraryEditDrop - selected_lib = drop.currentText - if not drop.isEnabled(): return #not populated - self.lib_path = self.settingsDialog.group_location.widget_location.pathEdit.text - print self.lib_path, selected_lib - if self.libs is None: return - for lib in self.libs: - if lib.name == selected_lib: - self.seaf_lib = lib - print "%s user selected" % selected_lib + if self.access_token is not None: + self.logOut() + return + + if self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text \ + and self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text \ + and self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text: + self.seaf_url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text + if True: + #try: + self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) + self.saveSettings() + self.loadSettings() + self.populateLibrarySelector() + #except Exception as e: + #QMessageBox.critical(self.settingsDialog, "Failed to login", "Verify your server url and credentials" + e.message) + self.saveSettings() + self.updateUi() + + def locationUpdate(self): + drop = self.settingsDialog.group_location.widget_location.libraryEditDrop + selected_lib = drop.currentText + if not drop.isEnabled(): return #not populated + self.lib_path = self.settingsDialog.group_location.widget_location.pathEdit.text + print self.lib_path, selected_lib + if self.libs is None: return + for lib in self.libs: + if lib.name == selected_lib: + self.seaf_lib = lib + print "%s user selected" % selected_lib - def login(self,user,password): - cli = SeafileClient(self.seaf_url,user,password) - self.access_token = cli.obtain_token() + def login(self,user,password): + cli = SeafileClient(self.seaf_url,user,password) + self.access_token = cli.obtain_token() - def logOut(self): - settings = QSettings() - settings.beginGroup("uploaders") - settings.beginGroup("seafile") - settings.remove("auth-token") - self.access_token = None - settings.endGroup() - settings.endGroup() - self.loadSettings() - self.updateUi() + def logOut(self): + settings = QSettings() + settings.beginGroup("uploaders") + settings.beginGroup("seafile") + settings.remove("auth-token") + self.access_token = None + settings.endGroup() + settings.endGroup() + self.loadSettings() + self.updateUi() + + def nameFormatEdited(self, nameFormat): + self.settingsDialog.group_name.label_example.setText(ScreenCloud.formatFilename(nameFormat, False)) - def nameFormatEdited(self, nameFormat): - self.settingsDialog.group_name.label_example.setText(ScreenCloud.formatFilename(nameFormat, False)) diff --git a/modules/processors.py b/modules/processors.py new file mode 100644 index 0000000..9d721a6 --- /dev/null +++ b/modules/processors.py @@ -0,0 +1,86 @@ +import time + +from encryptedscreenshot import EncryptedScreenshot, Signer +import getpass, os +from PythonQt.QtGui import QInputDialog +from PythonQt.QtCore import QSettings +from seafapi import * + +class Processor: + + def configure(self,parent): + pass + + def is_configured(self): + return True + + def upload(self,file): + pass + + +class DefaultProcessor(Processor): + + def __init__(self,seaf_lib,lib_path): + self.seaf_lib = seaf_lib + self.lib_path = lib_path + + def upload(self,file,name): + return self.seaf_lib.upload(file,name,self.lib_path).share() + +class EncryptedProcessor(Processor): + + def __init__(self,seaf_lib,lib_path): + self.seaf_lib = seaf_lib + self.lib_path = lib_path + self.load_settings() + self.host = "" + + def load_settings(self): + settings = QSettings() + settings.beginGroup("uploaders") + settings.beginGroup("seafile") + settings.beginGroup("encscreen") + self.host = settings.value("url", "") + settings.endGroup() + settings.endGroup() + settings.endGroup() + + def save_settings(self): + settings = QSettings() + settings.beginGroup("uploaders") + settings.beginGroup("seafile") + settings.beginGroup("encscreen") + settings.setValue("url", self.host) + settings.endGroup() + settings.endGroup() + settings.endGroup() + + def is_configured(self): + return self.host is not None and self.host != "" + + def configure(self,parent): + self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/s#%id%key):', text="https://screens.shimun.net/s#%id%key") + self.save_settings() + + def upload(self,file,name): + enrypted = EncryptedScreenshot({ + "owner": unicode(getpass.getuser()), + "format": unicode(str(file).split('.')[-1]), + "title": unicode(name), + "timestamp": int(time.time() * 1000), + "size": os.stat(file).st_size + },signer=Signer.default()) + tmpHandle = open(file + "c", 'wb') + tmpHandle.write(enrypted.assemble(file)) + tmpHandle.close() + seaf_file = self.seaf_lib.upload(file + "c",name + ".enc",self.lib_path) + if not seaf_file: + return + seaf_link = seaf_file.share() + if seaf_link: + id = str(seaf_link).split('/')[-2] + return self.host.replace('%id', id).replace('%key',"%s" % enrypted.password) + else: + return False + +