Commit graph

194 commits

Author SHA1 Message Date
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
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
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
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
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
2ddc16d532 feat(concert): 콘서트 상세 페이지 추가 (몰입형 디자인)
기존 DefaultSection으로 빈약하게 표시되던 콘서트를 전용 상세 페이지로.

백엔드:
- getScheduleDetail 콘서트 분기: 포스터/장소/세트리스트(곡별 멤버)/굿즈/다른 회차

프론트엔드:
- ConcertSection(PC) / MobileConcertSection(모바일) 신규
- 블러 포스터 히어로 + 회차 드롭다운 + 장소 지도 다이얼로그
- 세트리스트 펼치기/접기 애니메이션, 유닛/솔로만 멤버 태그
- 굿즈 masonry 갤러리(라이트박스), 회차 전환은 history replace
- 모바일은 세로 중앙형 전용 히어로 + 바텀시트
- Lightbox/MobileLightbox를 createPortal로 변경 (오버레이 전체화면 보장)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 23:20:48 +09:00
8b8b9a7f53 feat(x-schedule): 링크 미리보기(OG) 카드 추가 - 하이브리드
트윗의 외부 링크에 대해 미리보기 카드 표시.
- Nitter가 렌더링한 카드 우선 사용 (extractCard)
- Nitter 카드가 비어있으면 본문 URL로 OG 직접 추출 (og.js)
  - YouTube/Instagram 등 복구, HTML 엔티티 디코딩 포함
  - TikTok 등 봇 차단 사이트는 Nitter 카드로 커버
- schedule_x.card_data 컬럼 + getScheduleDetail 응답에 card 포함
- 가로 레이아웃 카드 (왼쪽 이미지 + 오른쪽 텍스트)
- CardImage: 이미지 로드 실패 시 fallback 아이콘 (인스타 CDN 만료 대비)
- 자체 영상/이미지가 있으면 OG 카드 숨김 (중복 방지)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 19:34:42 +09:00
d3d3c9cf75 feat(x-schedule): 트윗 네이티브 영상 썸네일 표시
Nitter는 영상 파일을 제공하지 않으므로 썸네일만 추출해 표시하고,
재생 시 원본 트윗으로 이동.

- scraper: extractVideoThumbnails 추가 (amplify_video_thumb 등)
- schedule_x.video_thumbnails 컬럼 + saveTweet 저장
- getScheduleDetail 응답에 videoThumbnails 포함
- PC/모바일 X 상세: 썸네일 + 재생버튼 + 'X에서 재생' 배지

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 19:02:29 +09:00
4cfa4ffc00 fix(x-bot): 리트윗 이중 저장 방지
같은 리트윗이 타임라인에서 래퍼 id / 원본 id 두 형태로 번갈아 나타나
post_id 중복 체크를 통과해 두 번 저장되던 문제 수정.

리트윗 저장 시 동일 내용 + (원작자 또는 봇계정) username이 이미 있으면
중복으로 간주해 건너뜀. hydration으로 양쪽 모두 전체 내용을 갖추므로
내용 기반 매칭이 안정적으로 동작.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 18:02:22 +09:00
2cfc580283 fix(x-bot): 잘린 긴 리트윗 전체 내용 복원 (hydration)
X long tweet(280자 초과)을 Nitter 타임라인이 간헐적으로 …로 잘라서
주는 경우, 개별 상태 페이지에서 재요청해 전체 내용으로 교체.

- parseTweets: …로 끝나는 트윗에 truncated 플래그 부여
- hydrateTruncatedTweets: 잘린 트윗 status 페이지 재요청 후 교체 (best-effort)
- fetchTweets/fetchAllTweets에 적용
- fetchSingleTweet을 timeout-safe하게 변경

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-31 18:00:14 +09:00
6a24b997dd feat(logs): 활동 로그 다이얼로그 상세 정보 표시 + 에러 정보 보강
- logs API: longtext로 저장된 details를 JSON 객체로 파싱해 반환
- 응답 스키마에 additionalProperties: true 추가 (fast-json-stringify가
  스키마 미정의 키를 제거하던 문제 해결)
- scheduler 에러 로그: err.cause / err.code / err.causeCode 함께 기록
  (fetch failed 등 모호한 메시지의 진짜 원인 식별 가능)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 17:02:53 +09:00
d530822a68 feat(festival-bot): 대학 축제 크롤러 봇 구현 (3단계)
검색 페이지(memogipost)를 크롤링하여 프로미스나인 출연 대학 축제를
Gemini url_context로 추출, 행사 일정을 자동 생성하는 봇.

백엔드:
- services/event.js: 이벤트 생성 로직 공유화 (upsertVenue, createEventSchedule, 카카오 검색)
- services/festival/: scraper(검색 페이지 크롤) + gemini(추출) + index(봇 플러그인)
- routes/admin/festival-bots.js: 축제 봇 CRUD API
- scheduler.js: festival 타입 지원, 시간 단위 cron(0 */H * * *) 변환
- 처리한 글 URL은 festival_crawl_log에 기록, 새 글 없으면 Gemini 미호출
- 학교명 부분일치 중복 감지, 활동 멤버 전체 자동 등록
- Gemini 503/500/429 재시도 로직

기타 수정:
- 행사 상세 페이지 관련 링크 줄바꿈 (truncate → break-all)
- 대학 축제 아이콘 변경 (GraduationCap → PartyPopper)
- docs/api.md, CLAUDE.md 환경변수 문서화

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:28:24 +09:00
3827a23d75 feat(festival-bot): 축제 봇 관리 UI 추가 (2단계)
- bot_festival, festival_crawl_log 테이블 SQL
- FestivalBotDialog: 봇 이름/크롤링 URL/동기화 간격(1~24시간) 입력
- 봇 관리 페이지에 '축제' 섹션 추가 (emerald, PartyPopper)
- BotCard: festival 타입 수정/삭제 버튼 표시
- API 클라이언트 함수 추가 (백엔드 라우트는 3단계)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:09:07 +09:00
bcc8555193 feat(youtube-bot): 제목에서 멤버 추출 옵션 추가
- bot_youtube에 extract_members_from_title 컬럼 추가 (기본값 0)
- services/youtube/index.js: 설명과 제목에서 각각 멤버 이름 검색, 합집합으로 중복 제거
- YouTubeBotDialog 고급 설정에 토글 추가 (설명 추출 토글 아래)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:50:02 +09:00
678e228bc5 feat(x-bot): 관리 YouTube 채널 영상 제외 옵션 추가
- bot_x에 exclude_managed_channels 컬럼 추가 (기본값 1, 기존 동작 유지)
- X 봇이 트윗에서 YouTube 링크를 추출할 때 이미 등록된 YouTube 봇 채널의 영상을 중복 추가할지 옵션으로 제어
- XBotDialog에 토글 추가 (extract_youtube 활성 시만 노출, 왼쪽 border로 하위 옵션 시각화)
- services/x/index.js processYoutubeLinks 시그니처에 옵션 파라미터 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 18:45:45 +09:00
7c20e9bb17 feat(schedule): 행사 수정 폼 + 공개 상세 페이지 + 지도
- Admin: EventEditForm 추가 (기존 포스터 유지 + 신규 추가 조합), ScheduleItem 편집 경로에 '행사' 분기
- PC 공개 상세: EventSection 추가 - 포스터 Swiper 슬라이드 + 호버 화살표, 클릭 시 Lightbox, 카카오맵 + 마커 + 장소명 오버레이, 관련 링크는 중간점+primary 색상, max-w-5xl 및 text-2xl로 크기 확대
- Mobile 공개 상세: MobileEventSection 추가 (포스터/장소/지도/링크)
- KakaoMap 공용 컴포넌트 신규 (SDK 1회 로드 공유), VITE_KAKAO_JS_KEY 사용
- .gitignore: frontend/.env 제외
- routes/admin/events.js: PUT 핸들러의 addOrUpdateSchedule → syncScheduleById 정정
- 관련 문서(api/architecture/development) 업데이트

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 12:24:01 +09:00
d9836d2f5d feat(schedule): 행사 카테고리 추가 (학교 행사)
- schedule_categories에 '행사' 카테고리(id=11) 시드, CATEGORY_IDS.EVENT 상수 추가
- event_venues / schedule_event 테이블 생성 (subtype, school_name, venue_id, post_urls, poster_image_ids)
- routes/admin/events.js 신설: multipart 기반 CRUD + 다중 포스터 업로드 + 카카오맵 venue upsert
- services/image.js에 uploadEventPoster 추가 (event/{scheduleId}/poster/...)
- 공개 /schedules 서비스의 SCHEDULE_LIST_SQL / getScheduleDetail에 행사 JOIN 및 응답(subtype, schoolName, venue, posters, postUrls)
- buildSource에 EVENT 분기 추가 → source.name = 학교명
- Meilisearch 동기화: source_name에 school_name 포함, 부분 검색 대응을 위한 resolveSchoolNames 추가
- 프론트: form/index.jsx에 '행사' 분기, EventForm 컴포넌트 신설 (LocationSearchDialog 재사용, 다중 포스터/URL)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:04:42 +09:00
f2a15e07d6 feat(youtube-bot): 주간 지정 시간 폴링 모드 추가
- bot_youtube에 weekly_schedule_config JSON 컬럼 추가, cron_interval nullable로 변경
- weekly 모드: 지정 요일/시각에만 cron 트리거 → setInterval로 intervalSeconds 간격 폴링
- 종료 조건: 새 영상 1개 발견(stopOnFound) 또는 durationMinutes 경과
- 평상시 API 호출 없어 주 1회 업로드 채널(워크맨 등)의 할당량 낭비 최소화
- 프론트 폼에 상시/주간 모드 토글 추가, 요일 드롭다운 월~일 순서로 정렬
- 관련 문서(api/development/architecture) 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 20:56:54 +09:00
8ece4b1850 feat(backend): 봇 연속 오류 시 자동 정지 로직 추가
- consecutiveErrors 카운터로 실패 횟수 추적 (성공 시 0으로 리셋)
- 동일 에러 루프에서 sync/error 로그는 첫 1회만 기록하여 스팸 방지
- 10회 연속 실패 시 stopBot 호출 및 bot/stop 로그 1건 남김
- docs/logs.md, docs/development.md 관련 설명 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:38:37 +09:00
48ed3bb9e0 feat(variety): 방송사 프리셋을 입력 빈도수 기반으로 변경
- GET /admin/variety/broadcasters: DB에서 빈도수 상위 10개 조회 (Redis 1시간 캐시)
- 일정 생성/수정 시 캐시 무효화
- 프론트엔드: 하드코딩 프리셋 제거, API에서 동적으로 로드

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 13:37:52 +09:00
a01d368728 feat(variety): 썸네일을 RustFS 이미지 업로드로 변경
- schedule/{id}/thumbnail/ 경로에 original/medium_800/thumb_400 webp 업로드
- images 테이블로 이미지 관리, schedule_variety.thumbnail_id로 참조
- 프론트엔드: URL 입력 → 파일 업로드(드래그&드롭) + 미리보기로 변경
- 수정 시 기존 썸네일 교체/삭제 지원

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 19:07:08 +09:00
73f84fd7ac feat: 예능 카테고리 관리 기능 구현
- 백엔드: POST/PUT/GET /admin/variety/schedule API
- 백엔드: 일정 상세 응답에 broadcaster, replayUrl, thumbnailUrl 포함
- 프론트엔드: VarietyForm (추가), VarietyEditForm (수정) 페이지
- 방송사 프리셋 버튼 (KBS, MBC, SBS, tvN, 유튜브, 티빙 등)
- 출연 멤버 선택, 다시보기 링크, 썸네일 URL 지원
- 라우트 등록 및 일정 목록 편집 링크 연결

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 18:16:16 +09:00
96969e1bf0 feat: 예능 카테고리 및 schedule_variety 테이블 추가
- schedule_variety: broadcaster, replay_url, thumbnail_url
- 카테고리 ID 10 '예능' (#22c55e) 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 18:08:56 +09:00
9e3a71e156 fix: 사진/티저 업로드·삭제 시 앨범 캐시 무효화 누락 수정
photos.js, teasers.js에서 invalidateAlbumCache 호출 추가.
앨범 생성 후 사진/티저 추가 시 캐시된 빈 데이터가 반환되던 문제 해결.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:31:40 +09:00
ce41fc1a60 feat(concert): 콘서트 수정 페이지 추가
- 백엔드: GET /admin/concert/schedule/:seriesId (상세 조회)
- 백엔드: PUT /admin/concert/schedule/:seriesId (수정)
- 프론트엔드: ConcertEditForm 페이지 (생성 폼 컴포넌트 재사용)
- 라우트: /admin/schedule/concert/:seriesId/edit 등록
- 일정 목록: 콘서트 카테고리 편집 버튼이 수정 페이지로 연결
- schedule.js: formatSchedule에 concertSeriesId 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 18:25:01 +09:00
8ccf18e8b1 feat(concert): 회차별 세트리스트 입력 지원
- 프론트엔드: 단일 setlist → 회차별 setlists (탭 UI로 전환)
- 회차 추가 시 이전 회차의 세트리스트 자동 복사
- '다른 회차에서 복사' 기능 추가
- 백엔드: 각 concert_id별로 독립적인 세트리스트 저장
- 하위호환: 기존 setlist 필드도 지원 (단일 배열 → 첫 회차에 적용)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 18:03:08 +09:00
9498559f6b fix(x-bot): 리트윗 프로필/이미지 복구 및 원본 트윗 매칭
- getProfile: bot_x에 없는 계정도 Nitter에서 직접 조회 후 Redis 캐시
- refetch-retweets 스크립트: 원본 작성자 타임라인에서 매칭 트윗 찾아 이미지/내용 복구
- 기존 21건 리트윗 데이터 재수집 완료 (이미지 포함)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:07:43 +09:00
3ce8d7ec7d fix(x-bot): 리트윗 내용 잘림, Nitter 링크, 이미지 누락 수정
- extractTextFromHtml: Nitter 프록시 t.co URL을 원본 https://t.co/ URL로 변환
- parseTweets: 리트윗 원본 작성자(originalUsername) 추출, URL을 원본 작성자 기준으로 생성
- saveTweet: 리트윗인 경우 원본 작성자를 username으로 저장
- refetch-retweets 엔드포인트 및 스크립트 추가 (기존 잘못된 데이터 재수집)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:59:19 +09:00
607a652c2b fix(admin): 활동 로그 필터 UI 개선
- 카테고리를 하드코딩 대신 DB에서 조회하도록 변경 (GET /admin/logs/categories)
- 카테고리 칩을 체크박스 멀티셀렉트 드롭다운으로 교체
- 카테고리가 없을 때 드롭다운 비활성화
- DatePicker에 min/max/compact prop 추가 (날짜 범위 제한, 높이 통일)
- 날짜 선택 칸 너비 축소, 초기화 버튼 여백 축소

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:16:52 +09:00
1f1d6987d1 feat(backend): 관리자/봇 라우트에 logActivity 호출 추가
12개 관리자 라우트와 3개 봇 서비스 파일에 활동 로그 기록 추가.
관리자 작업(일정/앨범/멤버/봇 CRUD)과 봇 동기화(완료/에러)를
logs 테이블에 fire-and-forget으로 기록.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:04:07 +09:00
357fd7fc88 feat(backend): 활동 로그 유틸리티 및 API 엔드포인트 추가
- logActivity() fire-and-forget 유틸리티 함수
- GET /api/admin/logs 엔드포인트 (필터/페이지네이션)
- 라우트 등록

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:56:44 +09:00
45adaaf0dc refactor(youtube): API 호출 최적화 - 새 영상만 상세 조회
기존: 매 폴링마다 activities.list + videos.list (2 units)
변경: activities.list로 videoId 확인 후 DB에 없는 새 영상만 videos.list 호출
결과: 일일 API 사용량 약 50% 감소 (1분 간격 3채널도 가능)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:52:42 +09:00
f8acb5450f fix(bot): 동시성 중복 INSERT 시 ER_DUP_ENTRY 에러 무시 처리
YouTube/X 봇의 영상 저장 트랜잭션에서 UNIQUE 제약 위반 발생 시
크래시 대신 null을 반환하여 gracefully 무시하도록 변경.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:28:27 +09:00
3feb23f67f fix(scheduler): 봇 중지 상태가 서버 재시작 후 유지되지 않는 문제 수정
DB 조회 시 WHERE enabled = 1 필터를 제거하여 비활성 봇도 시스템에서
인식되도록 변경. 이전에는 비활성 봇이 목록/검색에서 완전히 제외되어
재시작 불가 및 관리 UI에서 사라지는 문제가 있었음.
PUT 엔드포인트의 stopBot/startBot 조건 로직도 함께 정리.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:27:16 +09:00
91d4442d30 docs: X 봇 extract_youtube 관련 문서 및 스키마 업데이트
- bot_x.sql에 누락된 컬럼 추가 (text_filters, include_retweets, extract_youtube)
- api.md에 X 봇 API 응답 스키마 및 필드 설명 추가
- architecture.md bot_x 테이블 설명 구체화
- development.md API 클라이언트 함수 목록 보완

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 13:12:00 +09:00
ba7def935c feat(x-bot): YouTube 영상 추출 옵션 추가
X 봇 설정에서 트윗 내 YouTube 링크 자동 추출 기능을 온/오프 가능하게 함:
- bot_x 테이블에 extract_youtube 컬럼 추가 (기본값: false)
- 고급 설정에 "YouTube 영상 추출" 토글 추가
- extractYoutube가 true일 때만 YouTube 일정 자동 생성

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 22:40:52 +09:00
d01f7e60dc fix(schedule): YouTube 일정 상세 조회 쿼리 단순화
- 불필요한 channel_id 선택 제거
- banner_url만 조회하도록 수정

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 22:23:24 +09:00
7d140aa1f3 fix(x-bot): 동기화 결과에 total 필드 추가
- syncNewTweets(), syncAllTweets()에 total 필드 추가
- 프론트엔드 토스트에서 undefined 표시되던 문제 해결

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 09:57:04 +09:00
c86cda00ae fix(meilisearch): 전체 동기화 시 DB에 없는 문서 삭제
- syncAllSchedules()에서 Meilisearch의 모든 문서 ID 조회
- DB에 없는 문서는 Meilisearch에서 삭제
- 삭제된 일정이 검색에 계속 나타나는 문제 해결

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 09:50:54 +09:00
294018c93b refactor(x-bot): x_profiles 테이블 제거, bot_x로 통합
- x_profiles 테이블 삭제 (bot_x에 프로필 정보 포함)
- saveProfile(), getProfile() 함수가 bot_x 테이블 사용하도록 수정
- Redis 캐시는 그대로 유지 (성능)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 09:42:26 +09:00
5d44434e36 feat(x-bot): 리트윗 옵션 및 고정 트윗 제외 기능 추가
- include_retweets 옵션으로 리트윗 포함 여부 설정 가능
- 고정된 트윗(pinned)은 기본적으로 파싱에서 제외
- XBotDialog에서 Twitter 아이콘을 X 아이콘으로 변경
- schedule_x의 username을 source_name으로 활용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 09:37:57 +09:00
9ceef6c656 feat(x-bot): 키워드 필터링 및 전체 동기화 기능 추가
Backend:
- bot_x 테이블에 text_filters 컬럼 추가
- syncNewTweets/syncAllTweets에 텍스트 필터링 로직 적용
- 봇 추가 시 전체 트윗 동기화 수행 (백그라운드)
- X 봇 API에 text_filters 필드 처리

Frontend:
- XBotDialog에 고급 설정 (키워드 필터) UI 추가
- BotTableRow에서 X 봇 수정/삭제 버튼 활성화

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 09:23:45 +09:00
86769f1edc feat(admin): 봇 목록 API에 X 봇 상세 정보 추가
- 스키마에 X 봇 필드 추가 (username, display_name, avatar_url)
- X 봇 응답에 db_id, cron_interval 포함

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 23:56:45 +09:00
25c2b45cf5 feat(scheduler): X 봇 DB 기반 로드 추가
- getXBotsFromDB() 함수 추가
- getAllBots()에서 X 봇도 DB에서 로드
- config/bots.js에서 X 봇 제거 (meilisearch만 남음)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 23:51:38 +09:00
2355068c77 feat(admin): X 봇 CRUD API 추가
- POST /api/admin/x-bots/lookup: 프로필 조회
- GET /api/admin/x-bots: 목록 조회
- GET /api/admin/x-bots/🆔 상세 조회
- POST /api/admin/x-bots: 봇 추가
- PUT /api/admin/x-bots/🆔 봇 수정
- DELETE /api/admin/x-bots/🆔 봇 삭제

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 23:48:58 +09:00