mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-04-05 23:41:27 +03:00
Logger is now separated into its own module
Added eslint and fixed many logic errors based on its recommendations
This commit is contained in:
18
backend/.eslintrc.json
Normal file
18
backend/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parser": "esprima",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [],
|
||||
"rules": {
|
||||
},
|
||||
"root": true
|
||||
}
|
||||
160
backend/app.js
160
backend/app.js
@@ -1,35 +1,35 @@
|
||||
const { uuid } = require('uuidv4');
|
||||
var fs = require('fs-extra');
|
||||
var { promisify } = require('util');
|
||||
var auth_api = require('./authentication/auth');
|
||||
var winston = require('winston');
|
||||
var path = require('path');
|
||||
var ffmpeg = require('fluent-ffmpeg');
|
||||
var compression = require('compression');
|
||||
var glob = require("glob")
|
||||
var multer = require('multer');
|
||||
var express = require("express");
|
||||
var bodyParser = require("body-parser");
|
||||
var archiver = require('archiver');
|
||||
var unzipper = require('unzipper');
|
||||
var db_api = require('./db');
|
||||
var utils = require('./utils')
|
||||
var mergeFiles = require('merge-files');
|
||||
const fs = require('fs-extra');
|
||||
const { promisify } = require('util');
|
||||
const auth_api = require('./authentication/auth');
|
||||
const winston = require('winston');
|
||||
const path = require('path');
|
||||
const compression = require('compression');
|
||||
const glob = require("glob")
|
||||
const multer = require('multer');
|
||||
const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
const archiver = require('archiver');
|
||||
const unzipper = require('unzipper');
|
||||
const db_api = require('./db');
|
||||
const utils = require('./utils')
|
||||
const mergeFiles = require('merge-files');
|
||||
const low = require('lowdb')
|
||||
var ProgressBar = require('progress');
|
||||
const ProgressBar = require('progress');
|
||||
const NodeID3 = require('node-id3')
|
||||
const fetch = require('node-fetch');
|
||||
var URL = require('url').URL;
|
||||
const URL = require('url').URL;
|
||||
const url_api = require('url');
|
||||
const CONSTS = require('./consts')
|
||||
const read_last_lines = require('read-last-lines');
|
||||
var ps = require('ps-node');
|
||||
const ps = require('ps-node');
|
||||
|
||||
// needed if bin/details somehow gets deleted
|
||||
if (!fs.existsSync(CONSTS.DETAILS_BIN_PATH)) fs.writeJSONSync(CONSTS.DETAILS_BIN_PATH, {"version":"2000.06.06","path":"node_modules\\youtube-dl\\bin\\youtube-dl.exe","exec":"youtube-dl.exe","downloader":"youtube-dl"})
|
||||
|
||||
var youtubedl = require('youtube-dl');
|
||||
const youtubedl = require('youtube-dl');
|
||||
|
||||
const logger = require('./logger');
|
||||
var config_api = require('./config.js');
|
||||
var subscriptions_api = require('./subscriptions')
|
||||
var categories_api = require('./categories');
|
||||
@@ -61,30 +61,11 @@ const admin_token = '4241b401-7236-493e-92b5-b72696b9d853';
|
||||
|
||||
// logging setup
|
||||
|
||||
// console format
|
||||
const defaultFormat = winston.format.printf(({ level, message, label, timestamp }) => {
|
||||
return `${timestamp} ${level.toUpperCase()}: ${message}`;
|
||||
});
|
||||
const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.combine(winston.format.timestamp(), defaultFormat),
|
||||
defaultMeta: {},
|
||||
transports: [
|
||||
//
|
||||
// - Write to all logs with level `info` and below to `combined.log`
|
||||
// - Write all logs error (and below) to `error.log`.
|
||||
//
|
||||
new winston.transports.File({ filename: 'appdata/logs/error.log', level: 'error' }),
|
||||
new winston.transports.File({ filename: 'appdata/logs/combined.log' }),
|
||||
new winston.transports.Console({level: !debugMode ? 'info' : 'debug', name: 'console'})
|
||||
]
|
||||
});
|
||||
|
||||
config_api.initialize(logger);
|
||||
db_api.initialize(db, users_db, logger);
|
||||
auth_api.initialize(db_api, logger);
|
||||
subscriptions_api.initialize(db_api, logger);
|
||||
categories_api.initialize(db, users_db, logger, db_api);
|
||||
config_api.initialize();
|
||||
db_api.initialize(db, users_db);
|
||||
auth_api.initialize(db_api);
|
||||
subscriptions_api.initialize(db_api);
|
||||
categories_api.initialize(db_api);
|
||||
|
||||
// Set some defaults
|
||||
db.defaults(
|
||||
@@ -122,13 +103,9 @@ users_db.defaults(
|
||||
).write();
|
||||
|
||||
// config values
|
||||
var frontendUrl = null;
|
||||
var backendUrl = null;
|
||||
var backendPort = null;
|
||||
var basePath = null;
|
||||
var audioFolderPath = null;
|
||||
var videoFolderPath = null;
|
||||
var downloadOnlyMode = null;
|
||||
var useDefaultDownloadingAgent = null;
|
||||
var customDownloadingAgent = null;
|
||||
var allowSubscriptions = null;
|
||||
@@ -138,8 +115,6 @@ var archivePath = path.join(__dirname, 'appdata', 'archives');
|
||||
var url_domain = null;
|
||||
var updaterStatus = null;
|
||||
|
||||
var timestamp_server_start = Date.now();
|
||||
|
||||
const concurrentStreams = {};
|
||||
|
||||
if (debugMode) logger.info('YTDL-Material in debug mode!');
|
||||
@@ -368,6 +343,7 @@ async function updateServer(tag) {
|
||||
}
|
||||
restartServer(true);
|
||||
}, err => {
|
||||
logger.error(err);
|
||||
updaterStatus = {
|
||||
updating: false,
|
||||
error: true,
|
||||
@@ -398,12 +374,10 @@ async function downloadReleaseFiles(tag) {
|
||||
fs.createReadStream(path.join(__dirname, `youtubedl-material-release-${tag}.zip`)).pipe(unzipper.Parse())
|
||||
.on('entry', function (entry) {
|
||||
var fileName = entry.path;
|
||||
var type = entry.type; // 'Directory' or 'File'
|
||||
var size = entry.size;
|
||||
var is_dir = fileName.substring(fileName.length-1, fileName.length) === '/'
|
||||
if (!is_dir && fileName.includes('youtubedl-material/public/')) {
|
||||
// get public folder files
|
||||
var actualFileName = fileName.replace('youtubedl-material/public/', '');
|
||||
const actualFileName = fileName.replace('youtubedl-material/public/', '');
|
||||
if (actualFileName.length !== 0 && actualFileName.substring(actualFileName.length-1, actualFileName.length) !== '/') {
|
||||
fs.ensureDirSync(path.join(__dirname, 'public', path.dirname(actualFileName)));
|
||||
entry.pipe(fs.createWriteStream(path.join(__dirname, 'public', actualFileName)));
|
||||
@@ -412,7 +386,7 @@ async function downloadReleaseFiles(tag) {
|
||||
}
|
||||
} else if (!is_dir && !replace_ignore_list.includes(fileName)) {
|
||||
// get package.json
|
||||
var actualFileName = fileName.replace('youtubedl-material/', '');
|
||||
const actualFileName = fileName.replace('youtubedl-material/', '');
|
||||
logger.verbose('Downloading file ' + actualFileName);
|
||||
entry.pipe(fs.createWriteStream(path.join(__dirname, actualFileName)));
|
||||
} else {
|
||||
@@ -750,17 +724,6 @@ function generateEnvVarConfigItem(key) {
|
||||
return {key: key, value: process['env'][key]};
|
||||
}
|
||||
|
||||
function getVideoFormatID(name)
|
||||
{
|
||||
var jsonPath = videoFolderPath+name+".info.json";
|
||||
if (fs.existsSync(jsonPath))
|
||||
{
|
||||
var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
||||
var format = obj.format.substring(0,3);
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {'audio' | 'video'} type
|
||||
* @param {string[]} fileNames
|
||||
@@ -808,16 +771,11 @@ async function downloadFileByURL_exec(url, type, options, sessionID = null) {
|
||||
let category = null;
|
||||
|
||||
// prepend with user if needed
|
||||
let multiUserMode = null;
|
||||
if (options.user) {
|
||||
let usersFileFolder = config_api.getConfigItem('ytdl_users_base_path');
|
||||
const user_path = path.join(usersFileFolder, options.user, type);
|
||||
fs.ensureDirSync(user_path);
|
||||
fileFolderPath = user_path + path.sep;
|
||||
multiUserMode = {
|
||||
user: options.user,
|
||||
file_path: fileFolderPath
|
||||
}
|
||||
options.customFileFolderPath = fileFolderPath;
|
||||
}
|
||||
|
||||
@@ -947,11 +905,8 @@ async function downloadFileByURL_exec(url, type, options, sessionID = null) {
|
||||
if (!success) logger.error('Failed to apply ID3 tag to audio file ' + output_json['_filename']);
|
||||
}
|
||||
|
||||
const file_path = options.noRelativePath ? path.basename(full_file_path) : full_file_path.substring(fileFolderPath.length, full_file_path.length);
|
||||
const customPath = options.noRelativePath ? path.dirname(full_file_path).split(path.sep).pop() : null;
|
||||
|
||||
if (options.cropFileSettings) {
|
||||
await cropFile(full_file_path, options.cropFileSettings.cropFileStart, options.cropFileSettings.cropFileEnd, ext);
|
||||
await utils.cropFile(full_file_path, options.cropFileSettings.cropFileStart, options.cropFileSettings.cropFileEnd, ext);
|
||||
}
|
||||
|
||||
// registers file in DB
|
||||
@@ -1022,6 +977,8 @@ async function generateArgs(url, type, options) {
|
||||
var youtubePassword = options.youtubePassword;
|
||||
|
||||
let downloadConfig = null;
|
||||
|
||||
// TODO: fix
|
||||
let qualityPath = (is_audio && !options.skip_audio_args) ? ['-f', 'bestaudio'] : ['-f', 'bestvideo+bestaudio', '--merge-output-format', 'mp4'];
|
||||
const is_youtube = url.includes('youtu');
|
||||
if (!is_audio && !is_youtube) {
|
||||
@@ -1197,33 +1154,6 @@ async function getUrlInfos(urls) {
|
||||
});
|
||||
}
|
||||
|
||||
// ffmpeg helper functions
|
||||
|
||||
async function cropFile(file_path, start, end, ext) {
|
||||
return new Promise(resolve => {
|
||||
const temp_file_path = `${file_path}.cropped${ext}`;
|
||||
let base_ffmpeg_call = ffmpeg(file_path);
|
||||
if (start) {
|
||||
base_ffmpeg_call = base_ffmpeg_call.seekOutput(start);
|
||||
}
|
||||
if (end) {
|
||||
base_ffmpeg_call = base_ffmpeg_call.duration(end - start);
|
||||
}
|
||||
base_ffmpeg_call
|
||||
.on('end', () => {
|
||||
logger.verbose(`Cropping for '${file_path}' complete.`);
|
||||
fs.unlinkSync(file_path);
|
||||
fs.moveSync(temp_file_path, file_path);
|
||||
resolve(true);
|
||||
})
|
||||
.on('error', (err, test, test2) => {
|
||||
logger.error(`Failed to crop ${file_path}.`);
|
||||
logger.error(err);
|
||||
resolve(false);
|
||||
}).save(temp_file_path);
|
||||
});
|
||||
}
|
||||
|
||||
// download management functions
|
||||
|
||||
async function updateDownloads() {
|
||||
@@ -1951,14 +1881,12 @@ app.post('/api/getSubscription', optionalJwt, async (req, res) => {
|
||||
let subID = req.body.id;
|
||||
let subName = req.body.name; // if included, subID is optional
|
||||
|
||||
let user_uid = req.isAuthenticated() ? req.user.uid : null;
|
||||
|
||||
// get sub from db
|
||||
let subscription = null;
|
||||
if (subID) {
|
||||
subscription = await subscriptions_api.getSubscription(subID, user_uid)
|
||||
subscription = await subscriptions_api.getSubscription(subID)
|
||||
} else if (subName) {
|
||||
subscription = await subscriptions_api.getSubscriptionByName(subName, user_uid)
|
||||
subscription = await subscriptions_api.getSubscriptionByName(subName)
|
||||
}
|
||||
|
||||
if (!subscription) {
|
||||
@@ -2124,28 +2052,6 @@ app.post('/api/getPlaylists', optionalJwt, async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/updatePlaylistFiles', optionalJwt, async (req, res) => {
|
||||
let playlistID = req.body.playlist_id;
|
||||
let uids = req.body.uids;
|
||||
|
||||
let success = false;
|
||||
try {
|
||||
if (req.isAuthenticated()) {
|
||||
auth_api.updatePlaylistFiles(req.user.uid, playlistID, uids);
|
||||
} else {
|
||||
await db_api.updateRecord('playlists', {id: playlistID}, {uids: uids})
|
||||
}
|
||||
|
||||
success = true;
|
||||
} catch(e) {
|
||||
logger.error(`Failed to find playlist with ID ${playlistID}`);
|
||||
}
|
||||
|
||||
res.send({
|
||||
success: success
|
||||
})
|
||||
});
|
||||
|
||||
app.post('/api/addFileToPlaylist', optionalJwt, async (req, res) => {
|
||||
let playlist_id = req.body.playlist_id;
|
||||
let file_uid = req.body.file_uid;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const path = require('path');
|
||||
const config_api = require('../config');
|
||||
const consts = require('../consts');
|
||||
const fs = require('fs-extra');
|
||||
const logger = require('../logger');
|
||||
|
||||
const jwt = require('jsonwebtoken');
|
||||
const { uuid } = require('uuidv4');
|
||||
const bcrypt = require('bcryptjs');
|
||||
@@ -12,15 +12,13 @@ var JwtStrategy = require('passport-jwt').Strategy,
|
||||
ExtractJwt = require('passport-jwt').ExtractJwt;
|
||||
|
||||
// other required vars
|
||||
let logger = null;
|
||||
let db_api = null;
|
||||
let SERVER_SECRET = null;
|
||||
let JWT_EXPIRATION = null;
|
||||
let opts = null;
|
||||
let saltRounds = null;
|
||||
|
||||
exports.initialize = function(db_api, input_logger) {
|
||||
setLogger(input_logger)
|
||||
exports.initialize = function(db_api) {
|
||||
setDB(db_api);
|
||||
|
||||
/*************************
|
||||
@@ -53,10 +51,6 @@ exports.initialize = function(db_api, input_logger) {
|
||||
}));
|
||||
}
|
||||
|
||||
function setLogger(input_logger) {
|
||||
logger = input_logger;
|
||||
}
|
||||
|
||||
function setDB(input_db_api) {
|
||||
db_api = input_db_api;
|
||||
}
|
||||
@@ -291,17 +285,12 @@ exports.getUserVideo = async function(user_uid, file_uid, requireSharing = false
|
||||
return file;
|
||||
}
|
||||
|
||||
exports.updatePlaylistFiles = function(user_uid, playlistID, new_filenames) {
|
||||
users_db.get('users').find({uid: user_uid}).get(`playlists`).find({id: playlistID}).assign({fileNames: new_filenames});
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.removePlaylist = async function(user_uid, playlistID) {
|
||||
await db_api.removeRecord('playlist', {playlistID: playlistID});
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.getUserPlaylists = async function(user_uid, user_files = null) {
|
||||
exports.getUserPlaylists = async function(user_uid) {
|
||||
return await db_api.getRecords('playlists', {user_uid: user_uid});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
const config_api = require('./config');
|
||||
const utils = require('./utils');
|
||||
const logger = require('./logger');
|
||||
|
||||
var logger = null;
|
||||
var db = null;
|
||||
var users_db = null;
|
||||
var db_api = null;
|
||||
|
||||
function setDB(input_db, input_users_db, input_db_api) { db = input_db; users_db = input_users_db; db_api = input_db_api }
|
||||
function setLogger(input_logger) { logger = input_logger; }
|
||||
function setDB(input_db_api) { db_api = input_db_api }
|
||||
|
||||
function initialize(input_db, input_users_db, input_logger, input_db_api) {
|
||||
setDB(input_db, input_users_db, input_db_api);
|
||||
setLogger(input_logger);
|
||||
function initialize(input_db_api) {
|
||||
setDB(input_db_api);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -72,7 +67,7 @@ async function getCategoriesAsPlaylists(files = null) {
|
||||
const categories_as_playlists = [];
|
||||
const available_categories = await getCategories();
|
||||
if (available_categories && files) {
|
||||
for (category of available_categories) {
|
||||
for (let category of available_categories) {
|
||||
const files_that_match = utils.addUIDsToCategory(category, files);
|
||||
if (files_that_match && files_that_match.length > 0) {
|
||||
category['thumbnailURL'] = files_that_match[0].thumbnailURL;
|
||||
@@ -125,21 +120,21 @@ function applyCategoryRules(file_json, rules, category_name) {
|
||||
return rules_apply;
|
||||
}
|
||||
|
||||
async function addTagToVideo(tag, video, user_uid) {
|
||||
// TODO: Implement
|
||||
}
|
||||
// async function addTagToVideo(tag, video, user_uid) {
|
||||
// // TODO: Implement
|
||||
// }
|
||||
|
||||
async function removeTagFromVideo(tag, video, user_uid) {
|
||||
// TODO: Implement
|
||||
}
|
||||
// async function removeTagFromVideo(tag, video, user_uid) {
|
||||
// // TODO: Implement
|
||||
// }
|
||||
|
||||
// adds tag to list of existing tags (used for tag suggestions)
|
||||
async function addTagToExistingTags(tag) {
|
||||
const existing_tags = db.get('tags').value();
|
||||
if (!existing_tags.includes(tag)) {
|
||||
db.get('tags').push(tag).write();
|
||||
}
|
||||
}
|
||||
// // adds tag to list of existing tags (used for tag suggestions)
|
||||
// async function addTagToExistingTags(tag) {
|
||||
// const existing_tags = db.get('tags').value();
|
||||
// if (!existing_tags.includes(tag)) {
|
||||
// db.get('tags').push(tag).write();
|
||||
// }
|
||||
// }
|
||||
|
||||
module.exports = {
|
||||
initialize: initialize,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const logger = require('./logger');
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
let CONFIG_ITEMS = require('./consts.js')['CONFIG_ITEMS'];
|
||||
@@ -5,11 +7,7 @@ const debugMode = process.env.YTDL_MODE === 'debug';
|
||||
|
||||
let configPath = debugMode ? '../src/assets/default.json' : 'appdata/default.json';
|
||||
|
||||
var logger = null;
|
||||
function setLogger(input_logger) { logger = input_logger; }
|
||||
|
||||
function initialize(input_logger) {
|
||||
setLogger(input_logger);
|
||||
function initialize() {
|
||||
ensureConfigFileExists();
|
||||
ensureConfigItemsExist();
|
||||
}
|
||||
@@ -175,7 +173,7 @@ module.exports = {
|
||||
globalArgsRequiresSafeDownload: globalArgsRequiresSafeDownload
|
||||
}
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
const DEFAULT_CONFIG = {
|
||||
"YoutubeDLMaterial": {
|
||||
"Host": {
|
||||
"url": "http://example.com",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
let CONFIG_ITEMS = {
|
||||
exports.CONFIG_ITEMS = {
|
||||
// Host
|
||||
'ytdl_url': {
|
||||
'key': 'ytdl_url',
|
||||
@@ -210,7 +210,7 @@ let CONFIG_ITEMS = {
|
||||
}
|
||||
};
|
||||
|
||||
AVAILABLE_PERMISSIONS = [
|
||||
exports.AVAILABLE_PERMISSIONS = [
|
||||
'filemanager',
|
||||
'settings',
|
||||
'subscriptions',
|
||||
@@ -219,11 +219,6 @@ AVAILABLE_PERMISSIONS = [
|
||||
'downloads_manager'
|
||||
];
|
||||
|
||||
const DETAILS_BIN_PATH = 'node_modules/youtube-dl/bin/details'
|
||||
exports.DETAILS_BIN_PATH = 'node_modules/youtube-dl/bin/details'
|
||||
|
||||
module.exports = {
|
||||
CONFIG_ITEMS: CONFIG_ITEMS,
|
||||
AVAILABLE_PERMISSIONS: AVAILABLE_PERMISSIONS,
|
||||
CURRENT_VERSION: 'v4.2',
|
||||
DETAILS_BIN_PATH: DETAILS_BIN_PATH
|
||||
}
|
||||
exports.CURRENT_VERSION = 'v4.2';
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
var fs = require('fs-extra')
|
||||
var path = require('path')
|
||||
var utils = require('./utils')
|
||||
const { uuid } = require('uuidv4');
|
||||
const config_api = require('./config');
|
||||
const { MongoClient } = require("mongodb");
|
||||
const { uuid } = require('uuidv4');
|
||||
|
||||
const config_api = require('./config');
|
||||
var utils = require('./utils')
|
||||
const logger = require('./logger');
|
||||
|
||||
const low = require('lowdb')
|
||||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
const local_adapter = new FileSync('./appdata/local_db.json');
|
||||
const local_db = low(local_adapter);
|
||||
|
||||
var logger = null;
|
||||
var db = null;
|
||||
var users_db = null;
|
||||
var database = null;
|
||||
let database = null;
|
||||
|
||||
const tables = {
|
||||
files: {
|
||||
@@ -62,13 +61,8 @@ function setDB(input_db, input_users_db) {
|
||||
exports.users_db = input_users_db
|
||||
}
|
||||
|
||||
function setLogger(input_logger) {
|
||||
logger = input_logger;
|
||||
}
|
||||
|
||||
exports.initialize = (input_db, input_users_db, input_logger) => {
|
||||
exports.initialize = (input_db, input_users_db) => {
|
||||
setDB(input_db, input_users_db);
|
||||
setLogger(input_logger);
|
||||
|
||||
// must be done here to prevent getConfigItem from being called before init
|
||||
using_local_db = config_api.getConfigItem('ytdl_use_local_db');
|
||||
|
||||
23
backend/logger.js
Normal file
23
backend/logger.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const winston = require('winston');
|
||||
|
||||
let debugMode = process.env.YTDL_MODE === 'debug';
|
||||
|
||||
const defaultFormat = winston.format.printf(({ level, message, label, timestamp }) => {
|
||||
return `${timestamp} ${level.toUpperCase()}: ${message}`;
|
||||
});
|
||||
const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.combine(winston.format.timestamp(), defaultFormat),
|
||||
defaultMeta: {},
|
||||
transports: [
|
||||
//
|
||||
// - Write to all logs with level `info` and below to `combined.log`
|
||||
// - Write all logs error (and below) to `error.log`.
|
||||
//
|
||||
new winston.transports.File({ filename: 'appdata/logs/error.log', level: 'error' }),
|
||||
new winston.transports.File({ filename: 'appdata/logs/combined.log' }),
|
||||
new winston.transports.Console({level: !debugMode ? 'info' : 'debug', name: 'console'})
|
||||
]
|
||||
});
|
||||
|
||||
module.exports = logger;
|
||||
@@ -1,27 +1,20 @@
|
||||
const FileSync = require('lowdb/adapters/FileSync')
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const youtubedl = require('youtube-dl');
|
||||
|
||||
var fs = require('fs-extra');
|
||||
const { uuid } = require('uuidv4');
|
||||
var path = require('path');
|
||||
|
||||
var youtubedl = require('youtube-dl');
|
||||
const config_api = require('./config');
|
||||
const twitch_api = require('./twitch');
|
||||
var utils = require('./utils');
|
||||
const utils = require('./utils');
|
||||
const logger = require('./logger');
|
||||
|
||||
const debugMode = process.env.YTDL_MODE === 'debug';
|
||||
|
||||
var logger = null;
|
||||
var db = null;
|
||||
var users_db = null;
|
||||
let db_api = null;
|
||||
|
||||
function setDB(input_db_api) { db_api = input_db_api }
|
||||
function setLogger(input_logger) { logger = input_logger; }
|
||||
|
||||
function initialize(input_db_api, input_logger) {
|
||||
function initialize(input_db_api) {
|
||||
setDB(input_db_api);
|
||||
setLogger(input_logger);
|
||||
}
|
||||
|
||||
async function subscribe(sub, user_uid = null) {
|
||||
@@ -52,7 +45,7 @@ async function subscribe(sub, user_uid = null) {
|
||||
getVideosForSub(sub, user_uid);
|
||||
} else {
|
||||
logger.error('Subscribe: Failed to get subscription info. Subscribe failed.')
|
||||
};
|
||||
}
|
||||
|
||||
result_obj.success = success;
|
||||
result_obj.sub = sub;
|
||||
@@ -146,7 +139,6 @@ async function unsubscribe(sub, deleteMode, user_uid = null) {
|
||||
basePath = path.join(config_api.getConfigItem('ytdl_users_base_path'), user_uid, 'subscriptions');
|
||||
else
|
||||
basePath = config_api.getConfigItem('ytdl_subscriptions_base_path');
|
||||
let result_obj = { success: false, error: '' };
|
||||
|
||||
let id = sub.id;
|
||||
|
||||
@@ -451,39 +443,26 @@ async function generateArgsForSubscription(sub, user_uid, redownload = false, de
|
||||
}
|
||||
|
||||
async function handleOutputJSON(sub, output_json, multiUserMode = null, reset_videos = false) {
|
||||
// TODO: remove streaming only mode
|
||||
if (false && sub.streamingOnly) {
|
||||
if (reset_videos) {
|
||||
sub_db.assign({videos: []}).write();
|
||||
}
|
||||
const path_object = path.parse(output_json['_filename']);
|
||||
const path_string = path.format(path_object);
|
||||
|
||||
// remove unnecessary info
|
||||
output_json.formats = null;
|
||||
const file_exists = await db_api.getRecord('files', {path: path_string, sub_id: sub.id});
|
||||
if (file_exists) {
|
||||
// TODO: fix issue where files of different paths due to custom path get downloaded multiple times
|
||||
// file already exists in DB, return early to avoid reseting the download date
|
||||
return;
|
||||
}
|
||||
|
||||
// add to db
|
||||
sub_db.get('videos').push(output_json).write();
|
||||
} else {
|
||||
path_object = path.parse(output_json['_filename']);
|
||||
const path_string = path.format(path_object);
|
||||
await db_api.registerFileDB2(output_json['_filename'], sub.type, sub.user_uid, null, sub.id);
|
||||
|
||||
const file_exists = await db_api.getRecord('files', {path: path_string, sub_id: sub.id});
|
||||
if (file_exists) {
|
||||
// TODO: fix issue where files of different paths due to custom path get downloaded multiple times
|
||||
// file already exists in DB, return early to avoid reseting the download date
|
||||
return;
|
||||
}
|
||||
|
||||
await db_api.registerFileDB2(output_json['_filename'], sub.type, sub.user_uid, null, sub.id);
|
||||
|
||||
const url = output_json['webpage_url'];
|
||||
if (sub.type === 'video' && url.includes('twitch.tv/videos/') && url.split('twitch.tv/videos/').length > 1
|
||||
&& config_api.getConfigItem('ytdl_use_twitch_api') && config_api.getConfigItem('ytdl_twitch_auto_download_chat')) {
|
||||
const file_name = path.basename(output_json['_filename']);
|
||||
const id = file_name.substring(0, file_name.length-4);
|
||||
let vodId = url.split('twitch.tv/videos/')[1];
|
||||
vodId = vodId.split('?')[0];
|
||||
twitch_api.downloadTwitchChatByVODID(vodId, id, sub.type, multiUserMode.user, sub);
|
||||
}
|
||||
const url = output_json['webpage_url'];
|
||||
if (sub.type === 'video' && url.includes('twitch.tv/videos/') && url.split('twitch.tv/videos/').length > 1
|
||||
&& config_api.getConfigItem('ytdl_use_twitch_api') && config_api.getConfigItem('ytdl_twitch_auto_download_chat')) {
|
||||
const file_name = path.basename(output_json['_filename']);
|
||||
const id = file_name.substring(0, file_name.length-4);
|
||||
let vodId = url.split('twitch.tv/videos/')[1];
|
||||
vodId = vodId.split('?')[0];
|
||||
twitch_api.downloadTwitchChatByVODID(vodId, id, sub.type, multiUserMode.user, sub);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +484,7 @@ async function getSubscriptionByName(subName, user_uid = null) {
|
||||
return await db_api.getRecord('subscriptions', {name: subName, user_uid: user_uid});
|
||||
}
|
||||
|
||||
async function updateSubscription(sub, user_uid = null) {
|
||||
async function updateSubscription(sub) {
|
||||
await db_api.updateRecord('subscriptions', {id: sub.id}, sub);
|
||||
return true;
|
||||
}
|
||||
@@ -516,7 +495,7 @@ async function updateSubscriptionPropertyMultiple(subs, assignment_obj) {
|
||||
});
|
||||
}
|
||||
|
||||
async function updateSubscriptionProperty(sub, assignment_obj, user_uid = null) {
|
||||
async function updateSubscriptionProperty(sub, assignment_obj) {
|
||||
// TODO: combine with updateSubscription
|
||||
await db_api.updateRecord('subscriptions', {id: sub.id}, assignment_obj);
|
||||
return true;
|
||||
@@ -585,7 +564,6 @@ module.exports = {
|
||||
unsubscribe : unsubscribe,
|
||||
deleteSubscriptionFile : deleteSubscriptionFile,
|
||||
getVideosForSub : getVideosForSub,
|
||||
setLogger : setLogger,
|
||||
initialize : initialize,
|
||||
updateSubscriptionPropertyMultiple : updateSubscriptionPropertyMultiple
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const config_api = require('./config');
|
||||
const logger = require('./logger');
|
||||
const CONSTS = require('./consts')
|
||||
const archiver = require('archiver');
|
||||
|
||||
@@ -349,6 +351,33 @@ function removeFileExtension(filename) {
|
||||
return filename_parts.join('.');
|
||||
}
|
||||
|
||||
// ffmpeg helper functions
|
||||
|
||||
async function cropFile(file_path, start, end, ext) {
|
||||
return new Promise(resolve => {
|
||||
const temp_file_path = `${file_path}.cropped${ext}`;
|
||||
let base_ffmpeg_call = ffmpeg(file_path);
|
||||
if (start) {
|
||||
base_ffmpeg_call = base_ffmpeg_call.seekOutput(start);
|
||||
}
|
||||
if (end) {
|
||||
base_ffmpeg_call = base_ffmpeg_call.duration(end - start);
|
||||
}
|
||||
base_ffmpeg_call
|
||||
.on('end', () => {
|
||||
logger.verbose(`Cropping for '${file_path}' complete.`);
|
||||
fs.unlinkSync(file_path);
|
||||
fs.moveSync(temp_file_path, file_path);
|
||||
resolve(true);
|
||||
})
|
||||
.on('error', (err) => {
|
||||
logger.error(`Failed to crop ${file_path}.`);
|
||||
logger.error(err);
|
||||
resolve(false);
|
||||
}).save(temp_file_path);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* setTimeout, but its a promise.
|
||||
* @param {number} ms
|
||||
@@ -390,7 +419,7 @@ module.exports = {
|
||||
fixVideoMetadataPerms2: fixVideoMetadataPerms2,
|
||||
deleteJSONFile: deleteJSONFile,
|
||||
deleteJSONFile2: deleteJSONFile2,
|
||||
removeIDFromArchive, removeIDFromArchive,
|
||||
removeIDFromArchive: removeIDFromArchive,
|
||||
getDownloadedFilesByType: getDownloadedFilesByType,
|
||||
createContainerZipFile: createContainerZipFile,
|
||||
durationStringToNumber: durationStringToNumber,
|
||||
@@ -399,6 +428,7 @@ module.exports = {
|
||||
getCurrentDownloader: getCurrentDownloader,
|
||||
recFindByExt: recFindByExt,
|
||||
removeFileExtension: removeFileExtension,
|
||||
cropFile: cropFile,
|
||||
wait: wait,
|
||||
File: File
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user