diff --git a/.gitignore b/.gitignore index 9417727..ad25643 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /node_modules /db /package-lock.json -/uploads \ No newline at end of file +/uploads +/videos \ No newline at end of file diff --git a/client/player.js b/client/player.js new file mode 100644 index 0000000..cb6e4dc --- /dev/null +++ b/client/player.js @@ -0,0 +1,19 @@ +import Route from "../route.js"; +import auth from "../form/auth.js"; +import initDb from "../db.js"; + +let db = await initDb(); + +let main = new Route([auth], async function (req, res, input) { + let { username } = input; + let videoData = await db.all('SELECT * FROM video WHERE id = ?', [ + req.query.id + ]); + videoData = videoData[0]; + return res.render('player', { + username, + videoData + }); +}); + +export default main; \ No newline at end of file diff --git a/client/upload.js b/client/upload.js new file mode 100644 index 0000000..1af2ec0 --- /dev/null +++ b/client/upload.js @@ -0,0 +1,19 @@ +import Route from "../route.js"; +import auth from "../form/auth.js"; + +// TODO: rewrite +let main = new Route([auth], async function (req, res, input) { + let { username } = input; + return res.render('form', { + data: [ + { label: "Video file", type: "file", name: "file" }, + { label: "Name", type: "text", name: "title" }, + { label: "Description", type: "text", name: "desc" } + ], + 'route': '/api/upload/upload', + 'title': 'Upload Content', + username + }); +}); + +export default main; \ No newline at end of file diff --git a/db.js b/db.js index a492276..51338de 100644 --- a/db.js +++ b/db.js @@ -14,6 +14,8 @@ async function initDb() { await db.run(`CREATE TABLE IF NOT EXISTS auth (username TEXT, password TEXT);`); await db.run(`CREATE TABLE IF NOT EXISTS token (username TEXT, token TEXT);`); + await db.run(`CREATE TABLE IF NOT EXISTS video (id TEXT, title TEXT, desc TEXT, username TEXT);`); + return db; } diff --git a/form/upload.js b/form/upload.js new file mode 100644 index 0000000..a6b9193 --- /dev/null +++ b/form/upload.js @@ -0,0 +1,38 @@ +import Route from "../route.js"; +import initDb from "../db.js"; +import { randomUUID } from 'node:crypto'; +import {exec} from 'node:child_process'; +import { promisify } from "node:util"; +import auth from "../form/auth.js"; + +const execP = promisify(exec); + +let db = await initDb(); + +// TODO: rewrite +let main = new Route([auth], async function (req, res, input) { + let { username } = input; + let id = randomUUID(); + + let { title, desc } = req.body; + if (!title || !desc || !req.file) return { 'success': false, 'message': 'Some fields are missing' }; // probably should not re-use these strings + + let {path} = req.file; + + try { + await execP(`ffmpeg -i ${path} videos/${id}.mp4`); + } catch (err) { + return { 'success': false, 'message': 'Video is invalid'} + } + + await db.run('INSERT INTO video (id, title, desc, username) VALUES (?, ?, ?, ?)', [ + id, + title, + desc, + username + ]); + + return { 'message': 'Video created', 'success': true, 'redirect': '/client/video?id='+id }; +}); + +export default main; \ No newline at end of file diff --git a/index.js b/index.js index 91ae539..4386d51 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,7 @@ const upload = multer({ dest: 'uploads/' }); app.use(cookieParser()); app.use('/static', express.static('static')); +app.use('/videos', express.static('videos')); app.engine('.ejs', ejs.__express); app.set('views', './views'); app.set('view engine', 'ejs'); @@ -31,6 +32,10 @@ app.post('/api/form/:route', upload.none(), async (req, res) => { res.send(await iterate(req, res, 'form')); }) +app.post('/api/upload/:route', upload.single('file'), async (req, res) => { + res.send(await iterate(req, res, 'form')); +}) + app.listen(port, () => { console.log(`App listening on port ${port}`) }) \ No newline at end of file diff --git a/routes.js b/routes.js index 09e22cb..f59c1b3 100644 --- a/routes.js +++ b/routes.js @@ -2,25 +2,31 @@ import main from "./client/main.js"; import auth from "./form/auth.js"; import login from "./client/login.js"; import register from "./client/register.js"; +import upload from "./client/upload.js"; +import player from "./client/player.js"; import loginB from "./form/login.js"; import registerB from "./form/register.js"; +import uploadB from "./form/upload.js"; const routes = { get: {}, form: {}, - client: {} + client: {}, }; routes.client = { main, login, - register + register, + upload, + video: player } routes.get = { }; routes.form = { login: loginB, register: registerB, + upload: uploadB, auth }; diff --git a/static/img/logo.svg b/static/img/logo.svg index 7cdd5f4..aa8099b 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -27,10 +27,10 @@ inkscape:zoom="2.8284272" inkscape:cx="123.39013" inkscape:cy="141.77491" - inkscape:window-width="1860" - inkscape:window-height="1004" - inkscape:window-x="30" - inkscape:window-y="46" + inkscape:window-width="1499" + inkscape:window-height="1080" + inkscape:window-x="0" + inkscape:window-y="16" inkscape:window-maximized="1" inkscape:current-layer="layer1" showgrid="false" /> @@ -44,8 +44,8 @@ offset="0" id="stop6" /> - - - - - - - - - diff --git a/static/main.css b/static/main.css index 110ecfc..a677b0c 100644 --- a/static/main.css +++ b/static/main.css @@ -109,4 +109,8 @@ form { .header img { height: 2em; +} + +video { + width: 690px; } \ No newline at end of file diff --git a/views/header_block.ejs b/views/header_block.ejs index 5eddb5c..f0871ef 100644 --- a/views/header_block.ejs +++ b/views/header_block.ejs @@ -4,8 +4,11 @@ <%if (username=='!nobody' ) { %> <% } else { %> - + <%= username %> + + Upload + <% } %> \ No newline at end of file diff --git a/views/player.ejs b/views/player.ejs new file mode 100644 index 0000000..347c0d2 --- /dev/null +++ b/views/player.ejs @@ -0,0 +1,14 @@ +<%- include('header.ejs') -%> +
+

Video

+ +
+ <%= videoData.title %> + +
+
by + <%= videoData.username %> +
+ +
+ <%- include('footer.ejs') -%> \ No newline at end of file