fix(anime): batch_download list crash + title 오분류 fallback 수정
This commit is contained in:
@@ -123,3 +123,15 @@
|
|||||||
- **원인**: 존재하지 않는 함수명으로 import (실제: `handle_anime_message`)
|
- **원인**: 존재하지 않는 함수명으로 import (실제: `handle_anime_message`)
|
||||||
- **해결**: import 수정 + 시그니처 확인 `(message, parsed)`
|
- **해결**: import 수정 + 시그니처 확인 `(message, parsed)`
|
||||||
- **주의**: 핸들러 연결 시 반드시 실제 모듈의 함수명/시그니처 확인 후 코드 작성
|
- **주의**: 핸들러 연결 시 반드시 실제 모듈의 함수명/시그니처 확인 후 코드 작성
|
||||||
|
|
||||||
|
### [2026-03-18] anime_handler — batch_download list 반환값 crash
|
||||||
|
- **증상**: title 없이 배치 다운로드 시 `AttributeError: 'list' object has no attribute 'message'`
|
||||||
|
- **원인**: `batch_download()`는 `list[DownloadResult]`를 반환하지만, 렌더링 코드가 단일 `result.message` 접근
|
||||||
|
- **해결**: `isinstance(result, list)` 체크 추가 → list면 합산 Embed 렌더링
|
||||||
|
- **주의**: pipeline 메서드 반환 타입을 반드시 확인하고 handler에서 처리할 것
|
||||||
|
|
||||||
|
### [2026-03-18] anime_handler — NLU title에 범위 한정자 진입
|
||||||
|
- **증상**: "이번분기 애니 업데이트" → `title="이번분기"` → `download("이번분기")` → "검색 결과가 없습니다"
|
||||||
|
- **원인**: handler line 90이 `title` truthy면 무조건 단건 다운로드. title 유효성 검증 없음
|
||||||
|
- **해결**: `download()` resolve 실패 + episode 미지정 시 `batch_download()` fallback 추가
|
||||||
|
- **주의**: AI NLU 출력을 무비판적으로 신뢰하지 말 것. 코드에서 반드시 방어적 검증 필요
|
||||||
|
|||||||
@@ -13,3 +13,4 @@
|
|||||||
| 011 | 19:40 | anime 분류 정확도 강화 (6/6 테스트 통과) | `77bd211` | ✅ |
|
| 011 | 19:40 | anime 분류 정확도 강화 (6/6 테스트 통과) | `77bd211` | ✅ |
|
||||||
| 012 | 19:45 | Foreman E2E 테스트 (분해→수정→Vikunja 등록) | `489755f` | ✅ |
|
| 012 | 19:45 | Foreman E2E 테스트 (분해→수정→Vikunja 등록) | `489755f` | ✅ |
|
||||||
| 013 | 21:35 | anime handler import 수정 + action 분기 완성 | `28ae0d5` | ✅ |
|
| 013 | 21:35 | anime handler import 수정 + action 분기 완성 | `28ae0d5` | ✅ |
|
||||||
|
| 014 | 22:40 | anime handler batch crash + title 오분류 수정 | - | ✅ |
|
||||||
|
|||||||
@@ -91,6 +91,12 @@ async def handle_anime_message(
|
|||||||
mode = parsed.get("download_mode", "auto")
|
mode = parsed.get("download_mode", "auto")
|
||||||
episode = parsed.get("episode")
|
episode = parsed.get("episode")
|
||||||
result = await pipeline.download(title, mode=mode, episode=episode)
|
result = await pipeline.download(title, mode=mode, episode=episode)
|
||||||
|
# resolve 실패 시 batch fallback (title이 애니 제목이 아닌 경우)
|
||||||
|
if not result.success and not episode:
|
||||||
|
logger.info(f"단건 resolve 실패 → 배치 fallback: '{title}'")
|
||||||
|
dl_filter = parsed.get("filter", "")
|
||||||
|
batch_mode = "sub_only" if "sub" in dl_filter else "auto"
|
||||||
|
result = await pipeline.batch_download(mode=batch_mode)
|
||||||
elif action == "download" and not title:
|
elif action == "download" and not title:
|
||||||
# 이번 분기 전체 다운로드 (자막 최신화 등)
|
# 이번 분기 전체 다운로드 (자막 최신화 등)
|
||||||
dl_filter = parsed.get("filter", "")
|
dl_filter = parsed.get("filter", "")
|
||||||
@@ -143,7 +149,22 @@ async def handle_anime_message(
|
|||||||
))
|
))
|
||||||
return
|
return
|
||||||
|
|
||||||
# 결과 임베드
|
# 결과 임베드 — batch_download는 list[DownloadResult] 반환
|
||||||
|
if isinstance(result, list):
|
||||||
|
successes = [r for r in result if r.success]
|
||||||
|
failures = [r for r in result if not r.success]
|
||||||
|
lines = []
|
||||||
|
for r in result:
|
||||||
|
icon = "✅" if r.success else "❌"
|
||||||
|
name = r.anime.subject if r.anime else "?"
|
||||||
|
lines.append(f"{icon} {name}: {r.message[:60]}")
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"📥 일괄 다운로드 ({len(successes)}/{len(result)}건 성공)",
|
||||||
|
description="\n".join(lines)[:2000] if lines else "처리 완료",
|
||||||
|
color=0x2ECC71 if not failures else 0xF39C12,
|
||||||
|
)
|
||||||
|
await safe_send_embed(message.channel, embed)
|
||||||
|
else:
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"🎬 {result.message[:100]}" if result.message else "🎬 결과",
|
title=f"🎬 {result.message[:100]}" if result.message else "🎬 결과",
|
||||||
description=result.message[:2000] if result.message else "완료",
|
description=result.message[:2000] if result.message else "완료",
|
||||||
|
|||||||
Reference in New Issue
Block a user