import time import os import re import pyperclip from pywinauto import Application, findwindows, clipboard, timings from pywinauto.controls.hwndwrapper import HwndWrapper from PIL import ImageGrab class WhaleTranslator: def __init__(self, logger): self.logger = logger self.whale_app = None self.whale_window = None def start_whale_browser(self): whale_exe_path = os.path.join(os.getcwd(), "browsers", "whale", "whale.exe") user_data_dir = os.path.join(os.getcwd(), "browsers", "whale", "user_data") cache_dir = os.path.join(os.getcwd(), "browsers", "whale", "cache") self.whale_app = Application(backend="uia").start( f'"{whale_exe_path}" --incognito --user-data-dir="{user_data_dir}" --disk-cache-dir="{cache_dir}"' ) # 창이 완전히 생성될 때까지 대기 self.whale_window = self.find_whale_window() if self.whale_window: self.logger.info("웨일 시크릿 모드로 시작 완료.") else: self.logger.warning("웨일 창을 찾을 수 없습니다.") def find_whale_window(self): try: # 최대 10초 동안 '새 시크릿 탭 - Whale' 창이 나타나기를 기다림 timings.wait_until(10, 0.5, lambda: any(window.name == '새 시크릿 탭 - Whale' for window in findwindows.find_elements())) windows = findwindows.find_elements() for window in windows: if window.name == '새 시크릿 탭 - Whale': whale_pid = window.process_id self.whale_app = Application(backend="uia").connect(process=whale_pid) self.whale_window = self.whale_app.top_window() # 위치 및 크기 조절 self.hwnd_wrapper = HwndWrapper(self.whale_window.handle) self.hwnd_wrapper.move_window(x=1, y=1, width=1280, height=720) self.whale_window.set_focus() self.logger.info("웨일 창을 성공적으로 찾았습니다.") return self.whale_window self.logger.error("'새 시크릿 탭 - Whale' 창을 찾을 수 없습니다.") except Exception as e: self.logger.error(f"웨일 창 탐색 중 오류 발생: {e}", exc_info=True) return None def navigate_to_url(self, url): """주소창에 URL을 입력하고 페이지 로딩을 대기""" try: # URL을 클립보드에 복사 pyperclip.copy(url) # 주소창을 클릭하여 URL 붙여넣기 address_bar = self.whale_window.child_window(title="주소창 및 검색창", control_type="Edit") address_bar.click_input() # Ctrl + V로 URL 붙여넣기 후 Enter 키 입력 address_bar.type_keys("^v{ENTER}", with_spaces=True) self.logger.debug(f"{url}로 이동 중...") # 5초 동안 0.1초 간격으로 이미지 요소가 나타나는지 검사 start_time = time.time() while time.time() - start_time < 5: try: # 특정 이미지 요소를 찾으면 즉시 반환 image_element = self.whale_window.child_window(title="누락된 이미지 설명을 확인하려면 컨텍스트 메뉴를 여세요.", control_type="Image") if image_element.exists(timeout=0.5): self.logger.debug("페이지 로딩 완료: 이미지 요소가 나타났습니다.") return except Exception: pass # 요소가 아직 나타나지 않은 경우 대기 self.logger.error("지정된 시간 내에 이미지 요소를 찾지 못했습니다.") except Exception as e: self.logger.error(f"주소창에 접근할 수 없습니다: {e}", exc_info=True) def right_click_on_image_and_action(self, actions = None): try: image = self.whale_window.child_window(title="누락된 이미지 설명을 확인하려면 컨텍스트 메뉴를 여세요.", control_type="Image") if image.exists(): image.right_click_input() self.logger.debug("이미지 요소에서 우클릭을 수행했습니다.") else: self.logger.error("이미지 요소를 찾을 수 없습니다.") return # 이미지 번역 if actions == '이미지번역': translate_menu_item = self.whale_window.child_window(title="이미지 번역 (R)", control_type="MenuItem") translate_menu_item.click_input() self.logger.debug("이미지 번역 명령이 실행되었습니다.") time.sleep(0.5) # 쇼핑 렌즈 if actions == '쇼핑렌즈': translate_menu_item = self.whale_window.child_window(title="이미지 번역 (R)", control_type="MenuItem") translate_menu_item.click_input() self.logger.debug("이미지 번역 명령이 실행되었습니다.") time.sleep(0.5) except Exception as e: self.logger.error(f"이미지 요소에서 우클릭 중 오류 발생: {e}", exc_info=True) return False def click_back_button(self): """'뒤로' 버튼을 클릭합니다.""" try: # '뒤로' 버튼 찾기 back_button = self.whale_window.child_window(title="뒤로", control_type="Button") if back_button.exists(): back_button.click_input() self.logger.debug("'뒤로' 버튼을 클릭했습니다.") else: self.logger.warning("'뒤로' 버튼을 찾을 수 없습니다.") except Exception as e: self.logger.error(f"'뒤로' 버튼 클릭 중 오류 발생: {e}", exc_info=True) def close_whale_window(self): """웨일 창을 종료하는 메서드.""" try: if self.whale_app: self.whale_app.kill() self.logger.info("웨일 창을 성공적으로 종료했습니다.") else: self.logger.warning("웨일 애플리케이션이 시작되지 않았습니다.") except Exception as e: self.logger.error("웨일 창을 종료하는 중 오류 발생", exc_info=True)