diff --git a/package-lock.json b/package-lock.json index ac1ee51..f93fdf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,10 @@ "@koa/cors": "^3.1.0", "@types/mongoose": "^5.11.97", "dotenv": "^10.0.0", + "formidable": "^2.0.1", "handbrake-js": "^6.0.0", "koa": "^2.13.4", + "koa-body": "^4.2.0", "koa-bodyparser": "^4.3.0", "koa-json": "^2.0.2", "koa-router": "^10.1.1", @@ -291,6 +293,14 @@ "@types/range-parser": "*" } }, + "node_modules/@types/formidable": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.5.tgz", + "integrity": "sha512-zu3mQJa4hDNubEMViSj937602XdDGzK7Q5pJ5QmLUbNxclbo9tZGt5jtwM352ssZ+pqo5V4H14TBvT/ALqQQcA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/handbrake-js": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/handbrake-js/-/handbrake-js-5.0.1.tgz", @@ -896,6 +906,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2074,6 +2089,15 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "node_modules/dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -2831,6 +2855,31 @@ "node": ">=12.20.0" } }, + "node_modules/formidable": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", + "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==", + "dependencies": { + "dezalgo": "1.0.3", + "hexoid": "1.0.0", + "once": "1.4.0", + "qs": "6.9.3" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formidable/node_modules/qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/freelist": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/freelist/-/freelist-1.0.3.tgz", @@ -3155,6 +3204,14 @@ "node": ">=8" } }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "engines": { + "node": ">=8" + } + }, "node_modules/http-assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", @@ -3849,6 +3906,36 @@ "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" } }, + "node_modules/koa-body": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz", + "integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==", + "dependencies": { + "@types/formidable": "^1.0.31", + "co-body": "^5.1.1", + "formidable": "^1.1.1" + } + }, + "node_modules/koa-body/node_modules/co-body": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz", + "integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==", + "dependencies": { + "inflation": "^2.0.0", + "qs": "^6.4.0", + "raw-body": "^2.2.0", + "type-is": "^1.6.14" + } + }, + "node_modules/koa-body/node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, "node_modules/koa-bodyparser": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", @@ -7018,6 +7105,14 @@ "@types/range-parser": "*" } }, + "@types/formidable": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.5.tgz", + "integrity": "sha512-zu3mQJa4hDNubEMViSj937602XdDGzK7Q5pJ5QmLUbNxclbo9tZGt5jtwM352ssZ+pqo5V4H14TBvT/ALqQQcA==", + "requires": { + "@types/node": "*" + } + }, "@types/handbrake-js": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/handbrake-js/-/handbrake-js-5.0.1.tgz", @@ -7486,6 +7581,11 @@ "es-abstract": "^1.19.0" } }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -8287,6 +8387,15 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -8881,6 +8990,24 @@ "fetch-blob": "^3.1.2" } }, + "formidable": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", + "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==", + "requires": { + "dezalgo": "1.0.3", + "hexoid": "1.0.0", + "once": "1.4.0", + "qs": "6.9.3" + }, + "dependencies": { + "qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==" + } + } + }, "freelist": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/freelist/-/freelist-1.0.3.tgz", @@ -9102,6 +9229,11 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" + }, "http-assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", @@ -9610,6 +9742,34 @@ "vary": "^1.1.2" } }, + "koa-body": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz", + "integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==", + "requires": { + "@types/formidable": "^1.0.31", + "co-body": "^5.1.1", + "formidable": "^1.1.1" + }, + "dependencies": { + "co-body": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz", + "integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==", + "requires": { + "inflation": "^2.0.0", + "qs": "^6.4.0", + "raw-body": "^2.2.0", + "type-is": "^1.6.14" + } + }, + "formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" + } + } + }, "koa-bodyparser": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", diff --git a/package.json b/package.json index 5ecad1c..8b48a09 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,10 @@ "@koa/cors": "^3.1.0", "@types/mongoose": "^5.11.97", "dotenv": "^10.0.0", + "formidable": "^2.0.1", "handbrake-js": "^6.0.0", "koa": "^2.13.4", + "koa-body": "^4.2.0", "koa-bodyparser": "^4.3.0", "koa-json": "^2.0.2", "koa-router": "^10.1.1", diff --git a/src/interfaces.ts b/src/interfaces.ts index b497585..ecdc65e 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -2,7 +2,7 @@ import { Schema } from 'mongoose'; export interface Room { id: string; - magnet: string; + magnet?: string; createdAt: Date; movie?: string; filename?: string; @@ -16,7 +16,7 @@ export interface Room { export const roomSchema = new Schema({ id: { type: String, required: true }, - magnet: { type: String, required: true }, + magnet: { type: String, required: false }, createdAt: { type: Date, required: true }, movie: { type: String, required: false }, filename: { type: String, required: false }, diff --git a/src/routes.ts b/src/routes.ts index e6e4380..8f7ef80 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -1,18 +1,22 @@ import Router from 'koa-router'; +import KoaBody from 'koa-body'; import short from 'short-uuid'; import WebTorrent from 'webtorrent'; import { model } from 'mongoose'; +import fs from 'fs'; import { errorResponse } from './utils'; import processDownloaded from './processDownloaded'; import { Room, roomSchema } from './interfaces'; +import type formidable from 'formidable'; const RoomModel = model('Room', roomSchema); const tCli = new WebTorrent(); const router = new Router({ prefix: '/api' }); +const koaBody = KoaBody({ multipart: true }); -router.post('/room', async (ctx) => { +router.post('/roomMagnet', async (ctx) => { if (ctx.request.body.magnet) { return new Promise(function (resolve) { tCli.add(ctx.request.body.magnet, { path: process.env.TEMP_FILES }, async function (torrent) { @@ -47,8 +51,32 @@ router.post('/room', async (ctx) => { resolve(null); }); }); + } else { + ({ status: ctx.status, body: ctx.body } = errorResponse('room-01', 'Invalid magnet link')); + } +}); + +router.post('/roomFile', koaBody, async (ctx) => { + if (ctx.request.files.file) { + const file = ctx.request.files.file as formidable.File; + const id = (short()).new(); + const room = { + id, + createdAt: new Date(), + movie: file.name, + position: 0, + syncedAt: new Date(), + downloaded: true, + filename: `${id}.mp4`, + }; + const doc = new RoomModel(room); + await doc.save(); + await fs.cpSync(file.path, `files/${id}.mp4`); + + ctx.body = room; + } else { + ({ status: ctx.status, body: ctx.body } = errorResponse('room-02', 'Invalid file')); } - ({ status: ctx.status, body: ctx.body } = errorResponse('room-01', 'Invalid magnet link')); }); router.get('/room', async (ctx) => {