feat(bot): studiofromis_9 채널 봇 추가 및 cron 표현식 지원
- .env에 YouTube API 키 추가 - bots 테이블에 channel_id, rss_url, cron_expression 컬럼 추가 - youtube-scheduler.js: cron_expression 파라미터 지원 - youtube-bot.js: bots 테이블에서 직접 조회, Shorts 필터링 제거 - studiofromis_9 봇 등록 (채널: UCW0ORl7mZO8wIWkgtq-yzjQ, cron: 1,2 * * * *)
This commit is contained in:
parent
1b01182028
commit
e216539f34
3 changed files with 28 additions and 35 deletions
3
.env
3
.env
|
|
@ -19,3 +19,6 @@ RUSTFS_BUCKET=fromis-9
|
||||||
|
|
||||||
# Kakao API
|
# Kakao API
|
||||||
KAKAO_REST_KEY=cf21156ae6cc8f6e95b3a3150926cdf8
|
KAKAO_REST_KEY=cf21156ae6cc8f6e95b3a3150926cdf8
|
||||||
|
|
||||||
|
# YouTube API
|
||||||
|
YOUTUBE_API_KEY=AIzaSyC6l3nFlcHgLc0d1Q9WPyYQjVKTv21ZqFs
|
||||||
|
|
|
||||||
|
|
@ -241,20 +241,19 @@ export async function createScheduleFromVideo(video, categoryId) {
|
||||||
*/
|
*/
|
||||||
export async function syncNewVideos(botId) {
|
export async function syncNewVideos(botId) {
|
||||||
try {
|
try {
|
||||||
// 봇 정보 조회
|
// 봇 정보 조회 (bots 테이블에서 직접)
|
||||||
const [bots] = await pool.query(
|
const [bots] = await pool.query(`SELECT * FROM bots WHERE id = ?`, [botId]);
|
||||||
`SELECT b.*, c.channel_id, c.rss_url, c.include_shorts
|
|
||||||
FROM bots b
|
|
||||||
JOIN bot_youtube_config c ON b.id = c.bot_id
|
|
||||||
WHERE b.id = ?`,
|
|
||||||
[botId]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (bots.length === 0) {
|
if (bots.length === 0) {
|
||||||
throw new Error("봇을 찾을 수 없습니다.");
|
throw new Error("봇을 찾을 수 없습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const bot = bots[0];
|
const bot = bots[0];
|
||||||
|
|
||||||
|
if (!bot.rss_url) {
|
||||||
|
throw new Error("RSS URL이 설정되지 않았습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
const categoryId = await getYoutubeCategory();
|
const categoryId = await getYoutubeCategory();
|
||||||
|
|
||||||
// RSS 피드 파싱
|
// RSS 피드 파싱
|
||||||
|
|
@ -262,10 +261,7 @@ export async function syncNewVideos(botId) {
|
||||||
let addedCount = 0;
|
let addedCount = 0;
|
||||||
|
|
||||||
for (const video of videos) {
|
for (const video of videos) {
|
||||||
// Shorts 필터링
|
// Shorts도 포함하여 일정으로 추가
|
||||||
if (!bot.include_shorts && video.videoType === "shorts") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scheduleId = await createScheduleFromVideo(video, categoryId);
|
const scheduleId = await createScheduleFromVideo(video, categoryId);
|
||||||
if (scheduleId) {
|
if (scheduleId) {
|
||||||
|
|
@ -303,20 +299,19 @@ export async function syncNewVideos(botId) {
|
||||||
*/
|
*/
|
||||||
export async function syncAllVideos(botId) {
|
export async function syncAllVideos(botId) {
|
||||||
try {
|
try {
|
||||||
// 봇 정보 조회
|
// 봇 정보 조회 (bots 테이블에서 직접)
|
||||||
const [bots] = await pool.query(
|
const [bots] = await pool.query(`SELECT * FROM bots WHERE id = ?`, [botId]);
|
||||||
`SELECT b.*, c.channel_id, c.include_shorts
|
|
||||||
FROM bots b
|
|
||||||
JOIN bot_youtube_config c ON b.id = c.bot_id
|
|
||||||
WHERE b.id = ?`,
|
|
||||||
[botId]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (bots.length === 0) {
|
if (bots.length === 0) {
|
||||||
throw new Error("봇을 찾을 수 없습니다.");
|
throw new Error("봇을 찾을 수 없습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const bot = bots[0];
|
const bot = bots[0];
|
||||||
|
|
||||||
|
if (!bot.channel_id) {
|
||||||
|
throw new Error("Channel ID가 설정되지 않았습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
const categoryId = await getYoutubeCategory();
|
const categoryId = await getYoutubeCategory();
|
||||||
|
|
||||||
// API로 전체 영상 수집
|
// API로 전체 영상 수집
|
||||||
|
|
@ -324,10 +319,7 @@ export async function syncAllVideos(botId) {
|
||||||
let addedCount = 0;
|
let addedCount = 0;
|
||||||
|
|
||||||
for (const video of videos) {
|
for (const video of videos) {
|
||||||
// Shorts 필터링
|
// Shorts도 포함하여 일정으로 추가
|
||||||
if (!bot.include_shorts && video.videoType === "shorts") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scheduleId = await createScheduleFromVideo(video, categoryId);
|
const scheduleId = await createScheduleFromVideo(video, categoryId);
|
||||||
if (scheduleId) {
|
if (scheduleId) {
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,14 @@ const schedulers = new Map();
|
||||||
/**
|
/**
|
||||||
* 개별 봇 스케줄 등록
|
* 개별 봇 스케줄 등록
|
||||||
*/
|
*/
|
||||||
export function registerBot(botId, intervalMinutes = 2) {
|
export function registerBot(botId, intervalMinutes = 2, cronExpression = null) {
|
||||||
// 기존 스케줄이 있으면 제거
|
// 기존 스케줄이 있으면 제거
|
||||||
unregisterBot(botId);
|
unregisterBot(botId);
|
||||||
|
|
||||||
// cron 표현식 생성 (1분 시작, X분 간격: 1,3,5,7...)
|
// cron 표현식: 지정된 표현식 사용, 없으면 기본값 생성
|
||||||
const cronExpression = `1-59/${intervalMinutes} * * * *`;
|
const expression = cronExpression || `1-59/${intervalMinutes} * * * *`;
|
||||||
|
|
||||||
const task = cron.schedule(cronExpression, async () => {
|
const task = cron.schedule(expression, async () => {
|
||||||
console.log(`[Bot ${botId}] 동기화 시작...`);
|
console.log(`[Bot ${botId}] 동기화 시작...`);
|
||||||
try {
|
try {
|
||||||
const result = await syncNewVideos(botId);
|
const result = await syncNewVideos(botId);
|
||||||
|
|
@ -26,9 +26,7 @@ export function registerBot(botId, intervalMinutes = 2) {
|
||||||
});
|
});
|
||||||
|
|
||||||
schedulers.set(botId, task);
|
schedulers.set(botId, task);
|
||||||
console.log(
|
console.log(`[Bot ${botId}] 스케줄 등록됨 (cron: ${expression})`);
|
||||||
`[Bot ${botId}] 스케줄 등록됨 (${intervalMinutes}분 간격, 1분 오프셋)`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -48,11 +46,11 @@ export function unregisterBot(botId) {
|
||||||
export async function initScheduler() {
|
export async function initScheduler() {
|
||||||
try {
|
try {
|
||||||
const [bots] = await pool.query(
|
const [bots] = await pool.query(
|
||||||
"SELECT id, check_interval FROM bots WHERE status = 'running'"
|
"SELECT id, check_interval, cron_expression FROM bots WHERE status = 'running'"
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const bot of bots) {
|
for (const bot of bots) {
|
||||||
registerBot(bot.id, bot.check_interval);
|
registerBot(bot.id, bot.check_interval, bot.cron_expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[Scheduler] ${bots.length}개 봇 스케줄 등록됨`);
|
console.log(`[Scheduler] ${bots.length}개 봇 스케줄 등록됨`);
|
||||||
|
|
@ -72,8 +70,8 @@ export async function startBot(botId) {
|
||||||
|
|
||||||
const bot = bots[0];
|
const bot = bots[0];
|
||||||
|
|
||||||
// 스케줄 등록
|
// 스케줄 등록 (cron_expression 우선 사용)
|
||||||
registerBot(botId, bot.check_interval);
|
registerBot(botId, bot.check_interval, bot.cron_expression);
|
||||||
|
|
||||||
// 상태 업데이트
|
// 상태 업데이트
|
||||||
await pool.query(
|
await pool.query(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue