import response from "../response.js"; import models from "../models/index.js"; import { clearFileBuffers, saveFileToDisk, generateHash, } from "../middlewares/uploadLevel.js"; import fs from "fs"; import path from "path"; import crypto from "crypto"; export const getAllLevels = async (req, res) => { try { const levels = await models.Level.findAll(); response(200, levels, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving levels data!", res); } }; export const getAllLevelById = async (req, res) => { try { const { id } = req.params; const level = await models.Level.findByPk(id); if (!level) { return response(404, null, "Level not found", res); } response(200, level, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getLevels = async (req, res) => { try { const levels = await models.Level.findAll({ attributes: { exclude: ["route1", "route2", "route3", "route4"], }, }); response(200, levels, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getLevelById = async (req, res) => { try { const { id } = req.params; const level = await models.Level.findByPk(id, { attributes: { exclude: ["route1", "route2", "route3", "route4"], }, }); if (!level) { return response(404, null, "Level not found", res); } response(200, level, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const createLevel = async (req, res) => { const { title, subject_id, topic_id, is_pretest, content, youtube } = req.body; // Files to be saved if everything else is okay const { video, audio, image } = req.filesToSave || {}; // Validate title if (!title) { clearFileBuffers({ video, audio, image }); return response(400, null, "Title is required", res); } // Validate subject_id if (!subject_id) { clearFileBuffers({ video, audio, image }); return response(400, null, "Subject ID is required", res); } // Validate topic_id if (!topic_id) { clearFileBuffers({ video, audio, image }); return response(400, null, "Topic ID is required", res); } try { // Check if the title already exists under the same topic_id const existingLevel = await models.Level.findOne({ where: { title, topic_id }, }); if (existingLevel) { clearFileBuffers({ video, audio, image }); return response( 409, null, "A level with this title already exists under this topic", res ); // 409 Conflict } // Save files to disk const videoFilename = video ? saveFileToDisk(video, "video", title, topic_id, subject_id) : null; const audioFilename = audio ? saveFileToDisk(audio, "audio", title, topic_id, subject_id) : null; const imageFilename = image ? saveFileToDisk(image, "image", title, topic_id, subject_id) : null; // Create the new level const newLevel = await models.Level.create({ title, subject_id, topic_id, is_pretest: is_pretest || 0, content, video: videoFilename, audio: audioFilename, image: imageFilename, youtube, route1: 0, route2: 0, route3: 0, route4: 0, }); // Update routes with the newly created level's ID await newLevel.update({ route1: newLevel.id, route2: newLevel.id, route3: newLevel.id, route4: newLevel.id, }); response(201, newLevel, "Level created successfully", res); } catch (error) { console.log(error); clearFileBuffers({ video, audio, image }); return response(500, null, "Internal Server Error", res); } }; export const updateLevelById = async (req, res) => { const { id } = req.params; const { title, subject_id, topic_id, is_pretest, content, youtube } = req.body; // Files to be saved if everything else is okay const { video, audio, image } = req.filesToSave || {}; try { // Find the existing level by ID const level = await models.Level.findByPk(id); if (!level) { clearFileBuffers({ video, audio, image }); return response(404, null, "Level not found", res); } // Check if a level with the same title under the same topic already exists if (title && topic_id) { const existingLevel = await models.Level.findOne({ where: { title, topic_id, id: { [models.Sequelize.Op.ne]: id }, // Exclude the current level from the check }, }); if (existingLevel) { clearFileBuffers({ video, audio, image }); return response( 409, null, "A level with this title already exists under this topic", res ); // 409 Conflict } } // Update level fields if (title) level.title = title; if (subject_id) level.subject_id = subject_id; if (topic_id) level.topic_id = topic_id; if (is_pretest !== undefined) level.is_pretest = is_pretest; if (content) level.content = content; if (youtube) level.youtube = youtube; // Handle video update if (video) { if (level.video) { const oldVideoPath = path.join( "public/uploads/level/video", level.video ); if (fs.existsSync(oldVideoPath)) { fs.unlinkSync(oldVideoPath); } } level.video = saveFileToDisk( video, "video", title || level.title, topic_id || level.topic_id, subject_id || level.subject_id ); } // Handle audio update if (audio) { if (level.audio) { const oldAudioPath = path.join( "public/uploads/level/audio", level.audio ); if (fs.existsSync(oldAudioPath)) { fs.unlinkSync(oldAudioPath); } } level.audio = saveFileToDisk( audio, "audio", title || level.title, topic_id || level.topic_id, subject_id || level.subject_id ); } // Handle image update if (image) { if (level.image) { const oldImagePath = path.join( "public/uploads/level/image", level.image ); if (fs.existsSync(oldImagePath)) { fs.unlinkSync(oldImagePath); } } level.image = saveFileToDisk( image, "image", title || level.title, topic_id || level.topic_id, subject_id || level.subject_id ); } await level.save(); response(200, level, "Level updated successfully", res); } catch (error) { console.log(error); clearFileBuffers({ video, audio, image }); return response(500, null, "Internal Server Error", res); } }; export const deleteLevelById = async (req, res) => { const { id } = req.params; try { // Find the existing level by ID const level = await models.Level.findByPk(id); if (!level) { return response(404, null, "Level not found", res); } // Delete associated files from disk if they exist const deleteFile = (filePath) => { if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } }; if (level.video) { const videoPath = path.join("public/uploads/level/video", level.video); deleteFile(videoPath); } if (level.audio) { const audioPath = path.join("public/uploads/level/audio", level.audio); deleteFile(audioPath); } if (level.image) { const imagePath = path.join("public/uploads/level/image", level.image); deleteFile(imagePath); } // Delete the level from the database await level.destroy(); response(200, null, "Level deleted successfully", res); } catch (error) { console.log(error); return response(500, null, "Internal Server Error", res); } }; export const getRoutes = async (req, res) => { try { const levels = await models.Level.findAll({ attributes: { exclude: [ "subject_id", "topic_id", "is_pretest", "content", "video", "audio", "image", "youtube", "ts_entri", ], }, }); response(200, levels, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getRouteById = async (req, res) => { try { const { id } = req.params; const level = await models.Level.findByPk(id, { attributes: { exclude: [ "subject_id", "topic_id", "is_pretest", "content", "video", "audio", "image", "youtube", "ts_entri", ], }, }); if (!level) { return response(404, null, "Level not found", res); } response(200, level, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const updateRouteById = async (req, res) => { const { id } = req.params; const { route1, route2, route3, route4 } = req.body; try { // Find the existing level by ID const level = await models.Level.findByPk(id); if (!level) { return response(404, null, "Level not found", res); } // Update only the route fields await level.update({ route1: route1 !== undefined ? route1 : level.route1, route2: route2 !== undefined ? route2 : level.route2, route3: route3 !== undefined ? route3 : level.route3, route4: route4 !== undefined ? route4 : level.route4, }); response(200, level, "Routes updated successfully", res); } catch (error) { console.log(error); return response(500, null, "Internal Server Error", res); } };