From 543371db23d8b34a2d729c3c333bf47d60641e3d Mon Sep 17 00:00:00 2001 From: caadiq Date: Sat, 6 Jun 2026 23:04:38 +0900 Subject: [PATCH] =?UTF-8?q?feat(festival-bot):=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=20=EC=9B=94=EC=9D=BC=20=EB=95=8C=20'=EB=8C=80?= =?UTF-8?q?=EA=B8=B0=20=EC=A4=91'=20=EC=83=81=ED=83=9C=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 봇 목록 API에 active_months 노출. 봇이 켜져 있어도 현재 달이 활성 월이 아니면 카드 상태를 초록 '실행 중' 대신 amber '대기 중'으로 표시. Co-Authored-By: Claude Opus 4.7 --- backend/src/routes/admin/bots.js | 2 ++ .../pages/pc/admin/schedules/ScheduleBots.jsx | 25 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/backend/src/routes/admin/bots.js b/backend/src/routes/admin/bots.js index 2e6bf6e..dbd9615 100644 --- a/backend/src/routes/admin/bots.js +++ b/backend/src/routes/admin/bots.js @@ -37,6 +37,7 @@ const botResponse = { text_filters: { type: 'array', items: { type: 'string' } }, // 축제 봇 전용 필드 search_url: { type: 'string' }, + active_months: { type: ['array', 'null'], items: { type: 'integer' } }, }, }; @@ -144,6 +145,7 @@ export default async function botsRoutes(fastify) { botData.db_id = bot.dbId; botData.search_url = bot.searchUrl; botData.cron_interval = checkInterval; + botData.active_months = bot.activeMonths || null; } result.push(botData); diff --git a/frontend/src/pages/pc/admin/schedules/ScheduleBots.jsx b/frontend/src/pages/pc/admin/schedules/ScheduleBots.jsx index e35d98b..78d4fe8 100644 --- a/frontend/src/pages/pc/admin/schedules/ScheduleBots.jsx +++ b/frontend/src/pages/pc/admin/schedules/ScheduleBots.jsx @@ -2,7 +2,7 @@ import { useState, useEffect, useMemo } from 'react'; import { Link } from 'react-router-dom'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { motion, AnimatePresence } from 'framer-motion'; -import { Home, ChevronRight, Bot, CheckCircle, XCircle, RefreshCw, Plus, Youtube, PartyPopper } from 'lucide-react'; +import { Home, ChevronRight, Bot, CheckCircle, XCircle, RefreshCw, Plus, Youtube, PartyPopper, Clock } from 'lucide-react'; import { Toast, Tooltip, AnimatedNumber } from '@/components/common'; import { AdminLayout, XIcon, MeilisearchIcon, BotTableRow, BotTable, YouTubeBotDialog, XBotDialog, FestivalBotDialog } from '@/components/pc/admin'; import { useAdminAuth } from '@/hooks/pc/admin'; @@ -191,7 +191,26 @@ function ScheduleBots() { }; // 상태 아이콘 및 색상 - const getStatusInfo = (status) => { + // 봇이 켜져 있지만 현재 달이 활성 월이 아니면(축제 봇) 이번 달은 동기화하지 않음 + const isInactiveMonth = (bot) => { + const months = bot?.active_months; + if (!Array.isArray(months) || months.length === 0 || months.length >= 12) return false; + const currentMonth = new Date().getMonth() + 1; + return !months.includes(currentMonth); + }; + + const getStatusInfo = (bot) => { + const status = bot?.status; + // 실행 중이지만 비활성 월 → 대기 중 + if (status === 'running' && isInactiveMonth(bot)) { + return { + icon: , + text: '대기 중', + color: 'text-amber-500', + bg: 'bg-amber-50', + dot: 'bg-amber-400', + }; + } switch (status) { case 'running': return { @@ -523,7 +542,7 @@ function ScheduleBots() { index={index} isInitialLoad={isInitialLoad} syncing={syncing} - statusInfo={getStatusInfo(bot.status)} + statusInfo={getStatusInfo(bot)} onSync={handleSyncAllVideos} onToggle={toggleBot} onEdit={(bot) => {