Compare commits

..
3 Commits
Author SHA1 Message Date
KINDNICKandClaude Opus 4.7 d3a4efc173 v2.3.3: fix Discord webhook always failing (Cloudflare blocks Python UA)
Cloudflare protects Discord webhook endpoints and rejects requests
with the default Python urllib User-Agent ('Python-urllib/3.x') with
HTTP 403 + 'error code 1010'. Add a browser-like User-Agent header
to the request.

The onboarding wizard's 'Send Test Message' button (and clock-in/out
push messages) now succeed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 18:23:51 +09:00
KINDNICKandClaude Opus 4.7 86cf438785 v2.3.2: fix HelpView showing blank window (regression in v2.3.1)
In v2.3.1 the new 'Re-run Onboarding' button was added but the
self.setLayout(main_layout) line was accidentally indented into the
new _reopen_onboarding method body, so init_ui returned without
applying the layout. Result: F1 opened an empty dialog with no tabs.

Move setLayout back to the end of init_ui.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 18:12:51 +09:00
KINDNICKandClaude Opus 4.7 fc5184ae07 v2.3.1: add 'Re-run Onboarding' button to Help dialog
v2.3.0 had show_onboarding() method but no UI entry point. Existing
users couldn't reach the wizard since auto-migration marks them done.
Now Help dialog (F1) has a button to re-trigger the wizard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 18:07:57 +09:00
4 changed files with 50 additions and 3 deletions
+27
View File
@@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [2.3.3] — 2026-04-30
### Fixed
- **Discord 웹훅 항상 실패하던 문제** (Cloudflare error 1010 / 403 Forbidden)
- 원인: Python 기본 User-Agent(`Python-urllib/3.x`)를 Discord/Cloudflare가
봇으로 인식해 차단
- 수정: `utils/discord_webhook.py`에 브라우저 UA 헤더 추가
(`Mozilla/5.0 (Windows NT 10.0; Win64; x64) ClockOutCalculator/2.3`)
- 이제 온보딩 위저드의 "테스트 메시지 보내기" + 출퇴근/휴식 push 모두 정상 동작
## [2.3.2] — 2026-04-30
### Fixed
- **도움말 다이얼로그가 빈 창으로 표시되던 치명적 버그**
- v2.3.1에서 "온보딩 다시 보기" 버튼 추가 시 `self.setLayout(main_layout)` 라인이
실수로 `_reopen_onboarding` 메서드 안으로 들여쓰기되어 init_ui가 setLayout 없이 종료
- F1 누르면 빈 화면만 나옴 (탭 6개 모두 미렌더링)
- setLayout 호출 위치 복원 → 정상 표시
## [2.3.1] — 2026-04-30
### Fixed
- **도움말 다이얼로그에 "온보딩 다시 보기" 버튼 추가**
- v2.3.0에서 `show_onboarding()` 메서드는 만들었지만 UI 진입점 누락
- 이제 도움말 (F1) → 좌측 하단 "🚀 온보딩 다시 보기" 버튼으로 위저드 재실행 가능
- 본인 검증/설정 변경 시 유용
## [2.3.0] — 2026-04-30 ## [2.3.0] — 2026-04-30
### Added — Phase 1 + E1 (소비자 친화 6종) ### Added — Phase 1 + E1 (소비자 친화 6종)
+1 -1
View File
@@ -4,4 +4,4 @@
릴리스 시 이 값을 올린 후 git tag → push. 릴리스 시 이 값을 올린 후 git tag → push.
CHANGELOG.md의 최상단 항목과 일치시킬 것. CHANGELOG.md의 최상단 항목과 일치시킬 것.
""" """
__version__ = '2.3.0' __version__ = '2.3.3'
+14 -1
View File
@@ -51,18 +51,31 @@ class HelpView(QDialog):
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setContentsMargins(20, 10, 20, 20) button_layout.setContentsMargins(20, 10, 20, 20)
# 온보딩 다시 보기 (왼쪽)
onboarding_button = QPushButton("🚀 온보딩 다시 보기")
onboarding_button.setMinimumHeight(40)
onboarding_button.clicked.connect(self._reopen_onboarding)
button_layout.addWidget(onboarding_button)
button_layout.addStretch() button_layout.addStretch()
close_button = QPushButton(tr('btn.close')) close_button = QPushButton(tr('btn.close'))
close_button.setObjectName("btn_primary") close_button.setObjectName("btn_primary")
close_button.setMinimumHeight(40) close_button.setMinimumHeight(40)
close_button.setMinimumWidth(120) close_button.setMinimumWidth(120)
close_button.clicked.connect(self.close) close_button.clicked.connect(self.close)
button_layout.addWidget(close_button) button_layout.addWidget(close_button)
button_layout.addStretch()
main_layout.addLayout(button_layout) main_layout.addLayout(button_layout)
self.setLayout(main_layout) self.setLayout(main_layout)
def _reopen_onboarding(self):
"""부모 윈도우의 show_onboarding 호출 후 도움말 닫음."""
self.close()
if self.parent() and hasattr(self.parent(), 'show_onboarding'):
self.parent().show_onboarding()
def _make_tab(self, html: str) -> QWidget: def _make_tab(self, html: str) -> QWidget:
container = QWidget() container = QWidget()
layout = QVBoxLayout() layout = QVBoxLayout()
+8 -1
View File
@@ -10,6 +10,10 @@ import urllib.error
from datetime import datetime from datetime import datetime
from typing import Optional, List from typing import Optional, List
# Discord/Cloudflare는 Python 기본 UA(Python-urllib/3.x)를 봇으로 차단(error 1010).
# 일반 브라우저 UA로 위장해야 통과.
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ClockOutCalculator/2.3'
# Discord embed 색상 (decimal) # Discord embed 색상 (decimal)
COLOR_GREEN = 0x57F287 COLOR_GREEN = 0x57F287
COLOR_BLUE = 0x5865F2 COLOR_BLUE = 0x5865F2
@@ -49,7 +53,10 @@ def send(webhook_url: str, title: str, description: str,
data = json.dumps(payload, ensure_ascii=False).encode('utf-8') data = json.dumps(payload, ensure_ascii=False).encode('utf-8')
req = urllib.request.Request( req = urllib.request.Request(
webhook_url, data=data, webhook_url, data=data,
headers={'Content-Type': 'application/json; charset=utf-8'}, headers={
'Content-Type': 'application/json; charset=utf-8',
'User-Agent': USER_AGENT,
},
method='POST', method='POST',
) )
try: try: