def sudo(command: str, password: str, timeout=None): stat, out, err = common.execute('/usr/bin/sudo -S %s' % (command), '%s\n' % password, timeout, shell=True) Log.append(sudo, 'sudo', locals()) return stat, out, err
def callback_menu(self, name): try: Log.append(self.callback_menu, 'Info', 'Click %s.' % name) menu = self.menu[name] menu['callback'](menu['object']) except: self.callback_exception()
def translate(text): _text = text text = replace(text) text = t.translate(self._translate_from, self._translate_to, text) text = replace(text) Log.append(self.translate, 'Translate', '\n%s\n%s' % (_text, text)) return text
def __init__(self, args): Log.append('app_init', 'Info', 'version: %s' % Const.version) set_default(default_zone=Zone(home_dir=pyinstaller.get_runtime_dir())) self.qt = QApplication(args) self.qt.setApplicationName(Const.app_name) self.qt.setWindowIcon( QIcon('%s/app/res/icon.png' % pyinstaller.get_runtime_dir())) self.hook_exception() self.config = Config() self.config.load() self.lang = None # type: English self.load_language(Config.language) self.events = { 'process_events': self.qt.processEvents, 'export_log': self.export_log, 'check_update': self.check_update, 'load_language': self.load_language, 'get_language': lambda: self.lang, 'set_language': self.set_language, 'get_config': lambda: self.config, }
def callback_exception(self): exc = common.get_exception() Log.append(self.callback_exception, 'Error', exc) if QMessageBox.warning(None, self.lang.title_crash, self.lang.description_crash): self.export_log()
def t_refresh(): try: ts = [] count = 0 while True: if not self.need_restart: t = time.time() self.callback_refresh() t = time.time() - t if count > 5: tl = len(ts) ta = t if tl == 0 else sum(ts) / tl if tl < 10 or t < ta * 2: ts.append(t) if tl >= 10: ts.pop(0) if ta >= Const.restart_deadline: self.need_restart = True Log.append( t_refresh, 'Warning', 'Refresh timeout (%s), Need restart.' % ta) if count % 30 == 0 and not self.lid_stat: Log.append(t_refresh, 'Info', 'Refresh average time (%s).' % ta) else: self.callback_refresh() time.sleep(1) count += 1 except: self.callback_exception()
def __init__(self, config_class): self.init_time = time.time() self.app = rumps.App(Const.app_name, quit_button=None) self.app_shell = init_app_shell() if self.app_shell.check(): Log.init_app(keep_log=self.is_restart) Log.append('app_init', 'Info', 'version: %s' % Const.version, 'args: %s' % sys.argv, system_api.get_system_version()) Log.append('app_shell', 'Info', { 'shell_class': self.app_shell.__class__.__name__, 'runtime_dir': self.app_shell.get_runtime_dir(), 'app_path': self.app_shell.get_app_path(), 'is_restart': self.is_restart, 'restart_data': self.restart_data, }) self.config = config_class() self.config.load() self.lang = load_language(self.config.language) # type: English self.menu = {} self.menu_check_update = None # type: rumps.MenuItem self.is_admin = system_api.check_admin() if not self.is_restart: threading.Thread(target=self.check_update, args=(False,)).start()
def check_update(self, by_user=False, test=False): try: release = github.get_latest_release(Const.author, Const.app_name, timeout=5) Log.append(self.check_update, 'Info', release) have_new = test or common.compare_version(Const.version, release['tag_name']) if have_new: rumps.notification( self.lang.noti_update_version % release['name'], self.lang.noti_update_time % release['published_at'], release['body'], ) if by_user: if have_new: if len(release['assets']) > 0: system_api.open_url(release['assets'][0]['browser_download_url']) else: system_api.open_url(release['html_url']) else: rumps.notification(self.lang.menu_check_update, self.lang.noti_update_none, self.lang.noti_update_star) except: Log.append(self.check_update, 'Warning', common.get_exception()) if by_user: rumps.notification(self.lang.menu_check_update, '', self.lang.noti_network_error)
def save(self): with open(self._config_path, 'w') as io: config = object_convert.object_to_dict(self) for f in self._protect_fields: config[f] = base64.b64encode(config[f].encode()).decode()[::-1] json.dump(config, io, indent=' ') Log.append('config_save', 'Info', object_convert.object_to_dict(self))
def lock_delay(self, wait): Log.append(self.lock_delay, 'Info', wait) if (self.is_locked or self.lid_stat) and wait is not None: return with self.t_lock: if wait is None: self.lock_time = None else: self.lock_time = time.time() + wait
def callback_lid_status_changed(self, status: bool, status_prev: bool = None): params = locals() Log.append(self.callback_lid_status_changed, 'Info', 'from "%s" to "%s"' % (status_prev, status)) if status and not status_prev: self.is_lid_wake = True self.event_trigger(self.callback_lid_status_changed, params, self.config.event_lid_status_changed)
def t_event_execute(): [stat, out, err] = common.execute( path_event, env={Const.app_env: object_convert.to_json(params)}, sys_env=False, timeout=self.config.process_timeout, shell=True) Log.append( source, 'Event', { 'path': path_event, 'status': stat, 'output': out, 'error': err })
def callback_exception(self, exc=None): need_restart = (time.time() - self.init_time) >= 10 if exc is None: exc = common.get_exception() Log.append(self.callback_exception, 'Error', exc) if 'KeyboardInterrupt' in exc: self.quit() elif 'Too many open files in system' in exc: self.quit() if osa_api.alert(self.lang.title_crash, self.lang.description_crash): self.export_log() if need_restart: self.restart()
def callback_weak_signal(self, status: bool, status_prev: bool = None): params = locals() Log.append( self.callback_weak_signal, 'Info', 'from "%s" to "%s", signal value: %s' % (status_prev, status, self.signal_value)) self.refresh_app_icon_status() if status: self.lock_delay(self.config.weak_signal_lock_delay) else: self.lock_delay(None) self.event_trigger(self.callback_weak_signal, params, self.config.event_weak_signal)
def unlock(self): result = False if self.is_locked: if self.config.password != '': if self.unlock_count < Const.unlock_count_limit: self.unlock_by_user = False keys = [ dict(key='a', modifier='command down'), dict(key=self.config.password), dict(key='return', constant=True), ] for key in keys: self.refresh_cg_session_info() if not self.is_locked: result = True break [stat, _, _] = osa_api.key_stroke(**key) if stat != 0: break if not result: self.refresh_cg_session_info() result = not self.is_locked elif self.unlock_count == Const.unlock_count_limit: rumps.notification(self.lang.title_info, '', self.lang.noti_unlock_error) self.unlock_count += 1 elif self.hint_set_password: self.hint_set_password = False rumps.notification(self.lang.title_info, '', self.lang.noti_password_need) Log.append( self.unlock, 'Info', dict( unlock_count=self.unlock_count, is_lid_wake=self.is_lid_wake, is_idle_wake=self.is_idle_wake, is_sleep_wake=self.is_sleep_wake, result=result, )) return result
def lock_now(self, by_app=True): Log.append( self.lock_now, 'Info', dict( is_locked=self.is_locked, is_lid_wake=self.is_lid_wake, is_idle_wake=self.is_idle_wake, is_sleep_wake=self.is_sleep_wake, )) if not self.is_locked and not self.is_wake: self.lock_time = None self.lock_by_app = by_app if self.config.use_screen_saver_replace_lock: osa_api.screen_save() else: system_api.sleep(True)
def load(self): try: if os.path.exists(self._config_path): with open(self._config_path, 'r') as io: config = json.load(io) for f in self._protect_fields: config[f] = base64.b64decode( config[f][::-1].encode()).decode() object_convert.dict_to_object(config, self, new_fields=False) Log.set_replaces( dict([(getattr(self, f), Const.protector) for f in self._protect_fields])) Log.append('config_load', 'Info', object_convert.object_to_dict(self)) except: self.save()
def callback_connect_status_changed(self, status: bool, status_prev: bool = None): params = locals() Log.append(self.callback_connect_status_changed, 'Info', 'from "%s" to "%s"' % (status_prev, status)) self.refresh_app_icon_status() if status_prev is not None and not status: # disconnect. if self.lock_time is None: self.lock_delay(self.config.disconnect_lock_delay) elif not status_prev and status: # reconnect. if not self.is_weak: self.lock_delay(None) self.event_trigger(self.callback_connect_status_changed, params, self.config.event_connect_status_changed)
def check_update(self, test=False): try: release = github.get_latest_release(Const.author, Const.app_name, timeout=5) Log.append(self.check_update, 'Info', release) if test or common.compare_version(Const.version, release['tag_name']): if len(release['assets']) > 0: QMessageBox.information( self.lang.title_check_update, '%s\n%s\n\n%s' % (self.lang.description_new_version, release['body'], release['assets'][0]['browser_download_url'])) else: QMessageBox.information( self.lang.title_check_update, '%s\n%s\n\n%s' % (self.lang.description_new_version, release['body'], release['assets'][0]['browser_download_url'])) except: Log.append(self.check_update, 'Warning', common.get_exception())
def callback_lock_status_changed(self, status: bool, status_prev: bool = None): params = locals() is_lock = status and not status_prev is_unlock = status_prev and not status if is_lock: if self.idle_time < Const.idle_time_short and not self.lock_by_app: self.lock_by_user = True Log.append( self.callback_lock_status_changed, 'Info', 'from "%s" to "%s"' % (status_prev, status), dict(lock_by_user=self.lock_by_user, unlock_by_user=self.unlock_by_user, is_locked=self.is_locked, is_sleep_wake=self.is_sleep_wake, is_lid_wake=self.is_lid_wake, is_idle_wake=self.is_idle_wake)) if is_lock: # reset user unlock status. self.unlock_by_user = True elif is_unlock: if self.unlock_by_user and not self.lock_by_user and self.config.password != '': if not self.disable_near_unlock: self.set_disable_leave_lock(True) self.reset_wake() self.lock_by_user = False self.lock_by_app = False self.hint_set_password = True self.unlock_count = 0 self.event_trigger(self.callback_lock_status_changed, params, self.config.event_lock_status_changed)
def exec(code: str, timeout=None): stat, out, err = common.execute('/usr/bin/osascript', code, timeout) Log.append(AppleScript.exec, 'AppleScript', locals()) return stat, out, err
from app.res.language import load_language, LANGUAGES from app.res.language.translate_language import TranslateLanguage from app.util.log import Log from tools.translate import * sys_type = platform.system() datas = {} def add_data(src, dest): if os.path.exists(src): datas[src] = dest # build translate language data. Log.append('Build', 'Info', 'Building translate data now...') load_language() for lang_type in LANGUAGES.values(): if issubclass(lang_type, TranslateLanguage): lang = lang_type() if not lang._translated: if lang._translate_to == 'cn_t': translator = zhconv() elif '--translate-baidu' in sys.argv: translator = baidu_translate() else: translator = google_translate() Log.append('Build', 'Translate', 'Using %s' % translator.__class__.__name__) lang.translate(translator)