@moartube/moartube-node
Version:
A free, open-source, self-hosted, anonymous, decentralized video/live stream platform. Scalable via Cloudflare, works in the cloud or from home WiFi.
1,081 lines (852 loc) • 39.5 kB
JavaScript
const express = require('express');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const {
import_POST, imported_POST, videoIdImportingStop_POST, publishing_POST, published_POST, videoIdPublishingStop_POST, videoIdUpload_POST, videoIdStream_POST, error_POST,
videoIdSourceFileExtension_POST, videoIdSourceFileExtension_GET, videoIdPublishes_GET, videoIdUnpublish_POST, videoIdData_POST, videoIdIndexAdd_POST, videoIdIndexRemove_POST,
videoIdAlias_GET, search_GET, videoIdThumbnail_POST, videoIdPreview_POST, videoIdPoster_POST, videoIdLengths_POST, videoIdData_GET, delete_POST, finalize_POST,
videoIdComments_GET, videoIdCommentsCommentId_GET, videoIdCommentsComment_POST, videoIdCommentsCommentIdDelete_DELETE, videoIdLike_POST, videoIdDislike_POST, recommended_GET,
tags_GET, tagsAll_GET, videoIdWatch_GET, videoIdReport_POST, videoIdViewsIncrement_GET, formatResolutionPublished_POST, videoIdDataAll_GET, videoIdIndexOudated_POST,
videoIdPermissions_GET, videoIdPermissions_POST, videoIdAdaptiveM3u8ManifestsMasterManifest_POST
} = require('../controllers/videos');
const {
logDebugMessageToConsole
} = require('../utils/logger');
const {
addToPublishVideoUploadingTracker, addToPublishVideoUploadingTrackerUploadRequests, isPublishVideoUploading
} = require("../utils/trackers/publish-video-uploading-tracker");
const {
getVideosDirectoryPath
} = require('../utils/paths');
const {
isSegmentNameValid, isVideoIdValid, isFormatValid, isResolutionValid
} = require('../utils/validators');
const {
submitDatabaseWriteJob
} = require('../utils/database');
const {
performAuthenticationCheck
} = require('../middleware/authentication');
const {
websocketNodeBroadcast
} = require('../utils/helpers');
const router = express.Router();
router.post('/import', performAuthenticationCheck(true), async (req, res) => {
try {
const title = req.body.title;
const description = req.body.description;
const tags = req.body.tags;
const data = await import_POST(title, description, tags);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/imported', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.body.videoId;
const data = await imported_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/importing/stop', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdImportingStop_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/publishing', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.body.videoId;
const data = await publishing_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/published', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.body.videoId;
const data = await published_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/:format/:resolution/published', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const format = req.params.format;
const resolution = req.params.resolution;
const data = await formatResolutionPublished_POST(videoId, format, resolution);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/publishing/stop', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdPublishingStop_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/upload', performAuthenticationCheck(true), async (req, res) => {
const videoId = req.params.videoId;
const format = req.query.format;
const resolution = req.query.resolution;
logDebugMessageToConsole('uploading video with id <' + videoId + '> format <' + format + '> resolution <' + resolution + '>', null, null);
const totalFileSize = parseInt(req.headers['content-length']);
if (totalFileSize > 0) {
addToPublishVideoUploadingTracker(videoId);
addToPublishVideoUploadingTrackerUploadRequests(videoId, req);
let lastPublishTimestamp = 0;
let receivedFileSize = 0;
req.on('data', function (chunk) {
if (!isPublishVideoUploading(videoId)) {
receivedFileSize += chunk.length;
const uploadProgress = Math.floor(((receivedFileSize / totalFileSize) * 100) / 2) + 50;
// rate limit due to flooding
const currentPublishTimestamp = Date.now();
if ((currentPublishTimestamp - lastPublishTimestamp > 1000) || uploadProgress === 100) {
lastPublishTimestamp = currentPublishTimestamp;
websocketNodeBroadcast({ eventName: 'echo', data: { eventName: 'video_status', payload: { type: 'publishing', videoId: videoId, format: format, resolution: resolution, progress: uploadProgress } } });
}
}
});
multer(
{
fileFilter: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'application/vnd.apple.mpegurl' || mimeType === 'video/mp2t' || mimeType === 'video/mp4' || mimeType === 'video/webm' || mimeType === 'video/ogg') {
cb(null, true);
}
else {
cb(new Error('unsupported upload file type'));
}
},
storage: multer.diskStorage({
destination: function (req, file, cb) {
let directoryPath = '';
if (format === 'm3u8') {
const fileName = file.originalname;
const manifestFileName = 'manifest-' + resolution + '.m3u8';
if (fileName === manifestFileName) {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/adaptive/m3u8');
}
else if (isSegmentNameValid(fileName)) {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/adaptive/m3u8/' + resolution);
}
}
else if (format === 'mp4') {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/progressive/mp4');
}
else if (format === 'webm') {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/progressive/webm');
}
else if (format === 'ogv') {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/progressive/ogv');
}
if (directoryPath !== '') {
logDebugMessageToConsole('storing video with id <' + videoId + '> format <' + format + '> resolution <' + resolution + '> to directory <' + directoryPath + '>', null, null);
fs.mkdirSync(directoryPath, { recursive: true });
fs.access(directoryPath, fs.constants.F_OK, function (error) {
if (error) {
cb(new Error('directory creation error'), null);
}
else {
cb(null, directoryPath);
}
});
}
else {
cb(new Error('invalid directory path'), null);
}
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
})
}).fields([{ name: 'video_files' }])
(req, res, async function (error) {
if (error) {
logDebugMessageToConsole(null, error, new Error().stack);
await submitDatabaseWriteJob('UPDATE videos SET is_publishing = ?, is_error = ? WHERE video_id = ?', [false, true, videoId]);
res.send({ isError: true, message: 'video upload error' });
}
else {
try {
const data = await videoIdUpload_POST(videoId, format, resolution);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
}
});
}
else {
await submitDatabaseWriteJob('UPDATE videos SET is_publishing = ?, is_error = ? WHERE video_id = ?', [false, true, videoId]);
res.send({ isError: true, message: 'invalid content-length' });
}
});
router.post('/:videoId/stream', performAuthenticationCheck(true), async (req, res) => {
const videoId = req.params.videoId;
const format = req.query.format;
const resolution = req.query.resolution;
if (isVideoIdValid(videoId, false) && isFormatValid(format) && isResolutionValid(resolution)) {
const manifestFileName = 'manifest-' + resolution + '.m3u8';
multer(
{
fileFilter: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'application/vnd.apple.mpegurl' || mimeType === 'video/mp2t') {
cb(null, true);
}
else {
cb(new Error('only application/vnd.apple.mpegurl and video/mp2t files are supported'));
}
},
storage: multer.diskStorage({
destination: function (req, file, cb) {
let directoryPath = '';
if (format === 'm3u8') {
const fileName = file.originalname;
if (fileName === manifestFileName) {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/adaptive/m3u8');
}
else if (isSegmentNameValid(fileName)) {
directoryPath = path.join(getVideosDirectoryPath(), videoId + '/adaptive/m3u8/' + resolution);
}
}
if (directoryPath !== '') {
//logDebugMessageToConsole('storing stream with id <' + videoId + '> format <' + format + '> resolution <' + resolution + '> to directory <' + directoryPath + '>', null, null);
fs.mkdirSync(directoryPath, { recursive: true });
cb(null, directoryPath);
}
else {
cb(new Error('invalid directory path'), null);
}
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
})
}).fields([{ name: 'video_files' }])
(req, res, async function (error) {
if (error) {
logDebugMessageToConsole(null, error, new Error().stack);
await submitDatabaseWriteJob('UPDATE videos SET is_error = ? WHERE video_id = ?', [true, videoId]);
res.send({ isError: true, message: 'video upload error' });
}
else {
try {
const data = await videoIdStream_POST(videoId, format, resolution);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
}
});
}
else {
await submitDatabaseWriteJob('UPDATE videos SET is_error = ? WHERE video_id = ?', [true, videoId]);
res.send({ isError: true, message: 'invalid parameters' });
}
});
router.post('/error', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.body.videoId;
const data = await error_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/sourceFileExtension', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const sourceFileExtension = req.body.sourceFileExtension;
const data = await videoIdSourceFileExtension_POST(videoId, sourceFileExtension);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/sourceFileExtension', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdSourceFileExtension_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/publishes', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdPublishes_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/unpublish', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const format = req.body.format;
const resolution = req.body.resolution;
const data = await videoIdUnpublish_POST(videoId, format, resolution);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/data', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const title = req.body.title;
const description = req.body.description;
const tags = req.body.tags;
const data = await videoIdData_POST(videoId, title, description, tags);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/index/add', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const containsAdultContent = req.body.containsAdultContent;
const termsOfServiceAgreed = req.body.termsOfServiceAgreed;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const data = await videoIdIndexAdd_POST(videoId, containsAdultContent, termsOfServiceAgreed, cloudflareTurnstileToken);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/index/remove', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const data = await videoIdIndexRemove_POST(videoId, cloudflareTurnstileToken);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/index/outdated', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdIndexOudated_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/alias', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdAlias_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/search', performAuthenticationCheck(false), async (req, res) => {
try {
const searchTerm = req.query.searchTerm;
const sortTerm = req.query.sortTerm;
const tagTerm = req.query.tagTerm;
const tagLimit = req.query.tagLimit;
const timestamp = req.query.timestamp;
const data = await search_GET(searchTerm, sortTerm, tagTerm, tagLimit, timestamp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/images/thumbnail', performAuthenticationCheck(true), (req, res) => {
const videoId = req.params.videoId;
if (isVideoIdValid(videoId, false)) {
//logDebugMessageToConsole('uploading thumbnail for video id: ' + videoId, null, null);
multer(
{
fileFilter: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
cb(null, true);
}
else {
cb(new Error('unsupported upload file type'));
}
},
storage: multer.diskStorage({
destination: function (req, file, cb) {
const filePath = path.join(getVideosDirectoryPath(), videoId + '/images');
fs.access(filePath, fs.constants.F_OK, function (error) {
if (error) {
cb(new Error('file upload error'), null);
}
else {
cb(null, filePath);
}
});
},
filename: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
let extension;
if (mimeType === 'image/jpeg') {
extension = '.jpg';
}
const fileName = 'thumbnail' + extension;
cb(null, fileName);
}
else {
cb(new Error('Invalid Media Detected'), null);
}
}
})
}).fields([{ name: 'thumbnailFile', maxCount: 1 }])
(req, res, async function (error) {
if (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: error.message });
}
else {
try {
//logDebugMessageToConsole('uploaded thumbnail for video id <' + videoId + '>', null, null);
const data = videoIdThumbnail_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
}
});
}
else {
res.send({ isError: true, message: 'invalid parameters' });
}
});
router.post('/:videoId/images/preview', performAuthenticationCheck(true), (req, res) => {
const videoId = req.params.videoId;
if (isVideoIdValid(videoId, false)) {
multer(
{
fileFilter: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
cb(null, true);
}
else {
cb(new Error('unsupported upload file type'));
}
},
storage: multer.diskStorage({
destination: function (req, file, cb) {
const filePath = path.join(getVideosDirectoryPath(), videoId + '/images');
fs.access(filePath, fs.constants.F_OK, function (error) {
if (error) {
cb(new Error('file upload error'), null);
}
else {
cb(null, filePath);
}
});
},
filename: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
let extension;
if (mimeType === 'image/jpeg') {
extension = '.jpg';
}
const fileName = 'preview' + extension;
cb(null, fileName);
}
else {
cb(new Error('Invalid Media Detected'), null);
}
}
})
}).fields([{ name: 'previewFile', maxCount: 1 }])
(req, res, async function (error) {
if (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: error.message });
}
else {
try {
//logDebugMessageToConsole('uploaded preview for video id <' + videoId + '>', null, null);
const data = await videoIdPreview_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
}
});
}
else {
res.send({ isError: true, message: 'invalid parameters' });
}
});
router.post('/:videoId/images/poster', performAuthenticationCheck(true), (req, res) => {
const videoId = req.params.videoId;
if (isVideoIdValid(videoId, false)) {
multer(
{
fileFilter: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
cb(null, true);
}
else {
cb(new Error('unsupported upload file type'));
}
},
storage: multer.diskStorage({
destination: function (req, file, cb) {
const filePath = path.join(getVideosDirectoryPath(), videoId + '/images');
fs.access(filePath, fs.constants.F_OK, function (error) {
if (error) {
cb(new Error('file upload error'), null);
}
else {
cb(null, filePath);
}
});
},
filename: function (req, file, cb) {
const mimeType = file.mimetype;
if (mimeType === 'image/jpeg') {
let extension;
if (mimeType === 'image/jpeg') {
extension = '.jpg';
}
const fileName = 'poster' + extension;
cb(null, fileName);
}
else {
cb(new Error('Invalid Media Detected'), null);
}
}
})
}).fields([{ name: 'posterFile', maxCount: 1 }])
(req, res, async function (error) {
if (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: error.message });
}
else {
try {
//logDebugMessageToConsole('uploaded poster for video id <' + videoId + '>', null, null);
const data = videoIdPoster_POST(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
}
});
}
else {
res.send({ isError: true, message: 'invalid parameters' });
}
});
router.post('/:videoId/lengths', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const lengthSeconds = req.body.lengthSeconds;
const lengthTimestamp = req.body.lengthTimestamp;
const data = await videoIdLengths_POST(videoId, lengthSeconds, lengthTimestamp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/data', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdData_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/data/all', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdDataAll_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/delete', performAuthenticationCheck(true), async (req, res) => {
try {
const videoIds = req.body.videoIds;
const data = await delete_POST(videoIds);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/finalize', performAuthenticationCheck(true), async (req, res) => {
try {
const videoIds = req.body.videoIds;
const data = await finalize_POST(videoIds);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/comments', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const type = req.query.type;
const sort = req.query.sort;
const timestamp = req.query.timestamp;
const data = await videoIdComments_GET(videoId, type, sort, timestamp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/comments/:commentId', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const commentId = req.params.commentId;
const data = await videoIdCommentsCommentId_GET(videoId, commentId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/comments/comment', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const commentPlainText = req.body.commentPlainText;
const timestamp = req.body.timestamp;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const cloudflareConnectingIp = req.header('CF-Connecting-IP');
const data = await videoIdCommentsComment_POST(videoId, commentPlainText, timestamp, cloudflareTurnstileToken, cloudflareConnectingIp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.delete('/:videoId/comments/:commentId/delete', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const commentId = req.params.commentId;
const timestamp = req.query.timestamp;
const data = await videoIdCommentsCommentIdDelete_DELETE(videoId, commentId, timestamp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/like', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const cloudflareConnectingIp = req.header('CF-Connecting-IP');
const data = await videoIdLike_POST(videoId, cloudflareTurnstileToken, cloudflareConnectingIp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/dislike', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const cloudflareConnectingIp = req.header('CF-Connecting-IP');
const data = await videoIdDislike_POST(videoId, cloudflareTurnstileToken, cloudflareConnectingIp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/recommended', performAuthenticationCheck(false), async (req, res) => {
try {
const data = await recommended_GET();
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/tags', performAuthenticationCheck(false), async (req, res) => {
try {
const data = await tags_GET();
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/tags/all', performAuthenticationCheck(false), async (req, res) => {
try {
const data = await tagsAll_GET();
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/report', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const email = req.body.email;
const reportType = req.body.reportType;
const message = req.body.message;
const cloudflareTurnstileToken = req.body.cloudflareTurnstileToken;
const cloudflareConnectingIp = req.header('CF-Connecting-IP');
const data = await videoIdReport_POST(videoId, email, reportType, message, cloudflareTurnstileToken, cloudflareConnectingIp);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/views/increment', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdViewsIncrement_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/watch', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdWatch_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/adaptive/m3u8/:type/manifests/masterManifest', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const type = req.params.type;
const masterManifest = req.body.masterManifest;
const data = await videoIdAdaptiveM3u8ManifestsMasterManifest_POST(videoId, type, masterManifest);
res.send(data);
}
catch(error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.get('/:videoId/permissions', performAuthenticationCheck(false), async (req, res) => {
try {
const videoId = req.params.videoId;
const data = await videoIdPermissions_GET(videoId);
res.send(data);
}
catch (error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
router.post('/:videoId/permissions', performAuthenticationCheck(true), async (req, res) => {
try {
const videoId = req.params.videoId;
const type = req.body.type;
const isEnabled = req.body.isEnabled;
const data = await videoIdPermissions_POST(videoId, type, isEnabled);
res.send(data);
}
catch(error) {
logDebugMessageToConsole(null, error, new Error().stack);
res.send({ isError: true, message: 'error communicating with the MoarTube node' });
}
});
module.exports = router;