fix(tools): 애니 파이프라인 버그 4건 수정 — Unicode SyntaxError, 카타카나 변환, Nyaa 검색 전략 + Python 환경 설정
This commit is contained in:
@@ -49,6 +49,7 @@ description: 모든 작업에 자동 적용되는 에이전트 행동 규칙.
|
||||
|
||||
## PowerShell Notes
|
||||
|
||||
- **Python**: `C:\ProgramData\miniforge3\envs\gravity_web\python.exe` 사용 (시스템 `python` 대신)
|
||||
- `curl` → PowerShell에서 `Invoke-WebRequest` 별칭. **반드시 `curl.exe`** 사용
|
||||
- `npm` → 실행 정책 문제 시 `cmd /c npm` 사용
|
||||
- JSON 처리 시 `.py` 스크립트 권장 (PowerShell 이스케이핑 이슈 방지)
|
||||
|
||||
@@ -40,4 +40,20 @@
|
||||
|
||||
> 아래에 프로젝트 특화 이슈를 추가하세요.
|
||||
|
||||
(아직 기록된 프로젝트별 이슈가 없습니다)
|
||||
### [2026-03-08] nas_scanner docstring — Unicode escape SyntaxError
|
||||
- **증상**: `from tools.nas_scanner import NasScanner` 시 `SyntaxError: (unicode error) 'unicodeescape' codec can't decode \N`
|
||||
- **원인**: docstring 내 `\\NasData` 경로에서 `\N`이 Python Unicode named escape로 해석
|
||||
- **해결**: docstring을 `r"""..."""` (raw string)으로 변경
|
||||
- **주의**: Windows 경로(`\\`, `\N`, `\U` 등)가 포함된 docstring은 반드시 `r"""`로 작성
|
||||
|
||||
### [2026-03-08] title_matcher _kata_to_hira — 장음기호 깨짐
|
||||
- **증상**: `フリーレン` → `ふり゜れん` (ー가 ゜로 변환)
|
||||
- **원인**: 카타카나 범위 `0x30A0~0x30FF`에 기호 문자(`ー` U+30FC) 포함
|
||||
- **해결**: 범위를 `0x30A1~0x30F6`으로 좁혀 실제 문자만 변환
|
||||
- **주의**: 유니코드 범위 지정 시 기호/구두점 문자 포함 여부 확인 필수
|
||||
|
||||
### [2026-03-08] anime_pipeline — Nyaa 검색 0건 반환
|
||||
- **증상**: 한자 포함 원제의 로마자 변환 결과(`葬送nofuriren`) + suffix 고정으로 Nyaa 검색 실패
|
||||
- **원인**: 단일 검색 전략, suffix(ASW HEVC) 항상 부착
|
||||
- **해결**: 6단계 fallback 전략 (romaji±suffix → 원제±suffix → 한글±suffix)
|
||||
- **주의**: 외부 API 검색 시 반드시 다중 전략 + suffix 토글 구현
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
---
|
||||
---
|
||||
description: Gitea API로 저장소 커밋/이슈/PR 현황을 조회하는 워크플로우
|
||||
---
|
||||
|
||||
@@ -26,15 +26,15 @@ $issues | ForEach-Object { Write-Host "#$($_.number) $($_.title)" }
|
||||
|
||||
3. Wiki 페이지 목록:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\wiki_helper.py list
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\wiki_helper.py list
|
||||
```
|
||||
|
||||
4. Wiki 페이지 읽기:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\wiki_helper.py read "Architecture"
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\wiki_helper.py read "Architecture"
|
||||
```
|
||||
|
||||
5. Wiki 페이지 업데이트:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\wiki_helper.py update "페이지-제목" /tmp/wiki_content.md
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\wiki_helper.py update "페이지-제목" /tmp/wiki_content.md
|
||||
```
|
||||
|
||||
@@ -12,27 +12,27 @@ description: Vikunja API로 프로젝트 태스크 현황을 조회하는 워크
|
||||
|
||||
1. 전체 목록:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py list
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py list
|
||||
```
|
||||
|
||||
2. TODO만:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py list todo
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py list todo
|
||||
```
|
||||
|
||||
3. DONE만:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py list done
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py list done
|
||||
```
|
||||
|
||||
4. 태스크 완료 처리 (**⚠️ 반드시 이 방법 사용 — 직접 API 호출 금지**):
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py done {TASK_ID}
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py done {TASK_ID}
|
||||
```
|
||||
|
||||
5. 새 태스크 생성:
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:High
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:High
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
|
||||
@@ -87,9 +87,9 @@ git log --oneline -20
|
||||
|
||||
| 커밋 유형 | Vikunja 액션 |
|
||||
|-----------|-------------|
|
||||
| 기존 태스크 해당 작업 **완료** | `python .agents\workflows\helpers\vikunja_helper.py done {ID}` |
|
||||
| 신규 작업 완료 (기존 태스크 없음) | `python .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --done --labels Backend,Priority:High` |
|
||||
| 작업 중 발견된 **미완료 TODO** | `python .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:Mid` |
|
||||
| 기존 태스크 해당 작업 **완료** | `C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py done {ID}` |
|
||||
| 신규 작업 완료 (기존 태스크 없음) | `C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --done --labels Backend,Priority:High` |
|
||||
| 작업 중 발견된 **미완료 TODO** | `C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:Mid` |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 모든 커밋이 기존 또는 신규 태스크에 매핑되었는지 확인.
|
||||
@@ -97,13 +97,13 @@ git log --oneline -20
|
||||
### 2-2. 완료 처리
|
||||
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py done {TASK_ID}
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py done {TASK_ID}
|
||||
```
|
||||
|
||||
### 2-3. 신규 태스크 생성
|
||||
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:High
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --labels Backend,Priority:High
|
||||
```
|
||||
|
||||
### 라벨 규칙
|
||||
@@ -123,7 +123,7 @@ python .agents\workflows\helpers\vikunja_helper.py create "제목" "설명" --la
|
||||
| 새 모듈/패키지 추가 | Architecture |
|
||||
|
||||
```powershell
|
||||
python .agents\workflows\helpers\wiki_helper.py update "Architecture" /tmp/wiki_content.md
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\wiki_helper.py update "Architecture" /tmp/wiki_content.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -48,7 +48,7 @@ git log --oneline -5
|
||||
### 3. Vikunja TODO 태스크
|
||||
|
||||
```powershell
|
||||
python .agents\workflows\helpers\vikunja_helper.py list todo
|
||||
C:\ProgramData\miniforge3\envs\gravity_web\python.exe .agents\workflows\helpers\vikunja_helper.py list todo
|
||||
```
|
||||
|
||||
### 4. 종합 보고
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
| # | 시간 | 작업 | 커밋 | 상태 |
|
||||
|---|------|------|------|------|
|
||||
| 1 | 15:19~16:02 | 애니메이션 자동화 파이프라인 구현 (Anissia/Nyaa/qBit/자막다운로더/NAS스캐너 + AI 평문 통합) | `pending` | ✅ |
|
||||
| 1 | 15:19~16:02 | 애니메이션 자동화 파이프라인 구현 (Anissia/Nyaa/qBit/자막다운로더/NAS스캐너 + AI 평문 통합) | `c92433b` | ✅ |
|
||||
| 2 | 17:07~17:42 | 애니 파이프라인 검증 & 버그 4건 수정 (Unicode SyntaxError, 카타카나 변환, Nyaa 검색 전략) + Python 환경 설정 | `pending` | ✅ |
|
||||
|
||||
19
docs/devlog/entries/20260308-002.md
Normal file
19
docs/devlog/entries/20260308-002.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 애니 파이프라인 검증 & 버그 수정
|
||||
|
||||
- **시간**: 2026-03-08 17:07~17:42
|
||||
- **Commit**: `pending`
|
||||
|
||||
## 결정 사항
|
||||
|
||||
- **`_kata_to_hira` 범위 수정**: `0x30A0~0x30FF` 전체 → `0x30A1~0x30F6`(ア~ヶ만)으로 변경. ー(U+30FC)가 기호임에도 카타카나 범위에 포함되어 잘못 변환되는 문제. Unicode 블록을 범위로 사용할 때 기호 문자 포함 여부를 항상 확인해야 함.
|
||||
- **Nyaa 6단계 검색 전략**: romaji 변환은 한자 통과 특성상 순수 romaji만으로 검색 불가. suffix(ASW HEVC) 유무 조합으로 6가지 전략을 순차 시도. NyaaClient에 이미 `use_default_suffix` 파라미터가 있었으나 활용되지 않았음.
|
||||
- **Python 환경 고정**: 시스템 `python`이 작동하지 않아 `C:\ProgramData\miniforge3\envs\gravity_web\python.exe`를 AGENT.md + 6개 워크플로우에 명시.
|
||||
|
||||
## 수정 파일
|
||||
|
||||
- `tools/nas_scanner.py` — docstring `r"""` 변경
|
||||
- `tools/title_matcher.py` — `_kata_to_hira` 범위 + `japanese_to_romaji` 장음 처리
|
||||
- `tools/anime_pipeline.py` — Nyaa 6단계 검색 전략
|
||||
- `.agents/AGENT.md` — Python 경로 추가
|
||||
- `.agents/workflows/*.md` — Python 경로 일괄 변경 (6개 파일)
|
||||
- `.agents/references/known-issues.md` — 프로젝트 이슈 3건 추가
|
||||
@@ -81,16 +81,37 @@ class AnimePipeline:
|
||||
except Exception as e:
|
||||
result.errors.append(f"자막 조회 오류: {e}")
|
||||
|
||||
# 3. Nyaa 토렌트 검색 (원제 로마자로)
|
||||
# 3. Nyaa 토렌트 검색 (다중 전략 — suffix 있는/없는 조합)
|
||||
try:
|
||||
from tools.title_matcher import japanese_to_romaji
|
||||
romaji_title = japanese_to_romaji(anime.original_subject)
|
||||
import re as _re
|
||||
|
||||
# 먼저 로마자로 검색
|
||||
torrents = await self.nyaa.search(romaji_title)
|
||||
if not torrents:
|
||||
# 원제 그대로 검색
|
||||
torrents = await self.nyaa.search(anime.original_subject)
|
||||
romaji_full = japanese_to_romaji(anime.original_subject)
|
||||
# 한자/비ASCII 잔류 문자 제거 → 순수 로마자만 추출
|
||||
romaji_clean = _re.sub(r'[^\x00-\x7F]+', ' ', romaji_full).strip()
|
||||
romaji_clean = _re.sub(r'\s+', ' ', romaji_clean)
|
||||
|
||||
# 검색 전략 (query, use_default_suffix) 순서
|
||||
strategies: list[tuple[str, bool]] = []
|
||||
if romaji_clean and len(romaji_clean) >= 3:
|
||||
strategies.append((romaji_clean, True)) # romaji + ASW HEVC
|
||||
strategies.append((romaji_clean, False)) # romaji only
|
||||
strategies.append((anime.original_subject, True)) # 원제 + suffix
|
||||
strategies.append((anime.original_subject, False)) # 원제 only
|
||||
strategies.append((anime.subject, True)) # 한글 + suffix
|
||||
strategies.append((anime.subject, False)) # 한글 only
|
||||
|
||||
torrents = []
|
||||
for query, use_suffix in strategies:
|
||||
torrents = await self.nyaa.search(
|
||||
query, use_default_suffix=use_suffix,
|
||||
)
|
||||
if torrents:
|
||||
suffix_label = " +suffix" if use_suffix else ""
|
||||
logger.info(
|
||||
f"Nyaa 검색 성공: '{query}'{suffix_label} → {len(torrents)}건"
|
||||
)
|
||||
break
|
||||
|
||||
# 제목 매칭 필터링
|
||||
matched = match_titles(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""NAS 폴더 스캐너 — 다운로드된 애니 목록 + 파일 정보 조회.
|
||||
r"""NAS 폴더 스캐너 — 다운로드된 애니 목록 + 파일 정보 조회.
|
||||
|
||||
NAS Animation 폴더 구조:
|
||||
\\192.168.10.10\NasData\Video\Animation\
|
||||
|
||||
@@ -53,11 +53,12 @@ _KATA_OFFSET = ord('ア') - ord('あ')
|
||||
|
||||
|
||||
def _kata_to_hira(text: str) -> str:
|
||||
"""카타카나를 히라가나로 변환."""
|
||||
"""카타카나를 히라가나로 변환 (ー 장음기호는 유지)."""
|
||||
result = []
|
||||
for ch in text:
|
||||
cp = ord(ch)
|
||||
if 0x30A0 <= cp <= 0x30FF: # 카타카나 범위
|
||||
# 카타카나 범위이되, ー(U+30FC), ・(U+30FB) 등 기호는 제외
|
||||
if 0x30A1 <= cp <= 0x30F6: # ア~ヶ (실제 카타카나 문자만)
|
||||
result.append(chr(cp - _KATA_OFFSET))
|
||||
else:
|
||||
result.append(ch)
|
||||
@@ -71,6 +72,11 @@ def japanese_to_romaji(text: str) -> str:
|
||||
result = []
|
||||
i = 0
|
||||
while i < len(text):
|
||||
# 장음 기호 (ー U+30FC, ー가 히라가나로 안 변환되므로 여기서 처리)
|
||||
if text[i] == '\u30FC': # ー
|
||||
# 장음: 이전 모음 반복 (간략화: 스킵)
|
||||
i += 1
|
||||
continue
|
||||
# 2글자 매칭 우선 (きゃ 등)
|
||||
if i + 1 < len(text) and text[i:i+2] in _KANA_ROMAJI:
|
||||
result.append(_KANA_ROMAJI[text[i:i+2]])
|
||||
@@ -85,8 +91,6 @@ def japanese_to_romaji(text: str) -> str:
|
||||
else:
|
||||
result.append(romaji)
|
||||
i += 1
|
||||
elif text[i] == 'ー': # 장음
|
||||
i += 1
|
||||
else:
|
||||
# 한자, 영어, 숫자 등 → 그대로
|
||||
result.append(text[i])
|
||||
|
||||
@@ -49,5 +49,22 @@
|
||||
"project_id": 0
|
||||
},
|
||||
"docs_path": "docs/wiki"
|
||||
},
|
||||
"1480113683849023661": {
|
||||
"name": "variet-agent",
|
||||
"path": "c:\\Users\\Certes\\Desktop\\VW_Proj\\variet-agent",
|
||||
"channel_id": 1480113683849023661,
|
||||
"git": {
|
||||
"url": "",
|
||||
"token": "",
|
||||
"repo": "",
|
||||
"branch": "main"
|
||||
},
|
||||
"vikunja": {
|
||||
"url": "",
|
||||
"token": "",
|
||||
"project_id": 0
|
||||
},
|
||||
"docs_path": "docs/wiki"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user