Commit graph

647 commits

Author SHA1 Message Date
a11a027682 feat(admin-schedule): 일반 일정 생성/수정 라우트 추가 (컴백·팬사인회·기타)
전용 폼이 없는 단순 카테고리용 POST/PUT /admin/schedules 신규.
제목·날짜·시간·카테고리·멤버 + date_precision(월만=날짜 미정) 처리,
month이면 날짜를 해당 월 1일로 정규화. schedules + schedule_members
트랜잭션 + meili 동기화 + 월별 캐시 무효화. (앨범→컴백 카테고리 리네임 동반)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 21:58:57 +09:00
ad20149c88 feat(admin-schedule): 일정 추가 카테고리 선택에서 생일·기념일 제외
생일/기념일은 멤버 생일·데뷔일에서 자동 계산되는 카테고리라 수동 추가
대상이 아님. 카테고리 선택 목록과 기본 선택값에서 제외.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 21:40:19 +09:00
680ea46cd5 fix(festival-bot): 서술형 장소명 카카오맵 매칭 개선
Gemini가 추출한 서술형 장소명("캐리비안 베이 야외 파도풀 특설무대")이
카카오맵 검색에 안 걸려 좌표 없이 저장(장소 클릭 불가)되던 문제.
검색 실패 시 뒤 단어부터 줄이며 재시도하고, 축약 매칭 시 표시명은
원본 유지 + 좌표만 사용. 기존 2건(울산·캐리비안) 좌표 백필 완료.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 14:19:03 +09:00
5c31977411 fix(festival-bot): 한글 URL 디코딩으로 Gemini url_context 실패 해결
퍼센트 인코딩된 긴 한글 URL(%EC%BA%90...)을 Gemini가 도구 호출 시
잘못 복사해 fetch가 실패('URL 불일치')하고 no_event로 기록되던 문제
(캐리비안 베이 글 누락 원인). 스크래퍼가 URL을 한글로 디코딩해 전달하고
source_url 매칭도 디코딩 기준으로 정규화. 기존 크롤로그 24건 디코딩
마이그레이션 + 캐리비안 베이 재처리 → 7/4 일정 생성 확인.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 14:12:53 +09:00
f0eae805e6 docs(api): 축제 봇 통합(대학+일반) 반영, active_months 제거
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 14:04:42 +09:00
d1ee28e308 refactor(festival-bot): active_months 기능 제거
축제봇이 대학+일반 행사를 통합 수집하게 되면서 연중 실행이 필요해
활성 월 제한 기능 제거. 스케줄러 게이트/라우트/유틸/DB 컬럼/다이얼로그
월 선택 UI/'대기 중' 상태 표시 모두 정리. 동기화 간격만 유지.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 14:02:24 +09:00
73a008f4bc feat(festival-bot): 일반 행사(콘서트·페스티벌 등) 추출 통합
Gemini 프롬프트를 확장해 한 번의 호출로 대학 축제 + 일반 행사를 함께
추출(type 필드로 구분). 일반 행사는 행사명을 제목으로, venue로 카카오맵
검색, subtype 'general'(상세 페이지는 기존 '행사' 배지로 표시), 중복은
날짜+행사명(공백 무시 포함관계)으로 체크. 실제 게시글 2건으로 추출 검증.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 10:48:21 +09:00
734fc59bb2 fix(pc): 스크롤바 clickScroll을 'instant'로 — 커서 클릭점 어긋남에 둔감하게
사용자 환경에서 커서가 가리키는 지점과 실제 클릭 좌표가 수 px 어긋나
(maplestory에서도 동일 확인), 세로 8px 핸들을 조준해도 클릭이 핸들 밖
트랙에 떨어져 드래그가 간헐적으로 안 잡히던 문제. 'instant' 모드는
스크롤바 띠(14px) 어디를 눌러도 핸들이 그 위치로 즉시 점프하고 그대로
드래그가 이어져 정밀 조준이 불필요. ClickScrollPlugin은 불필요해져 제거.
헤드리스로 트랙 press→점프→연속 드래그 검증 완료.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 19:43:46 +09:00
3fef42aa6c fix(pc): OverlayScrollbars defer 제거 (간헐적 드래그 무반응)
defer는 초기화를 idle 콜백으로 미루고 그 사이를 CSS로 가리는데, 이때
스크롤바가 보이고 호버 색도 바뀌지만 드래그 리스너는 아직 없는 구간이
생김(React StrictMode 재마운트와 레이스 가능). 핸들을 잡아도 간헐적으로
안 끌리던 원인으로 추정. maplestory와 동일하게 동기 초기화로 변경.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 19:35:23 +09:00
6595d55532 fix(pc): 가로 스크롤바 잡기 어려운 문제 개선
핸들이 7px로 얇고 트랙 클릭(clickScroll)이 기본 꺼져 있어, 핸들을
2~3px 빗나가게 클릭하면 아무 반응이 없어 드래그가 안 되는 것처럼
느껴지던 문제. 스크롤바 14px/핸들 8px로 키우고 ClickScrollPlugin 등록 +
clickScroll 활성화로 트랙 클릭 시에도 스크롤되도록 변경.
헤드리스 브라우저로 핸들 드래그·트랙 클릭 동작 검증 완료.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 19:26:55 +09:00
e5f9ee70ea fix(pc): 헤더를 가로 스크롤 영역에 포함 (1440 미만 줄바꿈 해결)
min-width를 main 콘텐츠로 옮기면서 헤더만 뷰포트 너비가 돼 메뉴가
줄바꿈되던 문제 수정. 헤더+본문을 하나의 OS 컨테이너(min-w-1440)로 묶어
1440 미만이면 헤더까지 함께 가로 스크롤되고, 헤더는 sticky top-0으로
세로 스크롤 시 고정. 일정 페이지는 가로 스크롤만(세로는 내부 처리).
공개/관리자 레이아웃 동일 적용.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 19:17:00 +09:00
9dc2667741 feat(youtube-bot): 예정 일정 생성 주기(몇 주 뒤) 옵션 추가
기존엔 '다음 주 요일'만 가능해 격주 콘텐츠(한화 이단장 등)에 못 썼는데,
weeksAhead(1~4주)를 추가해 N주 뒤 날짜로 예정 일정을 생성. getNextWeekday에
weeksAhead 반영, auto_schedule_config JSON에 필드 추가, 다이얼로그에 생성 주기
드롭다운 추가. DB/라우트 변경 없음.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 21:34:46 +09:00
f9f2b03403 style(x-bot): 텍스트 필터 칩 검정 배경 흰 글씨로 변경 2026-06-07 18:38:20 +09:00
8f79ea4ee4 style(x-bot): 다이얼로그 색상을 X 브랜드(검정)로 변경
하늘색(sky, 구 트위터 색)을 X 현재 브랜드인 검정 계열로 교체
(토글/버튼/포커스/태그/로더). 헤더의 검정 X 아이콘과 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:37:09 +09:00
3d5f1d8a66 fix(youtube-bot): 토글 knob 위치를 X봇과 동일하게 (상하좌우 여백 균일)
knob을 mt-0.5 margin 방식 대신 absolute top-0.5 left-0.5로 위치 지정,
트랙에 relative 추가. 위아래가 잘려 보이던 문제 해결, 4개 토글 모두
X봇 다이얼로그와 동일한 비율로 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:35:30 +09:00
468bf1f3a7 fix(youtube-bot): 토글 스위치 위치 버그 + 방향 통일
translate-x-5.5(유효하지 않은 Tailwind 클래스)로 예정 일정/고정 멤버
토글의 knob이 움직이지 않고 색만 바뀌던 문제 수정. 모든 토글을
translate-x-5(오른쪽=활성화)로 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:31:06 +09:00
7d58d19737 feat(youtube-bot): 예정 일정에 고정 멤버 포함 옵션 추가
예정 일정 자동 생성 시 봇의 고정 멤버(default_member_ids)를 함께
추가하는 옵션(auto_schedule_config.includeDefaultMembers). 워크돌처럼
멤버가 고정인 채널의 다음 주 예정 일정에 멤버가 자동으로 붙음.
DB/라우트 변경 없이 auto_schedule_config JSON에 플래그 추가 +
관리자 다이얼로그에 토글.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:12:26 +09:00
8a8548e2d7 docs: 보류(유지보수 부채) 항목 카테고리별 정리 + 누락 항목 보강 2026-06-07 18:06:54 +09:00
805e1b5ec9 style(pc): 페이지 스크롤바 핸들 불투명 단색(primary)으로 변경 2026-06-07 17:29:04 +09:00
ec1c413ba8 style(pc): 페이지 스크롤바 핸들 끝을 둥글게 (os-handle-border-radius) 2026-06-07 17:28:32 +09:00
5aca8d97d1 feat(pc): 페이지 스크롤바를 OverlayScrollbars로 교체
#root의 min-width(1440)를 스크롤 컨테이너(main) 내부 콘텐츠로 옮기고
main에 OverlayScrollbars 적용. 1440 미만으로 줄여도 세로 스크롤바가
뷰포트 끝에 항상 보이고 가로 스크롤이 생김(maplestory 방식). 헤더 고정
모델 유지, 일정 페이지는 기존 내부 스크롤 유지. 공개/관리자 레이아웃 동일 적용.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 17:23:24 +09:00
93d7737bb0 chore(frontend): overlayscrollbars 의존성 추가 2026-06-07 17:19:28 +09:00
ac1c09a9c5 docs: 계획서 웨이브3 완료 체크 2026-06-07 16:39:53 +09:00
54e014c833 perf(schedule): 월별 일정 Redis 캐시 + 쓰기 시 무효화
캘린더(최다 호출 공개 엔드포인트) getMonthlySchedules를 getOrSet으로
캐시(TTL 60s). 무효화는 모든 쓰기가 수렴하는 3개 meili 동기화 함수
(addOrUpdateSchedule/syncScheduleById/deleteSchedule)에 redis 전달 시
schedule:monthly:* 무효화. 관리자 라우트·봇 경로에서 redis 전달(즉시
반영), festival/누락 경로는 60s TTL로 자동 치유.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 16:39:40 +09:00
f50463f394 docs: 계획서 웨이브2 완료 체크 2026-06-07 16:19:47 +09:00
1b330872f5 perf(schedule): 카드 onClick 안정화로 React.memo 복구
카드가 onClick(schedule)을 호출하도록 변경(기존 호출부는 인자 무시라
호환), 페이지는 useCallback 안정 핸들러를 전달. 매 렌더 새 인라인
함수로 memo가 깨져 필터/스크롤마다 전체 카드가 리렌더되던 문제 해결.
검색 결과 가상화 카드는 범위에서 제외(이미 최적화됨).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 16:19:33 +09:00
067618d792 perf(mobile-schedule): selectedDate 참조 안정화
storedSelectedDate가 없을 때 매 렌더 new Date()가 생성돼 다수
useMemo/useEffect가 재실행되고 날짜 스트립이 반복 scrollIntoView되던
문제를, useMemo로 참조를 안정화(값 의미는 동일).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 16:14:06 +09:00
11956a4669 docs: 계획서 웨이브1 완료 체크 2026-06-07 15:43:13 +09:00
b0a2e69711 fix(youtube): YouTube API fetch에 타임아웃 추가
업스트림 행 시 봇 동기화/요청 핸들러가 무한 대기하던 문제 방지.
fetchWithTimeout(AbortController, 10s)으로 7개 fetch 호출 일괄 래핑.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:42:53 +09:00
6e559a52b7 fix(scheduler): 봇 JSON 컬럼 파싱에 safeParse 가드 추가
깨진 JSON 값 하나가 getAllBots 전체를 throw시켜 startAll(전체 봇 기동)을
막던 위험 제거. weekly_schedule_config/title_filters/default_member_ids/
auto_schedule_config/text_filters를 safeParse(fallback)로 처리.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:41:57 +09:00
e16d3f1230 fix(security): 공개 /api/bots에서 민감 정보 제거
무인증 공개 엔드포인트가 봇 설정(채널/계정/필터)과 에러 내부정보
(errorMessage 등)를 그대로 노출하던 것을 상태 요약 필드만 반환하도록
화이트리스트. getBots() await 누락(잠재 버그)도 함께 수정.
관리자 화면은 인증된 /api/admin/bots 사용(영향 없음).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:40:42 +09:00
6b66445295 refactor(frontend): 죽은 API/훅 제거
- createSchedule/updateSchedule (백엔드 라우트 없음, 미사용) 삭제
- useMemberDetail/getMemberByName (미정의 함수 호출, 미사용) 삭제
- 불필요해진 fetchFormData import 정리

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:38:19 +09:00
48c2a68cda fix(x-bots): X봇 생성 시 exclude_managed_channels ReferenceError 수정
POST body 스키마/구조분해에 exclude_managed_channels(default true,
컬럼 기본값과 일치)를 추가. 누락으로 INSERT 시 ReferenceError 크래시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:36:19 +09:00
7828ca6399 docs: 개선 작업 계획서 추가 2026-06-07 15:35:44 +09:00
3e56670e8a feat(x-bot): TikTok 카드 썸네일 온디맨드 프록시
TikTok은 OG 이미지를 막지만 oEmbed는 thumbnail_url 제공. 단 서명·만료
URL이라 저장하지 않고, /api/schedules/x-card-thumb/:postId 엔드포인트가
요청 시 oEmbed로 현재 썸네일을 받아 302 리다이렉트(Redis 6h 캐시).
resolveCard는 TikTok 카드 이미지를 이 프록시 경로로 설정.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:40:32 +09:00
0b730405a6 fix(x-bot): 만료되는 트위터 카드 이미지를 원본 OG 이미지로 대체
Nitter가 주는 pbs.twimg.com/card_img 이미지는 시간이 지나면 404로
만료됨. resolveCard에서 카드 이미지가 없거나 해당 만료성 URL이면
원본 URL의 OG 이미지(i.ytimg 등 안정적)로 대체.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:30:59 +09:00
134f5836b7 fix(x-bot): OG 카드 엔티티 디코딩 + YouTube 이미지 보강
- 스크래퍼가 Nitter HTML 엔티티(&#x2F; &amp; 등)를 디코딩하지 않아
  본문/카드 제목에 [JP&#x2F;EN]처럼 노출되던 문제 수정 (extractCard,
  extractTextFromHtml에 decodeEntities 적용)
- resolveCard가 Nitter 카드에 제목만 있고 이미지가 없을 때 OG로 이미지를
  보강하도록 변경 (YouTube 카드 이미지 누락 복구)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:26:54 +09:00
3ba27c0100 style(festival-bot): 봇 관리 페이지 축제 섹션 색상 amber로 변경
typeConfig.festival 색상을 emerald → amber로 변경해 다이얼로그·축제
카테고리 색감과 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:06:07 +09:00
de6e56047c style(festival-bot): 다이얼로그 색상 축제 카테고리 톤(amber)으로 변경
초록(emerald) → amber 계열로 변경해 행사/축제 색감과 통일.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:04:38 +09:00
543371db23 feat(festival-bot): 비활성 월일 때 '대기 중' 상태 표시
봇 목록 API에 active_months 노출. 봇이 켜져 있어도 현재 달이 활성
월이 아니면 카드 상태를 초록 '실행 중' 대신 amber '대기 중'으로 표시.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:04:38 +09:00
d24f8cabe3 docs(api): 축제 봇 active_months 필드 문서화
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:59:03 +09:00
2af3af9345 feat(festival-bot): 다이얼로그에 활성 월 선택 UI
축제 봇 추가/수정 다이얼로그에 1~12월 토글 그리드 + 전체 선택/해제
추가. 신규 봇은 전체 월(항상 실행) 기본. 전체 선택은 active_months
null로 저장.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:58:13 +09:00
8b36e9b5f7 feat(festival-bot): active_months API + 축제 봇 전용으로 한정
- botMonths 유틸(parse/serialize) 추가, 빈배열·전체선택은 NULL 정규화
- 축제 봇 라우트 조회/생성/수정에 active_months 반영 (수정 시 봇 재시작으로 즉시 적용)
- 봇별 설정이 이미 분리돼 있어 x/youtube에는 미적용 — DB 컬럼/스케줄러 매퍼에서 제외
- 스케줄러 isActiveMonth 게이트는 범용 유지(미설정 봇은 항상 실행)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:56:26 +09:00
fa37891ab3 feat(bots): 스케줄러에 활성 월 게이트 추가
봇 매퍼에 activeMonths 파싱 추가. cron 콜백·즉시 실행 시 현재 KST
월이 활성 월에 포함될 때만 동기화 실행(매 실행 시점 재평가). NULL/
빈배열/12개 전체는 항상 실행. date.js에 monthKST() 헬퍼 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:52:26 +09:00
604142672e feat(bots): active_months 컬럼 추가 (시즌성 봇 실행 월 제한)
bot_festival/bot_x/bot_youtube에 active_months JSON 컬럼 추가.
NULL=전체 월(항상 실행), 정수 배열이면 해당 월에만 동기화.
대학 축제 봇처럼 시즌에만 도는 봇의 불필요한 API 호출 절약.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 22:49:35 +09:00
39a6225897 feat(schedule-mobile): 날짜 미정 일정 렌더링 (B안)
모바일 일정 페이지에 date_precision='month' 일정을 점선 "N월 중"
카드(UndatedScheduleListCard)로 표시. 선택 날짜와 무관하게 해당
달이면 확정 일정 아래 "날짜 미정" 구분선과 함께 배치.
캘린더/날짜 점은 1일에 찍지 않도록 PC·모바일 dot 목록에서 제외.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 20:27:07 +09:00
39aadf50e6 feat(schedule-pc): 날짜 미정 일정 렌더링 (B안)
date_precision='month' 일정을 점선 "N월 중" 카드(UndatedScheduleCard)로
표시. 선택 날짜와 무관하게 해당 월이면 확정 일정 아래에 배치하고
사이에 "날짜 미정" 구분선 추가. 카운트에도 포함.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 20:10:26 +09:00
44d30d48f6 feat(schedule): 조회 응답에 datePrecision 포함
목록(SCHEDULE_LIST_SQL)·상세(getScheduleDetail) 쿼리/포맷터가
date_precision을 반환하도록 추가. 기본값 'day'. 공개 페이지에서
'month'인 일정을 날짜 미정으로 렌더링하기 위한 읽기 지원.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 18:44:08 +09:00
17746581e1 feat(schedule): date_precision 컬럼 추가 (날짜 미정 일정 지원)
월만 확정된 일정을 위해 schedules에 date_precision ENUM('day','month')
추가. 기본값 'day'로 기존 일정/쿼리에 영향 없음. month인 경우
date는 해당 월 1일로 저장하고 확정 시 수정에서 정확한 날짜 입력.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 18:34:24 +09:00
01cf1cfe9a fix(mobile-schedule): 카테고리 칩 자동 숨김 제거
스크롤 방향 감지 자동 숨김이 sticky 바의 transform 전환과
충돌해 리스트 상단에서 위로 스크롤 시 떨림 발생.
항상 보이는 단순 sticky 칩 바로 변경.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 15:04:45 +09:00