import express from "express"; import path from "path"; import { fileURLToPath } from "url"; import membersRouter from "./routes/members.js"; import albumsRouter from "./routes/albums.js"; import statsRouter from "./routes/stats.js"; import adminRouter from "./routes/admin.js"; import schedulesRouter from "./routes/schedules.js"; import { initScheduler } from "./services/youtube-scheduler.js"; import { initMeilisearch } from "./services/meilisearch.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = process.env.PORT || 80; // JSON 파싱 app.use(express.json()); // 정적 파일 서빙 (프론트엔드 빌드 결과물) app.use(express.static(path.join(__dirname, "dist"))); // API 라우트 app.get("/api/health", (req, res) => { res.json({ status: "ok", timestamp: new Date().toISOString() }); }); app.use("/api/members", membersRouter); app.use("/api/albums", albumsRouter); app.use("/api/stats", statsRouter); app.use("/api/admin", adminRouter); app.use("/api/schedules", schedulesRouter); app.use("/api/schedule-categories", (req, res, next) => { // /api/schedule-categories -> /api/schedules/categories로 리다이렉트 req.url = "/categories"; schedulesRouter(req, res, next); }); // SPA 폴백 - 모든 요청을 index.html로 app.get("*", (req, res) => { res.sendFile(path.join(__dirname, "dist", "index.html")); }); app.listen(PORT, async () => { console.log(`🌸 fromis_9 서버가 포트 ${PORT}에서 실행 중입니다`); // Meilisearch 초기화 및 동기화 try { await initMeilisearch(); console.log("🔍 Meilisearch 초기화 완료"); // 서버 시작 시 일정 데이터 자동 동기화 const { syncAllSchedules } = await import("./services/meilisearch.js"); const [schedules] = await ( await import("./lib/db.js") ).default.query(` SELECT s.id, s.title, s.description, s.date, s.time, s.category_id, s.source_url, s.source_name, c.name as category_name, c.color as category_color, GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ',') as member_names FROM schedules s LEFT JOIN schedule_categories c ON s.category_id = c.id LEFT JOIN schedule_members sm ON s.id = sm.schedule_id LEFT JOIN members m ON sm.member_id = m.id GROUP BY s.id `); const syncedCount = await syncAllSchedules(schedules); console.log(`🔍 Meilisearch ${syncedCount}개 일정 동기화 완료`); } catch (error) { console.error("Meilisearch 초기화/동기화 오류:", error); } // YouTube 봇 스케줄러 초기화 try { await initScheduler(); console.log("📺 YouTube 봇 스케줄러 초기화 완료"); } catch (error) { console.error("YouTube 스케줄러 초기화 오류:", error); } });