From 7d58d19737cbe936970ce5731c613aef262578b8 Mon Sep 17 00:00:00 2001 From: caadiq Date: Sun, 7 Jun 2026 18:12:26 +0900 Subject: [PATCH] =?UTF-8?q?feat(youtube-bot):=20=EC=98=88=EC=A0=95=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=EC=97=90=20=EA=B3=A0=EC=A0=95=20=EB=A9=A4?= =?UTF-8?q?=EB=B2=84=20=ED=8F=AC=ED=95=A8=20=EC=98=B5=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 예정 일정 자동 생성 시 봇의 고정 멤버(default_member_ids)를 함께 추가하는 옵션(auto_schedule_config.includeDefaultMembers). 워크돌처럼 멤버가 고정인 채널의 다음 주 예정 일정에 멤버가 자동으로 붙음. DB/라우트 변경 없이 auto_schedule_config JSON에 플래그 추가 + 관리자 다이얼로그에 토글. Co-Authored-By: Claude Opus 4.7 --- backend/src/services/youtube/index.js | 9 ++++++ .../pc/admin/bot/YouTubeBotDialog.jsx | 28 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/backend/src/services/youtube/index.js b/backend/src/services/youtube/index.js index a7d1c80..489cda7 100644 --- a/backend/src/services/youtube/index.js +++ b/backend/src/services/youtube/index.js @@ -110,6 +110,15 @@ async function youtubeBotPlugin(fastify) { [newScheduleId, null, 'video', bot.channelId, bot.channelName] ); + // 옵션: 예정 일정에 고정 멤버 포함 + if (autoScheduleNext.includeDefaultMembers && bot.defaultMemberIds?.length > 0) { + const values = [...new Set(bot.defaultMemberIds)].map(id => [newScheduleId, id]); + await conn.query( + 'INSERT INTO schedule_members (schedule_id, member_id) VALUES ?', + [values] + ); + } + return newScheduleId; }); diff --git a/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx b/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx index be3e7f3..9b13463 100644 --- a/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx +++ b/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx @@ -293,6 +293,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) { const [scheduleTime, setScheduleTime] = useState('18:00'); const [titleTemplate, setTitleTemplate] = useState('{channelName} {episode}화'); const [deadlineDayOfWeek, setDeadlineDayOfWeek] = useState(5); + const [includeDefaultMembers, setIncludeDefaultMembers] = useState(false); // 고급 설정 const [showAdvanced, setShowAdvanced] = useState(false); @@ -371,12 +372,14 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) { setScheduleTime(config.time?.slice(0, 5) || '18:00'); setTitleTemplate(config.titleTemplate || '{channelName} {episode}화'); setDeadlineDayOfWeek(config.deadlineDayOfWeek ?? 5); + setIncludeDefaultMembers(config.includeDefaultMembers ?? false); } else { setAutoScheduleEnabled(false); setScheduleDayOfWeek(4); setScheduleTime('18:00'); setTitleTemplate('{channelName} {episode}화'); setDeadlineDayOfWeek(5); + setIncludeDefaultMembers(false); } setTitleFilters(bot.title_filters || []); @@ -458,6 +461,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) { time: `${scheduleTime}:00`, titleTemplate, deadlineDayOfWeek, + includeDefaultMembers, } : null, weekly_schedule_config: pollingMode === 'weekly' @@ -756,6 +760,30 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) { 이 요일까지 영상이 없으면 예정 일정을 삭제합니다

+ + {/* 고정 멤버 포함 */} +
setIncludeDefaultMembers(!includeDefaultMembers)} + > +
+

고정 멤버 포함

+

+ 예정 일정에 고급 설정의 고정 멤버를 함께 추가합니다 +

+
+
+
+
+
)}