import logging import os.path import sys logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('app.log', encoding='utf-8'), logging.StreamHandler(sys.stdout) ] ) from colorama import Fore # noqa: E402 from api import ClockifyAPI, RedmineAPI # noqa: E402 from config import arg_parser, config, db # noqa: E402 from utils import format_date, str_to_date, today_start, today_end, parse_task_id # noqa: E402 WORKSPACE_ID = config.WORKSPACE_ID USER_ID = config.USER_ID def main(): args = arg_parser.parse_args() if args.debug: logging.getLogger().setLevel(logging.DEBUG) logger = logging.getLogger(__name__) start, end = None, None if args.start: start = str_to_date(args.start) if args.end: end = str_to_date(args.end) if args.start is None and args.end is None: logger.info("Парсим задачи за сегодняшний день") start = today_start() end = today_end() else: if start: from_ = f"{start.day} {config.MONTHS.get(start.month)} {start.year} г." if end: to_ = f"{end.day} {config.MONTHS.get(end.month)} {end.year} г." if start == end: logger.info(f"{Fore.YELLOW}Парсим задачи за {from_}{Fore.RESET}") else: logger.info(Fore.YELLOW + "Парсим задачи" + (f" с {from_} " if start else " ") + (f"до {to_}" if end else "") + Fore.RESET) clock = ClockifyAPI( token=config.CLOCKIFY_TOKEN, workspace_id=WORKSPACE_ID, user_id=USER_ID ) if not WORKSPACE_ID or not USER_ID: if not os.path.exists(config.ENV_TXT): logger.info(f"{Fore.YELLOW}Необходимые переменные не были обнаружены. Попытка получения...{Fore.RESET}") clock.getenvs() else: logger.info(f'{Fore.YELLOW}Проверьте файл "{config.ENV_TXT}". Если необходимых переменных в нём нет, то просто удалите его.{Fore.RESET}') return red = RedmineAPI(config.REDMINE_TOKEN) user = clock.get_user() clock_user = { "clockify_user_id": user["id"], "clockify_email": user["email"], "clockify_username": user["username"], } user = red.get_user() red_user = { "redmine_user_id": user["id"], "redmine_email": user["email"], "first_name": user["first_name"], "last_name": user["last_name"], "redmine_username": user["username"] } db.insert_user(**clock_user, **red_user) if args.init_db: logger.info(Fore.YELLOW + "Обновление базы данных..." + Fore.RESET) try: # Обновление Тегов logger.info(f"{Fore.YELLOW}Обновление Тегов...\n{Fore.RESET}") clock_tags = clock.get_tags(is_updating=True, **{"page-size": clock.tags_count}) db_tags = db.get_tags() new_tags = [tag for tag in clock_tags if tag not in db_tags] if new_tags: try: db.insert_tags(new_tags) logger.info(f"{Fore.GREEN}Обновлено тегов: {len(new_tags)}{Fore.RESET}") except Exception as e: logger.error(f"{Fore.RED}Ошибка при сохранении тегов!{Fore.RESET}") else: logger.info(f"{Fore.YELLOW}Обновление тегов не требуется.\n{Fore.RESET}") # Обновление Задач logger.info(f"{Fore.YELLOW}Обновление Задач...\n{Fore.RESET}") db_tasks = db.get_tasks() red_tasks = red.get_issues() clock_tasks = [task for task in red_tasks if task.id in [parse_task_id(tag.title) for tag in [*db_tags, *new_tags]]] new_tasks = [task for task in clock_tasks if task not in db_tasks] if new_tasks: try: db.insert_tasks(new_tasks) logger.info(f"{Fore.GREEN}Обновлено задач: {len(new_tasks)}{Fore.RESET}") except Exception as e: logger.error(f"{Fore.RED}Ошибка при сохранении задач!{Fore.RESET}") else: logger.info(f"{Fore.YELLOW}Обновление задач не требуется\n{Fore.RESET}") # # Обновление Проектов Ветро # logger.info(f"{Fore.YELLOW}Получение Проектов Ветро{Fore.RESET}") # vetro_projects = clock.get_vetro_projects() # logger.info(f"{Fore.YELLOW}Получение Типов деятельности{Fore.RESET}") # activity_types = red.get_time_entry_activities() # if vetro_projects: # logger.info(f"{Fore.YELLOW}Сохранение Проектов Ветро{Fore.RESET}") # db.insert_vetro_projects(vetro_projects) # if activity_types: # logger.info(f"{Fore.YELLOW}Сохранение Типов деятелности{Fore.RESET}") # db.insert_activity_types(activity_types) except Exception as e: logger.error(Fore.RED + f"Ошибка при обновлении базы данных: {e}" + Fore.RESET) else: logger.info(Fore.GREEN + "База данных теперь актуальна." + Fore.RESET) activities = sorted(clock.get_activities( **{ "start": format_date(start), "end": format_date(end), "page-size": args.page_size, }, ), key=lambda x: x.date_start) if not activities: logger.info(Fore.YELLOW + "Нет задач для занесения трудочасов" + Fore.RESET) return db.insert_activities(activities) if args.debug: logger.debug("Пропускаем этап загрузки трудочасов") return try: tracked_activities = red.track_activities(activities) clock.mark_tracked(tracked_activities) db.insert_time_entries(tracked_activities) db.insert_activities(tracked_activities) except Exception as e: logger.error(e) if __name__ == "__main__": main()