commit 62a95c6fcce0e5c410d464f3ed79868565577a3d
Author: 9700X_PC <9700X_PC@gmail.com>
Date: Thu Jun 26 18:33:57 2025 +0900
first commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..442ca8b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+build/
+dist/
+*.pyc
+*.pyo
+*.pyd
+include/
+lib/
+scripts/
+pyvenv.cfg
diff --git a/ExtensionInstaller.spec b/ExtensionInstaller.spec
new file mode 100644
index 0000000..37f8d89
--- /dev/null
+++ b/ExtensionInstaller.spec
@@ -0,0 +1,38 @@
+# -*- mode: python ; coding: utf-8 -*-
+
+
+a = Analysis(
+ ['main.py'],
+ pathex=[],
+ binaries=[],
+ datas=[('wrmc_ext', 'wrmc_ext')],
+ hiddenimports=[],
+ hookspath=[],
+ hooksconfig={},
+ runtime_hooks=[],
+ excludes=[],
+ noarchive=False,
+ optimize=0,
+)
+pyz = PYZ(a.pure)
+
+exe = EXE(
+ pyz,
+ a.scripts,
+ a.binaries,
+ a.datas,
+ [],
+ name='ExtensionInstaller',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=True,
+ upx_exclude=[],
+ runtime_tmpdir=None,
+ console=False,
+ disable_windowed_traceback=False,
+ argv_emulation=False,
+ target_arch=None,
+ codesign_identity=None,
+ entitlements_file=None,
+)
diff --git a/log.txt b/log.txt
new file mode 100644
index 0000000..ea0deb1
--- /dev/null
+++ b/log.txt
@@ -0,0 +1,195 @@
+[2025-06-25 22:17:24] 관리자 권한 체크: 1
+[2025-06-25 22:17:24] 프로그램 시작
+[2025-06-25 22:17:24] 탐지된 브라우저: [{'name': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'}, {'name': 'Whale', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe'}, {'name': 'Edge', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe'}]
+[2025-06-25 22:17:28] 설치 버튼 클릭
+[2025-06-25 22:17:28] 선택된 브라우저: [{'name': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'}]
+[2025-06-25 22:17:28] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 22:17:28] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 22:17:28] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:17:28] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:17:28] 결과 UI 표시 완료
+[2025-06-25 22:17:28] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 22:17:28] 크롬 실행중 여부: True
+[2025-06-25 22:17:34] 크롬 실행중: 수동 안내
+[2025-06-25 22:17:40] 설치 안내 메시지 표시
+[2025-06-25 22:17:43] 관리자 권한 체크: 1
+[2025-06-25 22:17:43] 프로그램 시작
+[2025-06-25 22:17:43] 탐지된 브라우저: [{'name': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'}, {'name': 'Whale', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe'}, {'name': 'Edge', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe'}]
+[2025-06-25 22:17:47] 설치 버튼 클릭
+[2025-06-25 22:17:47] 선택된 브라우저: [{'name': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'}]
+[2025-06-25 22:17:47] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 22:17:47] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 22:17:47] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:17:47] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:17:47] 결과 UI 표시 완료
+[2025-06-25 22:17:47] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 22:17:47] 크롬 실행중 여부: False
+[2025-06-25 22:17:47] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 22:17:54] 설치 안내 메시지 표시
+[2025-06-25 22:17:55] 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:22:41] 관리자 권한 체크: 1
+[2025-06-25 22:22:41] 프로그램 시작
+[2025-06-25 22:22:41] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 22:22:47] 설치 버튼 클릭
+[2025-06-25 22:22:47] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 22:22:47] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 22:22:47] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 22:22:47] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:22:47] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:22:47] 결과 UI 표시 완료
+[2025-06-25 22:22:47] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 22:22:47] 크롬 실행중 여부: False
+[2025-06-25 22:22:47] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 22:22:51] 설치 안내 메시지 표시
+[2025-06-25 22:22:52] 확장주소 복사: chrome://extensions/
+[2025-06-25 22:40:37] 관리자 권한 체크: 1
+[2025-06-25 22:40:37] 프로그램 시작
+[2025-06-25 22:40:37] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 22:40:42] 설치 버튼 클릭
+[2025-06-25 22:40:42] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 22:40:42] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 22:40:42] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 22:40:42] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:40:42] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:40:42] 결과 UI 표시 완료
+[2025-06-25 22:40:42] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 22:40:42] 크롬 실행중 여부: False
+[2025-06-25 22:40:42] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 22:40:56] 설치 안내 메시지 표시
+[2025-06-25 22:40:57] 확장주소 복사: chrome://extensions/
+[2025-06-25 22:43:36] 관리자 권한 체크: 1
+[2025-06-25 22:43:36] 프로그램 시작
+[2025-06-25 22:43:36] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 22:43:40] 설치 버튼 클릭
+[2025-06-25 22:43:40] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 22:43:40] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 22:43:40] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 22:43:40] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:43:40] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 22:43:40] 결과 UI 표시 완료
+[2025-06-25 22:43:40] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 22:43:40] 크롬 실행중 여부: False
+[2025-06-25 22:43:40] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 22:43:41] 설치 안내 메시지 표시
+[2025-06-25 23:19:53] 관리자 권한 체크: 1
+[2025-06-25 23:19:53] 프로그램 시작
+[2025-06-25 23:19:53] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:19:57] 설치 버튼 클릭
+[2025-06-25 23:19:57] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 23:19:57] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:19:57] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:19:57] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:19:57] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:19:57] 결과 UI 표시 완료
+[2025-06-25 23:19:57] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:19:57] 크롬 실행중 여부: False
+[2025-06-25 23:19:57] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 23:19:59] 설치 안내 메시지 표시
+[2025-06-25 23:23:42] 관리자 권한 체크: 1
+[2025-06-25 23:23:42] 프로그램 시작
+[2025-06-25 23:23:42] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:23:46] 설치 버튼 클릭
+[2025-06-25 23:23:46] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 23:23:46] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:23:46] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:23:46] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:23:46] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:23:46] 결과 UI 표시 완료
+[2025-06-25 23:23:46] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:23:46] 크롬 실행중 여부: True
+[2025-06-25 23:23:50] 크롬 실행중: 수동 안내
+[2025-06-25 23:23:52] 설치 안내 메시지 표시
+[2025-06-25 23:24:02] 확장주소 복사: chrome://extensions/
+[2025-06-25 23:24:14] 폴더 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:26:05] 관리자 권한 체크: 1
+[2025-06-25 23:26:05] 프로그램 시작
+[2025-06-25 23:26:05] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:26:09] 설치 버튼 클릭
+[2025-06-25 23:26:09] 선택된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}]
+[2025-06-25 23:26:09] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:26:09] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:26:09] Chrome 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:26:09] Chrome 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:26:09] 결과 UI 표시 완료
+[2025-06-25 23:26:09] Chrome 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:26:09] 크롬 실행중 여부: False
+[2025-06-25 23:26:09] 크롬 확장페이지 새창으로 오픈
+[2025-06-25 23:26:10] 설치 안내 메시지 표시
+[2025-06-25 23:26:11] 확장주소 복사: chrome://extensions/
+[2025-06-25 23:26:24] 폴더 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\chrome_extension
+[2025-06-25 23:28:06] 관리자 권한 체크: 1
+[2025-06-25 23:28:06] 프로그램 시작
+[2025-06-25 23:28:06] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:28:09] 설치 버튼 클릭
+[2025-06-25 23:28:09] 선택된 브라우저: [{'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}]
+[2025-06-25 23:28:09] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:28:09] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:28:09] Whale 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:28:09] 결과 UI 표시 완료
+[2025-06-25 23:28:09] Whale 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:28:09] 웨일 확장페이지 새창으로 오픈
+[2025-06-25 23:28:13] 설치 안내 메시지 표시
+[2025-06-25 23:28:13] 확장주소 복사: whale://extensions/
+[2025-06-25 23:28:20] 폴더 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:31:07] 관리자 권한 체크: 1
+[2025-06-25 23:31:07] 프로그램 시작
+[2025-06-25 23:31:07] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:31:09] 설치 버튼 클릭
+[2025-06-25 23:31:09] 선택된 브라우저: [{'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}]
+[2025-06-25 23:31:09] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:31:09] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:31:09] Whale 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:31:09] Whale 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:31:09] 결과 UI 표시 완료
+[2025-06-25 23:31:09] Whale 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:31:09] 웨일 확장페이지 새창으로 오픈
+[2025-06-25 23:31:16] 설치 안내 메시지 표시
+[2025-06-25 23:32:06] 관리자 권한 체크: 1
+[2025-06-25 23:32:06] 프로그램 시작
+[2025-06-25 23:32:06] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:32:08] 설치 버튼 클릭
+[2025-06-25 23:32:08] 선택된 브라우저: [{'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}]
+[2025-06-25 23:32:08] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:32:08] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:32:08] Whale 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:32:08] Whale 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:32:08] 결과 UI 표시 완료
+[2025-06-25 23:32:08] Whale 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:32:08] 웨일 확장페이지 새창으로 오픈
+[2025-06-25 23:32:15] 설치 안내 메시지 표시
+[2025-06-25 23:32:16] 확장주소 복사: whale://extensions/
+[2025-06-25 23:32:36] 폴더 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:33:24] 관리자 권한 체크: 1
+[2025-06-25 23:33:24] 프로그램 시작
+[2025-06-25 23:33:24] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:33:26] 설치 버튼 클릭
+[2025-06-25 23:33:26] 선택된 브라우저: [{'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}]
+[2025-06-25 23:33:26] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:33:26] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:33:26] Whale 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:33:26] Whale 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:33:26] 결과 UI 표시 완료
+[2025-06-25 23:33:26] Whale 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:33:26] 웨일 확장페이지 새창으로 오픈
+[2025-06-25 23:33:31] 설치 안내 메시지 표시
+[2025-06-25 23:33:31] 확장주소 복사: whale://extensions/
+[2025-06-25 23:33:41] 폴더 경로 복사: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:37:11] 관리자 권한 체크: 1
+[2025-06-25 23:37:11] 프로그램 시작
+[2025-06-25 23:37:11] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-25 23:37:12] 설치 버튼 클릭
+[2025-06-25 23:37:12] 선택된 브라우저: [{'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}]
+[2025-06-25 23:37:12] wrmc_ext 폴더 경로: D:\py\AutoPercenty3_311\test\ext\wrmc_ext
+[2025-06-25 23:37:12] 설치 베이스 디렉토리: C:\Users\Administrator\AppData\Local\my_extension_installer
+[2025-06-25 23:37:12] Whale 기존 폴더 삭제: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:37:12] Whale 확장 폴더 복사 완료: C:\Users\Administrator\AppData\Local\my_extension_installer\whale_extension
+[2025-06-25 23:37:12] 결과 UI 표시 완료
+[2025-06-25 23:37:12] Whale 확장 프로그램 설정페이지 오픈 시도
+[2025-06-25 23:37:12] 웨일 확장페이지 새창으로 오픈
+[2025-06-25 23:57:36] 설치 안내 메시지 표시
+[2025-06-26 11:54:08] 관리자 권한 체크: 1
+[2025-06-26 11:54:08] 프로그램 시작
+[2025-06-26 11:54:08] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
+[2025-06-26 17:28:21] 관리자 권한 체크: 1
+[2025-06-26 17:28:21] 프로그램 시작
+[2025-06-26 17:28:21] 탐지된 브라우저: [{'name': 'Chrome', 'display': 'Chrome', 'path': 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'url': 'chrome://extensions/'}, {'name': 'Whale', 'display': 'Whale (네이버 웨일)', 'path': 'C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe', 'url': 'whale://extensions/'}, {'name': 'Edge', 'display': 'Edge (마이크로소프트)', 'path': 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 'url': 'edge://extensions/'}]
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..ff5fb5f
--- /dev/null
+++ b/main.py
@@ -0,0 +1,343 @@
+import sys
+import os
+import shutil
+import subprocess
+import ctypes
+import psutil
+import traceback
+from pathlib import Path
+from datetime import datetime
+
+from PySide6.QtWidgets import (
+ QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QMessageBox, QCheckBox,
+ QGroupBox, QSizePolicy, QScrollArea
+)
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QClipboard
+
+def get_resource_path(relative_path):
+ """PyInstaller로 만든 실행파일에서 리소스 경로를 올바르게 반환합니다."""
+ try:
+ # PyInstaller가 생성한 임시 폴더
+ base_path = sys._MEIPASS
+ except Exception:
+ # 개발 환경에서는 현재 스크립트의 디렉토리
+ base_path = os.path.dirname(os.path.abspath(sys.argv[0]))
+
+ return os.path.join(base_path, relative_path)
+
+def write_log(msg, exc_info=None):
+ try:
+ log_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "log.txt")
+ with open(log_path, "a", encoding="utf-8") as f:
+ now = datetime.now().strftime("[%Y-%m-%d %H:%M:%S] ")
+ f.write(now + msg + "\n")
+ if exc_info:
+ f.write(traceback.format_exc() + "\n")
+ except Exception as e:
+ print("로그 기록 실패:", e)
+
+def is_admin():
+ try:
+ admin = ctypes.windll.shell32.IsUserAnAdmin()
+ write_log(f"관리자 권한 체크: {admin}")
+ return admin
+ except Exception:
+ write_log("관리자 권한 체크 중 오류", exc_info=True)
+ return False
+
+BROWSER_INFOS = [
+ {"name": "Chrome", "display": "Chrome", "path": r"C:\Program Files\Google\Chrome\Application\chrome.exe", "url": "chrome://extensions/"},
+ {"name": "Whale", "display": "Whale (네이버 웨일)", "path": r"C:\Program Files\Naver\Naver Whale\Application\whale.exe", "url": "whale://extensions/"},
+ {"name": "Edge", "display": "Edge (마이크로소프트)", "path": r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", "url": "edge://extensions/"},
+ {"name": "Edge2", "display": "Edge (마이크로소프트)", "path": r"C:\Program Files\Microsoft\Edge\Application\msedge.exe", "url": "edge://extensions/"}
+]
+
+def get_install_base_dir():
+ path = os.path.join(os.environ["LOCALAPPDATA"], "my_extension_installer")
+ write_log(f"설치 베이스 디렉토리: {path}")
+ return path
+
+def find_browsers():
+ browser_list = []
+ used = set()
+ for info in BROWSER_INFOS:
+ if os.path.exists(info["path"]) and info["name"] not in used:
+ browser_list.append({
+ "name": info["name"] if info["name"] != "Edge2" else "Edge",
+ "display": info["display"],
+ "path": info["path"],
+ "url": info["url"]
+ })
+ used.add(info["name"])
+ write_log(f"탐지된 브라우저: {browser_list}")
+ return browser_list
+
+def open_browser_extensions(browser):
+ try:
+ write_log(f"{browser['name']} 확장 프로그램 설정페이지 오픈 시도")
+ if browser["name"] == "Chrome":
+ is_running = any('chrome.exe' in (p.name().lower() if hasattr(p, "name") else "") for p in psutil.process_iter())
+ write_log(f"크롬 실행중 여부: {is_running}")
+ if not is_running:
+ subprocess.Popen([browser["path"], "--new-window", "chrome://extensions/"])
+ write_log("크롬 확장페이지 새창으로 오픈")
+ else:
+ msg = ("크롬이 이미 실행중입니다!\n\n"
+ "주소창에 chrome://extensions/ 를 직접 입력하세요.")
+ QMessageBox.information(None, "수동 안내", msg)
+ write_log("크롬 실행중: 수동 안내")
+ elif browser["name"] == "Whale":
+ subprocess.Popen([browser["path"], "--new-window", "whale://extensions"])
+ write_log("웨일 확장페이지 새창으로 오픈")
+ elif browser["name"] == "Edge":
+ subprocess.Popen([browser["path"], "--new-window", "edge://extensions"])
+ write_log("엣지 확장페이지 새창으로 오픈")
+ else:
+ os.startfile(browser["path"])
+ write_log(f"{browser['name']} 실행")
+ except Exception:
+ write_log(f"{browser['name']} 확장 프로그램 페이지 오픈 중 오류", exc_info=True)
+
+class ExtensionInstaller(QWidget):
+ def __init__(self):
+ super().__init__()
+ write_log("프로그램 시작")
+ self.setWindowTitle("🧩 크롬/웨일/엣지 확장 자동설치 마법사")
+ self.setMinimumSize(1100, 850) # 가로 900, 세로 700
+ self.setStyleSheet("""
+ QWidget { background: #20222B; color: #eef; font-size: 12px;}
+ QGroupBox { border: 2px solid #67c1f5; border-radius: 12px; margin-top: 14px; font-weight: bold; padding:13px; }
+ QPushButton { border-radius: 8px; background: #67c1f5; color: #181818; min-width: 130px; min-height: 44px; font-weight: bold; font-size: 12px; padding: 6px 16px;}
+ QPushButton:hover { background: #38b6ff; }
+ QLabel { font-size: 12px;}
+ QCheckBox { font-size: 12px;}
+ """)
+ try:
+ self.browsers = find_browsers()
+ except Exception:
+ self.browsers = []
+ write_log("브라우저 탐색 실패", exc_info=True)
+ self.install_paths = {}
+ self.init_ui()
+
+ def init_ui(self):
+ layout = QVBoxLayout()
+ layout.setSpacing(20)
+
+ title = QLabel("🧩 크롬/웨일/엣지 확장 자동설치 마법사")
+ title.setStyleSheet("font-size: 22px; font-weight: bold; color: #58b7ff; padding:20px 0 0 0")
+ layout.addWidget(title, alignment=Qt.AlignHCenter)
+
+ guide = QLabel(
+ "설치 안내:
"
+ "1. main.py와 같은 경로의 wrmc_ext 폴더가 자동 복사됩니다.
"
+ "2. 설치할 브라우저를 모두 체크 후 설치 시작을 누르세요.
"
+ "3. 설치 후 브라우저별 단계별 안내를 참고하세요.")
+ guide.setWordWrap(True)
+ guide.setStyleSheet("margin-bottom:12px;")
+ layout.addWidget(guide)
+
+ browser_group = QGroupBox("설치할 브라우저 선택")
+ browser_layout = QHBoxLayout()
+ self.checkboxs = []
+ for b in self.browsers:
+ cb = QCheckBox(f"{b['display']}")
+ cb.setChecked(False)
+ cb.setStyleSheet("margin-right:40px;")
+ cb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.checkboxs.append(cb)
+ browser_layout.addWidget(cb)
+ browser_group.setLayout(browser_layout)
+ layout.addWidget(browser_group)
+
+ self.install_btn = QPushButton("🚀 설치 시작")
+ self.install_btn.setMinimumHeight(54)
+ self.install_btn.setStyleSheet("background:#38b6ff; color:#222; font-size:17px;")
+ self.install_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ self.install_btn.clicked.connect(self.do_install)
+ layout.addWidget(self.install_btn)
+
+ # 결과 부분 스크롤 지원(많이 길어질 경우)
+ self.scroll_area = QScrollArea()
+ self.scroll_area.setWidgetResizable(True)
+ self.result_group = QGroupBox("설치 완료 결과 (브라우저별 단계별 안내)")
+ self.result_group.setStyleSheet("QGroupBox { border: 2px solid #38b6ff; margin-top:18px; padding:24px; }")
+ self.result_layout = QVBoxLayout()
+ self.result_group.setLayout(self.result_layout)
+ self.result_group.hide()
+ self.scroll_area.setWidget(self.result_group)
+ layout.addWidget(self.scroll_area, stretch=1)
+
+ help_label = QLabel("※ 복사 버튼 클릭시 클립보드에 저장됩니다. 폴더 경로는 꼭 붙여넣기 해주세요.\n"
+ "※ 크롬이 이미 실행중이면 주소창에 직접 chrome://extensions/ 입력 필요.")
+ help_label.setStyleSheet("color:#bbffaa; font-size:12px; margin:10px 0 0 0;")
+ help_label.setWordWrap(True)
+ layout.addWidget(help_label)
+
+ self.setLayout(layout)
+
+ def do_install(self):
+ write_log("설치 버튼 클릭")
+ DEVELOPER_MODE_GUIDE = {
+ "Chrome": "② 오른쪽 상단의 [개발자 모드]를 ON(체크)로 변경하세요.",
+ "Edge": "② 오른쪽 상단의 [개발자 모드]를 ON(체크)로 변경하세요.",
+ "Whale": "② 제일 하단의 [개발자 모드]를 ON(체크)로 변경하세요."
+ }
+ try:
+ checked = [cb.isChecked() for cb in self.checkboxs]
+ selected = [b for b, ch in zip(self.browsers, checked) if ch]
+ write_log(f"선택된 브라우저: {selected}")
+ if not selected:
+ QMessageBox.warning(self, "경고", "적어도 하나의 브라우저를 선택하세요.")
+ write_log("브라우저 미선택 - 경고")
+ return
+
+ ext_folder = get_resource_path("wrmc_ext")
+ write_log(f"wrmc_ext 폴더 경로: {ext_folder}")
+ if not os.path.exists(ext_folder):
+ QMessageBox.critical(self, "오류", f"확장 프로그램 폴더가 없습니다:\n{ext_folder}")
+ write_log("wrmc_ext 폴더 없음 - 오류")
+ return
+
+ self.install_paths = {}
+ for b in selected:
+ base_dir = get_install_base_dir()
+ os.makedirs(base_dir, exist_ok=True)
+ folder_name = f"{b['name'].lower()}_extension"
+ target_dir = os.path.join(base_dir, folder_name)
+ try:
+ if os.path.exists(target_dir):
+ shutil.rmtree(target_dir)
+ write_log(f"{b['name']} 기존 폴더 삭제: {target_dir}")
+ shutil.copytree(ext_folder, target_dir)
+ self.install_paths[b['name']] = target_dir
+ write_log(f"{b['name']} 확장 폴더 복사 완료: {target_dir}")
+ except Exception as e:
+ QMessageBox.critical(self, "오류", f"{b['name']} 설치 폴더 복사 실패: {e}")
+ write_log(f"{b['name']} 설치 폴더 복사 실패", exc_info=True)
+ return
+
+ while self.result_layout.count():
+ item = self.result_layout.takeAt(0)
+ widget = item.widget()
+ if widget is not None:
+ widget.deleteLater()
+
+ # 단계별 안내(글자 안잘리도록, Expanding 적용, WordWrap, padding/여백 강화)
+ for b in selected:
+ browser_name = b['name']
+ browser_disp = b['display']
+ path = self.install_paths.get(browser_name, '')
+ url = b['url']
+ box = QGroupBox(f"{browser_disp} 단계별 안내")
+ box.setStyleSheet("QGroupBox {margin-bottom:24px;}")
+ box_layout = QVBoxLayout()
+ box_layout.setSpacing(18)
+ # 1번 확장주소 복사
+ row1 = QHBoxLayout()
+ lbl1 = QLabel("① 확장설정 페이지로 이동 :")
+ lbl1.setWordWrap(True)
+ lbl1.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
+ url_btn = QPushButton("확장주소 복사")
+ url_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ url_btn.setMinimumWidth(160)
+ url_lbl = QLabel(url)
+ url_lbl.setStyleSheet("color:#5be0ff; font-weight:bold;")
+ url_lbl.setTextInteractionFlags(Qt.TextSelectableByMouse)
+ url_lbl.setWordWrap(True)
+ url_lbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
+ row1.addWidget(lbl1)
+ row1.addWidget(url_btn)
+ row1.addWidget(url_lbl)
+ row1.addStretch()
+ # 2번 개발자모드 체크
+ row2 = QLabel(DEVELOPER_MODE_GUIDE.get(browser_name, "② [개발자 모드] 위치를 찾아 ON(체크)로 변경하세요."))
+ row2.setTextFormat(Qt.RichText)
+ row2.setWordWrap(True)
+ # 3번 압축해제된 확장프로그램 로드
+ row3 = QLabel("③ [압축해제된 확장 프로그램 로드] 버튼 클릭")
+ row3.setTextFormat(Qt.RichText)
+ row3.setWordWrap(True)
+ # 4번 폴더 선택 및 복사
+ row4 = QHBoxLayout()
+ lbl4 = QLabel("④ 아래 폴더 경로 복사→ [폴더 선택]에 붙여넣기 -> 아무것도 안나오지만 선택버튼 클릭")
+ lbl4.setWordWrap(True)
+ lbl4.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
+ path_btn = QPushButton("폴더 경로 복사")
+ path_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ path_btn.setMinimumWidth(160)
+ path_lbl = QLabel(path)
+ path_lbl.setStyleSheet("color:#eaff86; font-weight:bold;")
+ path_lbl.setTextInteractionFlags(Qt.TextSelectableByMouse)
+ path_lbl.setWordWrap(True)
+ path_lbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
+ # 5번 확장프로그램 아이콘을 클릭하여 로그인
+ row5 = QLabel("⑤ 주소창 옆 확장프로그램 아이콘을 클릭하여 로그인")
+ row5.setTextFormat(Qt.RichText)
+ row5.setWordWrap(True)
+
+ row4.addWidget(lbl4)
+ row4.addWidget(path_btn)
+ row4.addWidget(path_lbl)
+ row4.addStretch()
+
+ url_btn.clicked.connect(lambda checked, u=url: self.copy_to_clipboard(u, "확장주소"))
+ path_btn.clicked.connect(lambda checked, p=path: self.copy_to_clipboard(p, "폴더 경로"))
+
+ box_layout.addLayout(row1)
+ box_layout.addWidget(row2)
+ box_layout.addWidget(row3)
+ box_layout.addLayout(row4)
+ box_layout.addWidget(row5)
+ box.setLayout(box_layout)
+ self.result_layout.addWidget(box)
+
+ self.result_group.show()
+ write_log("결과 UI 표시 완료")
+
+ for b in selected:
+ open_browser_extensions(b)
+
+ msg = (
+ "설치가 완료되었습니다!\n\n"
+ "브라우저별로 ①~④ 단계대로 진행하세요.\n"
+ "※ 크롬이 이미 실행중이면 주소창에 직접 chrome://extensions/ 입력 필요!"
+ )
+ QMessageBox.information(self, "설치 안내", msg)
+ write_log("설치 안내 메시지 표시")
+
+ except Exception:
+ write_log("설치 프로세스 전체 예외 발생", exc_info=True)
+ QMessageBox.critical(self, "오류", "예상치 못한 오류가 발생했습니다. log.txt를 확인해 주세요.")
+
+ def copy_to_clipboard(self, value, kind):
+ try:
+ clipboard = QApplication.clipboard()
+ clipboard.setText(value, QClipboard.Clipboard)
+ write_log(f"{kind} 복사: {value}")
+ QMessageBox.information(self, "복사 완료", f"{kind}가 클립보드에 복사되었습니다:\n{value}")
+ except Exception:
+ write_log(f"{kind} 복사 함수 예외", exc_info=True)
+ QMessageBox.critical(self, "오류", f"{kind} 복사 중 오류가 발생했습니다.")
+
+if __name__ == "__main__":
+ try:
+ if not is_admin():
+ QMessageBox.critical(None, "권한 부족", "이 프로그램은 관리자 권한으로 실행해야 할 수 있습니다.\n(브라우저 접근/복사 등)")
+ write_log("관리자 권한이 아님 - 재실행")
+ if getattr(sys, 'frozen', False):
+ script_path = sys.argv[0]
+ else:
+ script_path = os.path.abspath(__file__)
+ ctypes.windll.shell32.ShellExecuteW(
+ None, "runas", sys.executable, f'"{script_path}"', None, 1)
+ sys.exit(0)
+
+ app = QApplication(sys.argv)
+ window = ExtensionInstaller()
+ window.show()
+ sys.exit(app.exec())
+ except Exception:
+ write_log("메인 루프 전체 예외", exc_info=True)
+ raise
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..8d9ac70
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+pyside6
+psutil
diff --git a/wrmc_ext/background.js b/wrmc_ext/background.js
new file mode 100644
index 0000000..9c53e72
--- /dev/null
+++ b/wrmc_ext/background.js
@@ -0,0 +1,2427 @@
+// background.js (Service Worker)
+
+chrome.runtime.onInstalled.addListener(() => {
+ // 컨텍스트 메뉴를 개별적으로 생성 (단축키 포함)
+ chrome.contextMenus.create({
+ id: "searchTrademark",
+ title: "지재권 검색 (Ctrl+Shift+S)",
+ contexts: ["selection"]
+ });
+
+ chrome.contextMenus.create({
+ id: "multiTranslate",
+ title: "멀티번역 (Ctrl+Shift+E)",
+ contexts: ["selection"]
+ });
+
+ chrome.alarms.create("keepAlive", { periodInMinutes: 4 });
+
+ // 새 어록 감지 알람 생성 (1분마다)
+ chrome.alarms.create("checkNewSayings", { periodInMinutes: 1 });
+
+ // 초기 마지막 확인 시간 설정
+ chrome.storage.local.set({ lastSayingsCheck: Date.now() });
+});
+
+// 단축키 명령어 처리
+chrome.commands.onCommand.addListener(async (command) => {
+ console.log(`[background.js] 단축키 명령어 실행: ${command}`);
+
+ try {
+ // 현재 활성 탭 가져오기
+ const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
+ if (!tab) {
+ console.error('[background.js] 활성 탭을 찾을 수 없습니다');
+ return;
+ }
+
+ // 선택된 텍스트 가져오기
+ const results = await chrome.scripting.executeScript({
+ target: { tabId: tab.id },
+ function: () => {
+ return window.getSelection().toString().trim();
+ }
+ });
+
+ const selectedText = results[0]?.result;
+ if (!selectedText) {
+ chrome.notifications.create({
+ type: 'basic',
+ iconUrl: 'icon.png',
+ title: '텍스트 선택 필요',
+ message: '먼저 텍스트를 선택해주세요.'
+ });
+ return;
+ }
+
+ // Content script 준비 확인
+ await ensureContentScriptReady(tab.id);
+
+ // 명령어에 따른 처리
+ if (command === 'trademark-search') {
+ // 로딩 인디케이터 표시
+ try {
+ await chrome.tabs.sendMessage(tab.id, {
+ action: "showLoading",
+ message: `🔄 "${selectedText.substring(0, 20)}${selectedText.length > 20 ? '...' : ''}" 지재권 검색 중...`
+ });
+ } catch (loadingError) {
+ console.log('[단축키-지재권검색] 로딩 인디케이터 표시 실패 (무시):', loadingError.message);
+ }
+
+ await handleTrademarkSearch(selectedText, tab);
+
+ // 로딩 인디케이터 제거
+ try {
+ await chrome.tabs.sendMessage(tab.id, { action: "hideLoading" });
+ } catch (e) {
+ console.log('[단축키-지재권검색] 로딩 인디케이터 제거 실패 (무시):', e.message);
+ }
+
+ } else if (command === 'multi-translate') {
+ // 로딩 인디케이터 표시
+ try {
+ await chrome.tabs.sendMessage(tab.id, {
+ action: "showLoading",
+ message: `🔄 "${selectedText.substring(0, 20)}${selectedText.length > 20 ? '...' : ''}" 번역 중...`
+ });
+ } catch (loadingError) {
+ console.log('[단축키-멀티번역] 로딩 인디케이터 표시 실패 (무시):', loadingError.message);
+ }
+
+ await handleMultiTranslate({ selectionText: selectedText });
+
+ // 로딩 인디케이터 제거
+ try {
+ await chrome.tabs.sendMessage(tab.id, { action: "hideLoading" });
+ } catch (e) {
+ console.log('[단축키-멀티번역] 로딩 인디케이터 제거 실패 (무시):', e.message);
+ }
+
+ } else if (command === 'korean-to-chinese') {
+ await handleKoreanToChinese(selectedText, tab);
+ }
+
+ } catch (error) {
+ console.error(`[background.js] 단축키 처리 중 오류:`, error);
+ chrome.notifications.create({
+ type: 'basic',
+ iconUrl: 'icon.png',
+ title: '오류 발생',
+ message: '단축키 처리 중 문제가 발생했습니다.'
+ });
+ }
+});
+
+chrome.alarms.onAlarm.addListener((alarm) => {
+ if (alarm.name === "keepAlive") {
+ console.log("[background.js] 서비스 워커 유지 알람 실행됨");
+ } else if (alarm.name === "checkNewSayings") {
+ checkForNewSayings();
+ }
+});
+
+// 새 어록 확인 함수
+async function checkForNewSayings() {
+ try {
+ console.log("[background.js] 새 어록 확인 시작");
+
+ // Chrome 확장 프로그램 컨텍스트 확인
+ if (!chrome || !chrome.storage || !chrome.storage.local) {
+ console.error("[background.js] Chrome 확장 프로그램 API에 접근할 수 없습니다.");
+ return;
+ }
+
+ // 마지막 확인 시간 가져오기 (안전한 방식)
+ let lastSayingsCheck;
+ try {
+ const result = await chrome.storage.local.get("lastSayingsCheck");
+ lastSayingsCheck = result.lastSayingsCheck;
+ } catch (storageError) {
+ console.error("[background.js] 스토리지 접근 오류:", storageError);
+ lastSayingsCheck = Date.now() - 60000; // 기본값: 1분 전
+ }
+
+ const lastCheckTime = lastSayingsCheck || Date.now() - 60000;
+
+ // 액세스 토큰 가져오기 (안전한 방식)
+ let access_token;
+ try {
+ const result = await chrome.storage.local.get("access_token");
+ access_token = result.access_token;
+ } catch (storageError) {
+ console.error("[background.js] 토큰 스토리지 접근 오류:", storageError);
+ return;
+ }
+
+ if (!access_token) {
+ console.log("[background.js] 액세스 토큰이 없어 새 어록 확인을 건너뜁니다.");
+ return;
+ }
+
+ // 올바른 Supabase URL과 헤더 사용
+ const SUPABASE_URL = "http://146.56.101.199:8000";
+ const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE";
+
+ // 새 어록 API 호출
+ const apiUrl = `${SUPABASE_URL}/rest/v1/tanya_sayings?select=*,sayings_cat(saying_cat),sayings_target(target)&created_at=gte.${new Date(lastCheckTime).toISOString()}&admin_approval=eq.true&order=created_at.desc`;
+
+ console.log("[background.js] API 호출:", apiUrl);
+
+ const response = await fetch(apiUrl, {
+ method: 'GET',
+ headers: {
+ 'apikey': SUPABASE_ANON_KEY,
+ 'Authorization': `Bearer ${access_token}`,
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (response.ok) {
+ const newSayings = await response.json();
+
+ if (newSayings && newSayings.length > 0) {
+ console.log(`[background.js] ${newSayings.length}개의 새 어록을 발견했습니다.`);
+
+ // 브라우저 알림 표시 (안전한 방식)
+ try {
+ if (chrome.notifications) {
+ chrome.notifications.create('newSayings', {
+ type: 'basic',
+ iconUrl: 'icon.png',
+ title: '새 어록 알림',
+ message: `${newSayings.length}개의 새로운 어록이 등록되었습니다.`,
+ buttons: [
+ { title: '확인하기' },
+ { title: '나중에' }
+ ]
+ });
+ }
+ } catch (notificationError) {
+ console.error("[background.js] 알림 생성 오류:", notificationError);
+ }
+
+ // 새 어록 데이터를 스토리지에 저장 (안전한 방식)
+ try {
+ await chrome.storage.local.set({
+ pendingNewSayings: newSayings,
+ hasNewSayings: true
+ });
+ console.log("[background.js] 새 어록 데이터 스토리지 저장 완료");
+ } catch (storageError) {
+ console.error("[background.js] 새 어록 데이터 저장 오류:", storageError);
+ }
+ } else {
+ console.log("[background.js] 새 어록이 없습니다.");
+ }
+
+ // 마지막 확인 시간 업데이트 (안전한 방식)
+ try {
+ await chrome.storage.local.set({ lastSayingsCheck: Date.now() });
+ console.log("[background.js] 마지막 확인 시간 업데이트 완료");
+ } catch (storageError) {
+ console.error("[background.js] 마지막 확인 시간 업데이트 오류:", storageError);
+ }
+
+ } else {
+ const errorText = await response.text();
+ console.error("[background.js] 새 어록 확인 실패:", response.status, response.statusText, errorText);
+ }
+
+ } catch (error) {
+ console.error("[background.js] 새 어록 확인 중 전체 오류:", error);
+
+ // 오류 유형별 처리
+ if (error.message.includes('Could not establish connection')) {
+ console.error("[background.js] Chrome 확장 프로그램 연결 오류 - 확장 프로그램을 다시 로드하세요.");
+ } else if (error.message.includes('Receiving end does not exist')) {
+ console.error("[background.js] 메시지 수신자가 존재하지 않음 - 페이지를 새로고침하세요.");
+ } else if (error.name === 'TypeError' && error.message.includes('fetch')) {
+ console.error("[background.js] 네트워크 연결 오류 - 서버 연결을 확인하세요.");
+ }
+ }
+}
+
+// 알림 클릭 처리
+chrome.notifications.onClicked.addListener((notificationId) => {
+ if (notificationId === 'newSayings') {
+ // 어록 관리 페이지 열기
+ chrome.tabs.create({ url: chrome.runtime.getURL('sayings.html') });
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateLogin') {
+ // 로그인 필요 알림 클릭 시 팝업 열기
+ chrome.action.openPopup();
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateLimit') {
+ // API 한도 초과 알림 클릭 시 팝업 열기
+ chrome.action.openPopup();
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateUserInfo') {
+ // 사용자 정보 오류 알림 클릭 시 팝업 열기
+ chrome.action.openPopup();
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateError') {
+ // 번역 오류 알림 클릭 시 알림만 제거
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateBasic') {
+ // 기본 회원 안내 알림 클릭 시 알림만 제거
+ chrome.notifications.clear(notificationId);
+ } else if (notificationId === 'multiTranslateException') {
+ // 예외 오류 알림 클릭 시 알림만 제거
+ chrome.notifications.clear(notificationId);
+ }
+});
+
+// 알림 버튼 클릭 처리
+chrome.notifications.onButtonClicked.addListener((notificationId, buttonIndex) => {
+ if (notificationId === 'newSayings') {
+ if (buttonIndex === 0) { // 확인하기
+ chrome.tabs.create({ url: chrome.runtime.getURL('sayings.html') });
+ }
+ chrome.notifications.clear(notificationId);
+ }
+});
+
+// 컨텍스트 메뉴 클릭 시 처리
+chrome.contextMenus.onClicked.addListener(async (info, tab) => {
+ const keyword = info.selectionText.trim();
+ if (!keyword) return;
+
+ // 지재권 검색 처리
+ if (info.menuItemId === "searchTrademark") {
+ try {
+ // Content script 준비 확인
+ await ensureContentScriptReady(tab.id);
+
+ // 로딩 인디케이터 표시
+ await chrome.tabs.sendMessage(tab.id, {
+ action: "showLoading",
+ message: `🔄 "${keyword.substring(0, 20)}${keyword.length > 20 ? '...' : ''}" 지재권 검색 중...`
+ });
+ } catch (loadingError) {
+ console.log('[지재권 검색] 로딩 인디케이터 표시 실패 (무시):', loadingError.message);
+ }
+
+ await handleTrademarkSearch(keyword, tab);
+
+ // 로딩 인디케이터 제거
+ try {
+ await chrome.tabs.sendMessage(tab.id, { action: "hideLoading" });
+ } catch (e) {
+ console.log('[지재권 검색] 로딩 인디케이터 제거 실패 (무시):', e.message);
+ }
+ }
+
+ // 멀티번역 처리
+ if (info.menuItemId === "multiTranslate") {
+ try {
+ // Content script 준비 확인
+ await ensureContentScriptReady(tab.id);
+
+ // 로딩 인디케이터 표시
+ await chrome.tabs.sendMessage(tab.id, {
+ action: "showLoading",
+ message: `🔄 "${keyword.substring(0, 20)}${keyword.length > 20 ? '...' : ''}" 번역 중...`
+ });
+ } catch (loadingError) {
+ console.log('[멀티번역] 로딩 인디케이터 표시 실패 (무시):', loadingError.message);
+ }
+
+ await handleMultiTranslate(info);
+
+ // 로딩 인디케이터 제거
+ try {
+ await chrome.tabs.sendMessage(tab.id, { action: "hideLoading" });
+ } catch (e) {
+ console.log('[멀티번역] 로딩 인디케이터 제거 실패 (무시):', e.message);
+ }
+ }
+});
+
+// 기존 지재권 검색 함수로 분리
+async function handleTrademarkSearch(keyword, tab) {
+ try {
+ // 1. 토큰 확인
+ const { access_token } = await chrome.storage.local.get("access_token");
+ if (!access_token) {
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "로그인 필요",
+ message: "지재권 검색을 사용하려면 먼저 로그인하세요."
+ });
+ return;
+ }
+
+ // 2. API 호출량 증가 및 한도 확인
+ console.log('[지재권 검색] API 호출량 확인 시작');
+ const apiCallResult = await incrementApiCallsAndCheckLimit();
+
+ if (!apiCallResult.success) {
+ console.error('[지재권 검색] API 호출량 한도 초과:', apiCallResult.error);
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "API 호출 한도 초과",
+ message: apiCallResult.error
+ });
+ return;
+ }
+
+ console.log('[지재권 검색] API 호출량 확인 완료:', {
+ current: apiCallResult.current,
+ limit: apiCallResult.limit,
+ remaining: apiCallResult.remaining
+ });
+
+ // 3. 사용자 정보 및 회원등급 확인
+ const SUPABASE_URL = "http://146.56.101.199:8000";
+ const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE";
+
+ // 사용자 기본 정보 가져오기 (토큰 검증)
+ const authUrl = `${SUPABASE_URL}/auth/v1/user`;
+ const authRes = await fetch(authUrl, {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ apikey: SUPABASE_ANON_KEY,
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!authRes.ok) {
+ const errorText = await authRes.text();
+ console.error("[지재권 검색] 토큰 검증 실패:", authRes.status, errorText);
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "인증 오류",
+ message: "세션이 만료되었습니다. 다시 로그인해주세요."
+ });
+ return;
+ }
+
+ const authUser = await authRes.json();
+ console.log("[지재권 검색] 사용자 인증 성공:", authUser.email);
+
+ // 사용자 상세 정보 및 회원등급 확인 (users 테이블에서 직접 조회)
+ const detailsUrl = `${SUPABASE_URL}/rest/v1/users?select=*&email=eq.${encodeURIComponent(authUser.email)}&limit=1`;
+ const detailsRes = await fetch(detailsUrl, {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ apikey: SUPABASE_ANON_KEY,
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (!detailsRes.ok) {
+ const errorText = await detailsRes.text();
+ console.error("[지재권 검색] 사용자 정보 조회 실패:", detailsRes.status, errorText);
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "사용자 정보 오류",
+ message: "사용자 정보를 가져올 수 없습니다."
+ });
+ return;
+ }
+
+ const detailsData = await detailsRes.json();
+ const userDetails = detailsData[0];
+
+ if (!userDetails) {
+ console.error("[지재권 검색] 사용자 정보 없음");
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "사용자 정보 없음",
+ message: "사용자 정보를 찾을 수 없습니다."
+ });
+ return;
+ }
+
+ // 4. 회원등급 확인 (premium, vip만 허용)
+ const membershipLevel = userDetails.membership_level;
+ console.log("[지재권 검색] 사용자 회원등급:", membershipLevel);
+
+ // premium 또는 vip가 아닌 경우 접근 거부
+ if (!membershipLevel || (membershipLevel !== 'premium' && membershipLevel !== 'vip')) {
+ chrome.notifications.create({
+ type: "basic",
+ iconUrl: "icon.png",
+ title: "권한 부족",
+ message: `지재권 검색은 프리미엄/VIP 회원만 사용할 수 있습니다.\n현재 등급: ${membershipLevel || '기본'}`
+ });
+ return;
+ }
+
+ // 5. 권한이 있는 경우 지재권 검색 실행
+ console.log(`[지재권 검색] 사용자: ${authUser.email}, 등급: ${membershipLevel}, 키워드: ${keyword}, API 호출: ${apiCallResult.current}/${apiCallResult.limit}`);
+
+ const url = buildMarkInfoUrl(keyword);
+
+ // 키워드 검색 실행
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error(`네트워크 오류: ${response.status}`);
+ }
+
+ const html = await response.text();
+ const match = /
+