def main(): src_dir = os.path.dirname(os.path.abspath(__file__)) config_full_path = os.path.join(src_dir, '../config/config_example.yaml') parser = argparse.ArgumentParser( description=f'[{APP_ID}] Track & analyze your computer activity') parser.add_argument('--log-level', type=str, choices=['debug', 'info', 'warning', 'error'], default='debug', metavar='', help='debug/info/warning/error') parser.add_argument('-c', '--config', type=str, default=config_full_path, metavar='', help='config path') args = parser.parse_args() log_level_map = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR } coloredlogs.install(log_level_map[args.log_level]) logger = logging.getLogger(APP_ID) pid_file = f'{tempfile.gettempdir()}/{APP_ID}.pid' fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: app_exit(logger, msg='Another instance is already running!') config = None error_config_msg = 'Speaking Eye does not work without config. Bye baby!' try: with open(args.config) as config_file: config = yaml.safe_load(config_file) except Exception: logger.exception(f'Config [{args.config}] is not correct') app_exit(logger, error_config_msg) if not config: logger.error(f'Config [{args.config}] is empty') app_exit(logger, error_config_msg) application_info_reader = ApplicationInfoReader() config_reader = ConfigReader(application_info_reader, config) detailed_app_infos = config_reader.try_read_application_info_list( ConfigReader.ConfigKey.DETAILED_NODE) # NOTE: Implicitly add LockScreen to monitor Break Time activity # to not to add this info at user detailed apps config break_time_activity_info = ApplicationInfo( SpecialApplicationInfoTitle.BREAK_TIME.value, SpecialWmClass.LOCK_SCREEN.value, tab_re='', is_distracting=False) detailed_app_infos.append(break_time_activity_info) distracting_app_infos = config_reader.try_read_application_info_list( ConfigReader.ConfigKey.DISTRACTING_NODE) application_info_matcher = ApplicationInfoMatcher(detailed_app_infos, distracting_app_infos) activity_reader = ActivityReader(logger, application_info_matcher) current_file_dir = Path(os.path.dirname(os.path.abspath(__file__))) app_root_dir = current_file_dir / '..' files_provider = FilesProvider(app_root_dir) dash_server_thread = threading.Thread(target=dash_report_server_main, kwargs={ 'config_reader': config_reader, 'logger': logger, 'activity_reader': activity_reader, 'files_provider': files_provider, }, daemon=True) dash_server_thread.start() app = SpeakingEyeApp(APP_ID, config, config_reader, logger, application_info_matcher, activity_reader, files_provider) app.run() app.start_main_loop()