import {getClient} from "../utils/database.js"; import * as path from "node:path"; import * as fs from "node:fs"; import { fileURLToPath } from 'url'; import { dirname } from 'path'; import jwt from "jsonwebtoken"; import {query} from "express-validator"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); export async function upload(req, res) { const fileBuffer = req.file.buffer; let isGenerate = false; while (isGenerate === false) { const client = await getClient(); let letters = "0123456789ABCDEF"; let hex = ''; for (let i = 0; i < 16; i++) hex += letters[(Math.floor(Math.random() * 16))]; const query = `SELECT * FROM videos WHERE slug='${hex}'`; const result = await client.query(query); client.end(); if (result.rows.length === 0) { isGenerate = true; req.body.slug = hex; } } const finalName = req.body.slug + "." + req.file.originalname.split(".")[1]; const destinationPath = path.join(__dirname, "../uploads/videos/" + finalName) fs.writeFileSync(destinationPath, fileBuffer); const client = await getClient(); const video = { title: req.body.title, description: req.body.description, //TODO thumbnail file: "/api/media/video/" + finalName, channel: req.body.channel, slug: req.body.slug, format: req.file.originalname.split(".")[1], visibility: req.body.visibility, } const logger = req.body.logger; logger.write("try to upload video"); const releaseDate = new Date(Date.now()).toISOString(); const query = `INSERT INTO videos (title, thumbnail, description, channel, visibility, file, slug, format, release_date) VALUES ('${video.title}', 'null', '${video.description}', '${video.channel}', '${video.visibility}', '${video.file}', '${video.slug}', '${video.format}', '${releaseDate}')`; await client.query(query); logger.write("successfully uploaded video", 200); res.status(200).json({"message": "Successfully uploaded video"}); } export async function uploadThumbnail(req, res) { const fileBuffer = req.file.buffer; const client = await getClient(); const videoId = req.body.video; const videoSlugQuery = `SELECT * from videos WHERE id = ${videoId}`; const result = await client.query(videoSlugQuery); const fileName = result.rows[0].slug + "." + req.file.originalname.split(".")[1]; const destinationPath = path.join(__dirname, "../uploads/thumbnails/", fileName); fs.writeFileSync(destinationPath, fileBuffer); const logger = req.body.logger; logger.action("try to add thumbnail to video " + req.body.video); const file = "/api/media/thumbnail/" + fileName; const updateQuery = `UPDATE videos SET thumbnail = '${file}' WHERE id = ${req.body.video}`; await client.query(updateQuery); logger.write("successfully uploaded thumbnail", 200); res.status(200).json({"message": "Successfully uploaded thumbnail"}); } export async function getById(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to get video " + id); const client = await getClient(); const query = `SELECT * FROM videos WHERE id = ${id}`; const result = await client.query(query); const video = result.rows[0]; logger.write("successfully get video " + id, 200); res.status(200).json(video); } export async function getByChannel(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to get video from channel " + id); const client = await getClient(); const query = `SELECT * FROM videos WHERE channel = ${id}`; const result = await client.query(query); logger.write("successfully get video from channel " + id, 200); res.status(200).json(result.rows); } export async function update(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to update video " + id); const client = await getClient(); const query = `UPDATE videos SET title='${req.body.title}', description:'${req.body.description}', visibility:'${req.body.visibility}'`; await client.query(query); logger.write("successfully updated video", 200); res.status(200).json({"message": "Successfully updated video"}); } export async function updateVideo(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to update video file " + id); const client = await getClient(); const videoQuery = `SELECT slug, format FROM videos WHERE id = ${id}`; const videoResult = await client.query(videoQuery); const video = videoResult.rows[0]; const slug = video.slug; const format = video.format; const pathToDelete = path.join(__dirname, "../uploads/videos/", slug + "." + format ); fs.unlink(pathToDelete, (error) => { if (error) { logger.write(error, 500); res.status(500).json({"message": "Failed to delete video"}); return } logger.action("successfully deleted video " + slug + "." + format ); const fileBuffer = req.file.buffer; const finalName = slug + "." + format; const destinationPath = path.join(__dirname, "../uploads/videos/" + finalName) fs.writeFileSync(destinationPath, fileBuffer); logger.write("successfully updated video", 200); res.status(200).json({"message": "Successfully updated video"}); }) } export async function del(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to delete video " + id); const client = await getClient(); const query = `SELECT slug, format, thumbnail FROM videos WHERE id = ${id}`; const result = await client.query(query); const video = result.rows[0]; const slug = video.slug; const format = video.format; const thumbnailFile = video.thumbnail.split("/")[4]; let pathToDelete = path.join(__dirname, "../uploads/videos/", slug + "." + format); fs.unlink(pathToDelete, (error) => { if (error) { logger.write(error, 500); res.status(500).json({"message": "Failed to delete video"}); return } pathToDelete = path.join(__dirname, "../uploads/thumbnails/", thumbnailFile); fs.unlink(pathToDelete, async (error) => { if (error) { logger.write(error, 500); res.status(500).json({"message": "Failed to delete video"}); return } const query = `DELETE FROM videos WHERE id = ${id}`; await client.query(query); logger.write("successfully deleted video", 200); res.status(200).json({"message": "Successfully deleted video"}); }) }) } export async function toggleLike(req, res) { const id = req.params.id; const logger = req.body.logger; logger.action("try to toggle like on video " + id); const token = req.headers.authorization.split(" ")[1]; const claims = jwt.decode(token); const client = await getClient(); const userId = claims.id; const getLikeQuery = `SELECT * FROM likes WHERE owner = ${userId} AND video = ${id}`; const likeResult = await client.query(getLikeQuery); if (likeResult.rows.length === 0) { const query = `INSERT INTO likes (video, owner) VALUES (${id},${userId})`; await client.query(query); logger.write("no likes found adding likes for video " + id, 200); res.status(200).json({"message": "Successfully added like"}); } else { const query = `DELETE FROM likes WHERE owner = ${userId} AND video = ${id}`; await client.query(query); logger.write("likes found, removing like for video " + id, 200); res.status(200).json({"message": "Successfully removed like"}); } } export async function addTags(req, res) { const tags = req.body.tags; const videoId = req.params.id; const logger = req.body.logger; logger.action("try to add tags to video " + videoId); const client = await getClient(); // DECREASE USAGE COUNT FOR ALL TAGS const decreaseUsageCountQuery = `UPDATE tags SET usage_count = usage_count - 1 WHERE id IN (SELECT tag FROM video_tags WHERE video = ${videoId})`; await client.query(decreaseUsageCountQuery); // DELETE ALL TAGS FOR VIDEO let deleteQuery = `DELETE FROM video_tags WHERE video = ${videoId}`; await client.query(deleteQuery); // INSERT NEW TAGS for (const tag of tags) { const tagQuery = `SELECT * FROM tags WHERE name = '${tag}'`; const tagResult = await client.query(tagQuery); let id = null; if (tagResult.rows.length === 0) { const insertTagQuery = `INSERT INTO tags (name, usage_count) VALUES ('${tag}', 1) RETURNING id`; const result = await client.query(insertTagQuery); id = result.rows[0].id; } else { logger.write("Tag " + tag + " already exists for video " + videoId, 200); const getTagQuery = `SELECT usage_count FROM tags WHERE name = '${tag}'`; const getTagResult = await client.query(getTagQuery); const usageCount = getTagResult.rows[0].usage_count + 1; const updateTagQuery = `UPDATE tags SET usage_count = ${usageCount} WHERE name = '${tag}'`; await client.query(updateTagQuery); id = tagResult.rows[0].id; } console.log("Tag ID: ", id); console.log("Video ID: ", videoId); // INSERT INTO video_tags const insertVideoTagQuery = `INSERT INTO video_tags (tag, video) VALUES (${id}, ${videoId})`; await client.query(insertVideoTagQuery); } logger.write("successfully added tags to video " + videoId, 200); await client.end(); res.status(200).json({"message": "Successfully added tags to video"}); }