예제 #1
0
    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)
예제 #2
0
 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()
예제 #3
0
 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
예제 #4
0
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
예제 #5
0
    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,
        }
예제 #6
0
        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()
예제 #7
0
    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()
예제 #8
0
 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))
예제 #9
0
    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
예제 #10
0
    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)
예제 #11
0
    def export_log(self):
        folder = osa_api.choose_folder(self.lang.menu_export_log)
        if folder is not None:
            log_str = Log.extract_log()
            err_str = Log.extract_err()

            if log_str != '':
                with open('%s/%s' % (folder, '%s.log' % Const.app_name), 'w') as io:
                    io.write(log_str)

            if err_str != '':
                with open('%s/%s' % (folder, '%s.err' % Const.app_name), 'w') as io:
                    io.write(err_str)
예제 #12
0
 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
         })
예제 #13
0
    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()
예제 #14
0
    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)
예제 #15
0
    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
예제 #16
0
    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)
예제 #17
0
 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()
예제 #18
0
    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)
예제 #19
0
    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())
예제 #20
0
    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()
예제 #21
0
    def export_log(self):
        folder = QFileDialog.getExistingDirectory(
            None, caption=self.lang.menu_export_log)
        if folder is not None:
            log = Log.extract_log()
            err = Log.extract_err()

            for f in Config._protect_fields:
                v = getattr(Config, f, '')
                if v != '':
                    log = log.replace(v, Const.protector)
                    err = err.replace(v, Const.protector)

            if log != '':
                with open('%s/%s' % (folder, '%s.log' % Const.app_name),
                          'w') as io:
                    io.write(log)

            if err != '':
                with open('%s/%s' % (folder, '%s.err' % Const.app_name),
                          'w') as io:
                    io.write(err)
예제 #22
0
    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)
예제 #23
0
import sys

from app import Application
from app.util import pyinstaller
from app.util.log import Log

if getattr(sys, 'frozen', False):
    # is run at pyinstaller
    pyinstaller.fix_encoding_in_pyinstaller()
    Log.init_app()

app = Application(sys.argv)

try:
    status = app.run()
    sys.exit(status)
except SystemExit:
    pass
except:
    app.callback_exception()
예제 #24
0
 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
예제 #25
0
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)