changemaker.lite/api/dist/modules/media/routes/video-schedule.routes.js

266 lines
10 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.videoScheduleRoutes = videoScheduleRoutes;
const database_1 = require("../../../config/database");
const auth_1 = require("../middleware/auth");
const video_schedule_queue_service_1 = require("../../../services/video-schedule-queue.service");
const logger_1 = require("../../../utils/logger");
const zod_1 = require("zod");
// Validation schemas
const schedulePublishSchema = zod_1.z.object({
publishAt: zod_1.z.string().datetime(),
timezone: zod_1.z.string().optional().default('UTC'),
});
const scheduleUnpublishSchema = zod_1.z.object({
unpublishAt: zod_1.z.string().datetime(),
timezone: zod_1.z.string().optional().default('UTC'),
});
async function videoScheduleRoutes(fastify) {
/**
* POST /videos/:id/schedule-publish
* Schedule a video to be published at a specific time
*/
fastify.post('/:id/schedule-publish', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
const videoId = parseInt(request.params.id);
const { publishAt, timezone } = request.body;
// Validate input
try {
schedulePublishSchema.parse(request.body);
}
catch (error) {
return reply.code(400).send({ message: 'Invalid input', error });
}
try {
// Verify video exists
const video = await database_1.prisma.video.findUnique({
where: { id: videoId },
});
if (!video) {
return reply.code(404).send({ message: 'Video not found' });
}
// Parse publish time
const publishDate = new Date(publishAt);
const now = new Date();
if (publishDate <= now) {
return reply.code(400).send({ message: 'Publish time must be in the future' });
}
// Get user ID from request (set by auth middleware)
const userId = request.user?.id;
if (!userId) {
return reply.code(401).send({ message: 'Unauthorized' });
}
// Schedule the publish
const result = await video_schedule_queue_service_1.videoScheduleQueueService.schedulePublish(videoId, publishDate, userId);
logger_1.logger.info(`Scheduled video ${videoId} to publish at ${publishDate.toISOString()}`);
return {
success: true,
message: 'Video scheduled for publish',
scheduledFor: result.scheduledFor,
jobId: result.jobId,
};
}
catch (error) {
logger_1.logger.error('Failed to schedule video publish', { error, videoId });
return reply.code(500).send({
message: error instanceof Error ? error.message : 'Failed to schedule video',
});
}
});
/**
* POST /videos/:id/schedule-unpublish
* Schedule a video to be unpublished at a specific time
*/
fastify.post('/:id/schedule-unpublish', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
const videoId = parseInt(request.params.id);
const { unpublishAt, timezone } = request.body;
// Validate input
try {
scheduleUnpublishSchema.parse(request.body);
}
catch (error) {
return reply.code(400).send({ message: 'Invalid input', error });
}
try {
// Verify video exists
const video = await database_1.prisma.video.findUnique({
where: { id: videoId },
});
if (!video) {
return reply.code(404).send({ message: 'Video not found' });
}
// Parse unpublish time
const unpublishDate = new Date(unpublishAt);
const now = new Date();
if (unpublishDate <= now) {
return reply.code(400).send({ message: 'Unpublish time must be in the future' });
}
// Get user ID from request
const userId = request.user?.id;
if (!userId) {
return reply.code(401).send({ message: 'Unauthorized' });
}
// Schedule the unpublish
const result = await video_schedule_queue_service_1.videoScheduleQueueService.scheduleUnpublish(videoId, unpublishDate, userId);
logger_1.logger.info(`Scheduled video ${videoId} to unpublish at ${unpublishDate.toISOString()}`);
return {
success: true,
message: 'Video scheduled for unpublish',
scheduledFor: result.scheduledFor,
jobId: result.jobId,
};
}
catch (error) {
logger_1.logger.error('Failed to schedule video unpublish', { error, videoId });
return reply.code(500).send({
message: error instanceof Error ? error.message : 'Failed to schedule video',
});
}
});
/**
* DELETE /videos/:id/schedule/:action
* Cancel a scheduled publish or unpublish
*/
fastify.delete('/:id/schedule/:action', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
const videoId = parseInt(request.params.id);
const action = request.params.action;
if (!['publish', 'unpublish'].includes(action)) {
return reply.code(400).send({ message: 'Invalid action. Must be "publish" or "unpublish"' });
}
try {
await video_schedule_queue_service_1.videoScheduleQueueService.cancelSchedule(videoId, action);
logger_1.logger.info(`Cancelled ${action} schedule for video ${videoId}`);
return {
success: true,
message: `${action} schedule cancelled`,
};
}
catch (error) {
logger_1.logger.error(`Failed to cancel ${action} schedule`, { error, videoId });
return reply.code(500).send({
message: `Failed to cancel ${action} schedule`,
});
}
});
/**
* GET /videos/schedules/upcoming
* Get all upcoming scheduled publish/unpublish operations
*/
fastify.get('/schedules/upcoming', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
const limit = parseInt(request.query.limit || '50');
try {
const schedules = await video_schedule_queue_service_1.videoScheduleQueueService.getUpcomingSchedules(limit);
return {
schedules,
total: schedules.length,
};
}
catch (error) {
logger_1.logger.error('Failed to get upcoming schedules', { error });
return reply.code(500).send({ message: 'Failed to fetch schedules' });
}
});
/**
* GET /videos/:id/schedule-history
* Get schedule history for a specific video
*/
fastify.get('/:id/schedule-history', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
const videoId = parseInt(request.params.id);
const limit = parseInt(request.query.limit || '10');
try {
const history = await video_schedule_queue_service_1.videoScheduleQueueService.getScheduleHistory(videoId, limit);
return {
videoId,
history,
};
}
catch (error) {
logger_1.logger.error('Failed to get schedule history', { error, videoId });
return reply.code(500).send({ message: 'Failed to fetch schedule history' });
}
});
/**
* GET /videos/schedules/stats
* Get queue statistics
*/
fastify.get('/schedules/stats', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
try {
const stats = await video_schedule_queue_service_1.videoScheduleQueueService.getStats();
return stats;
}
catch (error) {
logger_1.logger.error('Failed to get schedule stats', { error });
return reply.code(500).send({ message: 'Failed to fetch stats' });
}
});
/**
* POST /videos/schedules/pause
* Pause the schedule queue
*/
fastify.post('/schedules/pause', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
try {
await video_schedule_queue_service_1.videoScheduleQueueService.pause();
return {
success: true,
message: 'Schedule queue paused',
};
}
catch (error) {
logger_1.logger.error('Failed to pause schedule queue', { error });
return reply.code(500).send({ message: 'Failed to pause queue' });
}
});
/**
* POST /videos/schedules/resume
* Resume the schedule queue
*/
fastify.post('/schedules/resume', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
try {
await video_schedule_queue_service_1.videoScheduleQueueService.resume();
return {
success: true,
message: 'Schedule queue resumed',
};
}
catch (error) {
logger_1.logger.error('Failed to resume schedule queue', { error });
return reply.code(500).send({ message: 'Failed to resume queue' });
}
});
/**
* POST /videos/schedules/cleanup
* Clean up old completed jobs
*/
fastify.post('/schedules/cleanup', {
preHandler: auth_1.requireAdminRole,
}, async (request, reply) => {
try {
const cleaned = await video_schedule_queue_service_1.videoScheduleQueueService.cleanup();
return {
success: true,
message: `Cleaned ${cleaned} old jobs`,
cleaned,
};
}
catch (error) {
logger_1.logger.error('Failed to cleanup schedule queue', { error });
return reply.code(500).send({ message: 'Failed to cleanup queue' });
}
});
}
//# sourceMappingURL=video-schedule.routes.js.map