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)}
+ >
+
+
고정 멤버 포함
+
+ 예정 일정에 고급 설정의 고정 멤버를 함께 추가합니다
+
+
+
+
)}