feat(youtube-bot): 예정 일정 생성 주기(몇 주 뒤) 옵션 추가

기존엔 '다음 주 요일'만 가능해 격주 콘텐츠(한화 이단장 등)에 못 썼는데,
weeksAhead(1~4주)를 추가해 N주 뒤 날짜로 예정 일정을 생성. getNextWeekday에
weeksAhead 반영, auto_schedule_config JSON에 필드 추가, 다이얼로그에 생성 주기
드롭다운 추가. DB/라우트 변경 없음.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-06-08 21:34:46 +09:00
parent f9f2b03403
commit 9dc2667741
2 changed files with 31 additions and 2 deletions

View file

@ -11,15 +11,18 @@ async function youtubeBotPlugin(fastify) {
/**
* 다음 특정 요일 날짜 계산 (KST 기준)
* @param {number} targetDay - 목표 요일 (0=, 4=)
* @param {number} weeksAhead - (1=다음 , 2=2 , 격주 콘텐츠 대응)
* @param {Date} fromDate - 기준 날짜 (기본: 오늘)
* @returns {string} YYYY-MM-DD 형식
*/
function getNextWeekday(targetDay, fromDate = new Date()) {
function getNextWeekday(targetDay, weeksAhead = 1, fromDate = new Date()) {
const kst = new Date(fromDate.toLocaleString('en-US', { timeZone: 'Asia/Seoul' }));
const currentDay = kst.getDay();
// 다음 주 같은 요일까지 일수 계산
let daysUntil = targetDay - currentDay + 7;
if (daysUntil <= 0) daysUntil += 7;
// weeksAhead가 2 이상이면 그만큼 주를 더 더함
daysUntil += (Math.max(1, weeksAhead) - 1) * 7;
const nextDate = new Date(kst);
nextDate.setDate(kst.getDate() + daysUntil);
@ -81,7 +84,7 @@ async function youtubeBotPlugin(fastify) {
const { autoScheduleNext } = bot;
if (!autoScheduleNext) return null;
const nextDate = getNextWeekday(autoScheduleNext.dayOfWeek);
const nextDate = getNextWeekday(autoScheduleNext.dayOfWeek, autoScheduleNext.weeksAhead || 1);
// 이미 존재하는지 확인 (같은 채널, 같은 날짜, is_temp = 1)
const [existing] = await fastify.db.query(

View file

@ -47,6 +47,14 @@ const DAY_OPTIONS = [
{ value: 0, label: '일요일' },
];
// ( /3 )
const WEEKS_OPTIONS = [
{ value: 1, label: '다음 주 (매주)' },
{ value: 2, label: '2주 뒤 (격주)' },
{ value: 3, label: '3주 뒤' },
{ value: 4, label: '4주 뒤' },
];
// (00:00 ~ 23:00)
const TIME_OPTIONS = Array.from({ length: 24 }, (_, i) => ({
value: `${String(i).padStart(2, '0')}:00`,
@ -290,6 +298,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
//
const [autoScheduleEnabled, setAutoScheduleEnabled] = useState(false);
const [scheduleDayOfWeek, setScheduleDayOfWeek] = useState(4);
const [weeksAhead, setWeeksAhead] = useState(1);
const [scheduleTime, setScheduleTime] = useState('18:00');
const [titleTemplate, setTitleTemplate] = useState('{channelName} {episode}화');
const [deadlineDayOfWeek, setDeadlineDayOfWeek] = useState(5);
@ -369,6 +378,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
if (config && config.dayOfWeek !== undefined) {
setAutoScheduleEnabled(true);
setScheduleDayOfWeek(config.dayOfWeek);
setWeeksAhead(config.weeksAhead ?? 1);
setScheduleTime(config.time?.slice(0, 5) || '18:00');
setTitleTemplate(config.titleTemplate || '{channelName} {episode}화');
setDeadlineDayOfWeek(config.deadlineDayOfWeek ?? 5);
@ -376,6 +386,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
} else {
setAutoScheduleEnabled(false);
setScheduleDayOfWeek(4);
setWeeksAhead(1);
setScheduleTime('18:00');
setTitleTemplate('{channelName} {episode}화');
setDeadlineDayOfWeek(5);
@ -458,6 +469,7 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
auto_schedule_config: autoScheduleEnabled
? {
dayOfWeek: scheduleDayOfWeek,
weeksAhead,
time: `${scheduleTime}:00`,
titleTemplate,
deadlineDayOfWeek,
@ -732,6 +744,20 @@ function YouTubeBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
</div>
</div>
{/* 생성 주기 (몇 주 뒤) */}
<div>
<label className="block text-sm text-gray-600 mb-1">생성 주기</label>
<Dropdown
value={weeksAhead}
options={WEEKS_OPTIONS}
onChange={setWeeksAhead}
placeholder="주기 선택"
/>
<p className="text-xs text-gray-400 mt-1">
예정 일정을 날짜로 생성할지 (격주 콘텐츠는 2 )
</p>
</div>
{/* 제목 템플릿 */}
<div>
<label className="block text-sm text-gray-600 mb-1">제목 템플릿</label>