+ return self._callback
+
+ def set_callback_number(self, callback):
+ le = concurrent.AsyncLinearExecution(self._pool, self._set_callback_number)
+ le.start(callback)
+
+ def _set_callback_number(self, callback):
+ oldCallback = self._callback
+ try:
+ assert self.state == self.LOGGEDIN_STATE, "Callbacks configurable only when logged in (currently %s" % self.state
+ yield (
+ self._backend[0].set_callback_number,
+ (callback, ),
+ {},
+ )
+ except Exception, e:
+ _moduleLogger.exception("Reporting error to user")
+ self.error.emit(str(e))
+ return
+ self._callback = callback
+ if oldCallback != self._callback:
+ self.callbackNumberChanged.emit(self._callback)
+
+ def _login(self, username, password):
+ with qui_utils.notify_busy(self._errorLog, "Logging In"):
+ self._loggedInTime = self._LOGGINGIN_TIME
+ self.stateChange.emit(self.LOGGINGIN_STATE)
+ finalState = self.LOGGEDOUT_STATE
+ isLoggedIn = False
+ try:
+ if not isLoggedIn and self._backend[0].is_quick_login_possible():
+ isLoggedIn = yield (
+ self._backend[0].is_authed,
+ (),
+ {},
+ )
+ if isLoggedIn:
+ _moduleLogger.info("Logged in through cookies")
+ else:
+ # Force a clearing of the cookies
+ yield (
+ self._backend[0].logout,
+ (),
+ {},
+ )
+
+ if not isLoggedIn:
+ isLoggedIn = yield (
+ self._backend[0].login,
+ (username, password),
+ {},
+ )
+ if isLoggedIn:
+ _moduleLogger.info("Logged in through credentials")
+
+ if isLoggedIn:
+ self._loggedInTime = int(time.time())
+ oldUsername = self._username
+ self._username = username
+ finalState = self.LOGGEDIN_STATE
+ if oldUsername != self._username:
+ needOps = not self._load()
+ else:
+ needOps = True
+
+ self.loggedIn.emit()
+ self.stateChange.emit(finalState)
+ finalState = None # Mark it as already set
+
+ if needOps:
+ loginOps = self._loginOps[:]
+ else:
+ loginOps = []
+ del self._loginOps[:]
+ for asyncOp in loginOps:
+ asyncOp.start()
+ else:
+ self._loggedInTime = self._LOGGEDOUT_TIME
+ self.error.emit("Error logging in")
+ except Exception, e:
+ self._loggedInTime = self._LOGGEDOUT_TIME
+ _moduleLogger.exception("Reporting error to user")
+ self.error.emit(str(e))
+ finally:
+ if finalState is not None:
+ self.stateChange.emit(finalState)
+ if isLoggedIn and self._callback:
+ self.set_callback_number(self._callback)
+
+ def _load(self):
+ updateContacts = len(self._contacts) != 0
+ updateMessages = len(self._messages) != 0
+ updateHistory = len(self._history) != 0
+ oldDnd = self._dnd
+ oldCallback = self._callback
+
+ self._contacts = {}
+ self._messages = []
+ self._history = []
+ self._dnd = False
+ self._callback = ""
+
+ loadedFromCache = self._load_from_cache()
+ if loadedFromCache:
+ updateContacts = True
+ updateMessages = True
+ updateHistory = True
+
+ if updateContacts:
+ self.contactsUpdated.emit()
+ if updateMessages:
+ self.messagesUpdated.emit()
+ if updateHistory:
+ self.historyUpdated.emit()
+ if oldDnd != self._dnd:
+ self.dndStateChange.emit(self._dnd)
+ if oldCallback != self._callback:
+ self.callbackNumberChanged.emit(self._callback)
+
+ return loadedFromCache
+
+ def _load_from_cache(self):
+ if self._cachePath is None:
+ return False
+ cachePath = os.path.join(self._cachePath, "%s.cache" % self._username)
+
+ try:
+ with open(cachePath, "rb") as f:
+ dumpedData = pickle.load(f)
+ except (pickle.PickleError, IOError, EOFError, ValueError):
+ _moduleLogger.exception("Pickle fun loading")
+ return False
+ except:
+ _moduleLogger.exception("Weirdness loading")
+ return False
+
+ try:
+ (
+ version, build,
+ contacts, contactUpdateTime,
+ messages, messageUpdateTime,
+ history, historyUpdateTime,
+ dnd, callback
+ ) = dumpedData
+ except ValueError:
+ _moduleLogger.exception("Upgrade/downgrade fun")
+ return False
+ except:
+ _moduleLogger.exception("Weirdlings")
+
+ if misc_utils.compare_versions(
+ self._OLDEST_COMPATIBLE_FORMAT_VERSION,
+ misc_utils.parse_version(version),
+ ) <= 0:
+ _moduleLogger.info("Loaded cache")
+ self._contacts = contacts
+ self._contactUpdateTime = contactUpdateTime
+ self._messages = messages
+ self._messageUpdateTime = messageUpdateTime
+ self._history = history
+ self._historyUpdateTime = historyUpdateTime
+ self._dnd = dnd
+ self._callback = callback
+ return True
+ else:
+ _moduleLogger.debug(
+ "Skipping cache due to version mismatch (%s-%s)" % (
+ version, build
+ )
+ )
+ return False
+
+ def _save_to_cache(self):
+ _moduleLogger.info("Saving cache")
+ if self._cachePath is None:
+ return
+ cachePath = os.path.join(self._cachePath, "%s.cache" % self._username)
+
+ try:
+ dataToDump = (
+ constants.__version__, constants.__build__,
+ self._contacts, self._contactUpdateTime,
+ self._messages, self._messageUpdateTime,
+ self._history, self._historyUpdateTime,
+ self._dnd, self._callback
+ )
+ with open(cachePath, "wb") as f:
+ pickle.dump(dataToDump, f, pickle.HIGHEST_PROTOCOL)
+ _moduleLogger.info("Cache saved")
+ except (pickle.PickleError, IOError):
+ _moduleLogger.exception("While saving")
+
+ def _clear_cache(self):
+ updateContacts = len(self._contacts) != 0
+ updateMessages = len(self._messages) != 0
+ updateHistory = len(self._history) != 0
+ oldDnd = self._dnd
+ oldCallback = self._callback
+
+ self._contacts = {}
+ self._contactUpdateTime = datetime.datetime(1971, 1, 1)
+ self._messages = []
+ self._messageUpdateTime = datetime.datetime(1971, 1, 1)
+ self._history = []
+ self._historyUpdateTime = datetime.datetime(1971, 1, 1)
+ self._dnd = False
+ self._callback = ""