mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-04-07 12:01:29 +03:00
All config values are now reloaded on config set
Added 4 new settings: user files folder, enable registration, enable downloads manager, and logging level selection
This commit is contained in:
102
backend/app.js
102
backend/app.js
@@ -61,7 +61,7 @@ const logger = winston.createLogger({
|
|||||||
//
|
//
|
||||||
new winston.transports.File({ filename: 'appdata/logs/error.log', level: 'error' }),
|
new winston.transports.File({ filename: 'appdata/logs/error.log', level: 'error' }),
|
||||||
new winston.transports.File({ filename: 'appdata/logs/combined.log' }),
|
new winston.transports.File({ filename: 'appdata/logs/combined.log' }),
|
||||||
new winston.transports.Console({level: !debugMode ? 'info' : 'debug'})
|
new winston.transports.Console({level: !debugMode ? 'info' : 'debug', name: 'console'})
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -132,8 +132,6 @@ var archivePath = path.join(__dirname, 'appdata', 'archives');
|
|||||||
var options = null; // encryption options
|
var options = null; // encryption options
|
||||||
var url_domain = null;
|
var url_domain = null;
|
||||||
var updaterStatus = null;
|
var updaterStatus = null;
|
||||||
var last_downloads_check = null;
|
|
||||||
var downloads_check_interval = 1000;
|
|
||||||
|
|
||||||
var timestamp_server_start = Date.now();
|
var timestamp_server_start = Date.now();
|
||||||
|
|
||||||
@@ -536,38 +534,7 @@ async function setConfigFromEnv() {
|
|||||||
|
|
||||||
async function loadConfig() {
|
async function loadConfig() {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
url = !debugMode ? config_api.getConfigItem('ytdl_url') : 'http://localhost:4200';
|
loadConfigValues();
|
||||||
backendPort = config_api.getConfigItem('ytdl_port');
|
|
||||||
usingEncryption = config_api.getConfigItem('ytdl_use_encryption');
|
|
||||||
audioFolderPath = config_api.getConfigItem('ytdl_audio_folder_path');
|
|
||||||
videoFolderPath = config_api.getConfigItem('ytdl_video_folder_path');
|
|
||||||
downloadOnlyMode = config_api.getConfigItem('ytdl_download_only_mode');
|
|
||||||
useDefaultDownloadingAgent = config_api.getConfigItem('ytdl_use_default_downloading_agent');
|
|
||||||
customDownloadingAgent = config_api.getConfigItem('ytdl_custom_downloading_agent');
|
|
||||||
allowSubscriptions = config_api.getConfigItem('ytdl_allow_subscriptions');
|
|
||||||
subscriptionsCheckInterval = config_api.getConfigItem('ytdl_subscriptions_check_interval');
|
|
||||||
|
|
||||||
if (!useDefaultDownloadingAgent && validDownloadingAgents.indexOf(customDownloadingAgent) !== -1 ) {
|
|
||||||
logger.info(`Using non-default downloading agent \'${customDownloadingAgent}\'`)
|
|
||||||
} else {
|
|
||||||
customDownloadingAgent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usingEncryption)
|
|
||||||
{
|
|
||||||
var certFilePath = path.resolve(config_api.getConfigItem('ytdl_cert_file_path'));
|
|
||||||
var keyFilePath = path.resolve(config_api.getConfigItem('ytdl_key_file_path'));
|
|
||||||
|
|
||||||
var certKeyFile = fs.readFileSync(keyFilePath);
|
|
||||||
var certFile = fs.readFileSync(certFilePath);
|
|
||||||
|
|
||||||
options = {
|
|
||||||
key: certKeyFile,
|
|
||||||
cert: certFile
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
url_domain = new URL(url);
|
|
||||||
|
|
||||||
// creates archive path if missing
|
// creates archive path if missing
|
||||||
if (!fs.existsSync(archivePath)){
|
if (!fs.existsSync(archivePath)){
|
||||||
@@ -597,6 +564,51 @@ async function loadConfig() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadConfigValues() {
|
||||||
|
url = !debugMode ? config_api.getConfigItem('ytdl_url') : 'http://localhost:4200';
|
||||||
|
backendPort = config_api.getConfigItem('ytdl_port');
|
||||||
|
usingEncryption = config_api.getConfigItem('ytdl_use_encryption');
|
||||||
|
audioFolderPath = config_api.getConfigItem('ytdl_audio_folder_path');
|
||||||
|
videoFolderPath = config_api.getConfigItem('ytdl_video_folder_path');
|
||||||
|
downloadOnlyMode = config_api.getConfigItem('ytdl_download_only_mode');
|
||||||
|
useDefaultDownloadingAgent = config_api.getConfigItem('ytdl_use_default_downloading_agent');
|
||||||
|
customDownloadingAgent = config_api.getConfigItem('ytdl_custom_downloading_agent');
|
||||||
|
allowSubscriptions = config_api.getConfigItem('ytdl_allow_subscriptions');
|
||||||
|
subscriptionsCheckInterval = config_api.getConfigItem('ytdl_subscriptions_check_interval');
|
||||||
|
|
||||||
|
if (!useDefaultDownloadingAgent && validDownloadingAgents.indexOf(customDownloadingAgent) !== -1 ) {
|
||||||
|
logger.info(`Using non-default downloading agent \'${customDownloadingAgent}\'`)
|
||||||
|
} else {
|
||||||
|
customDownloadingAgent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usingEncryption)
|
||||||
|
{
|
||||||
|
var certFilePath = path.resolve(config_api.getConfigItem('ytdl_cert_file_path'));
|
||||||
|
var keyFilePath = path.resolve(config_api.getConfigItem('ytdl_key_file_path'));
|
||||||
|
|
||||||
|
var certKeyFile = fs.readFileSync(keyFilePath);
|
||||||
|
var certFile = fs.readFileSync(certFilePath);
|
||||||
|
|
||||||
|
options = {
|
||||||
|
key: certKeyFile,
|
||||||
|
cert: certFile
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
url_domain = new URL(url);
|
||||||
|
|
||||||
|
let logger_level = config_api.getConfigItem('ytdl_logger_level');
|
||||||
|
const possible_levels = ['error', 'warn', 'info', 'verbose', 'debug'];
|
||||||
|
if (!possible_levels.includes(logger_level)) {
|
||||||
|
logger.error(`${logger_level} is not a valid logger level! Choose one of the following: ${possible_levels.join(', ')}.`)
|
||||||
|
logger_level = 'info';
|
||||||
|
}
|
||||||
|
logger.level = logger_level;
|
||||||
|
winston.loggers.get('console').level = logger_level;
|
||||||
|
logger.transports[2].level = logger_level;
|
||||||
|
}
|
||||||
|
|
||||||
function calculateSubcriptionRetrievalDelay(amount) {
|
function calculateSubcriptionRetrievalDelay(amount) {
|
||||||
// frequency is 5 mins
|
// frequency is 5 mins
|
||||||
let frequency_in_ms = subscriptionsCheckInterval * 1000;
|
let frequency_in_ms = subscriptionsCheckInterval * 1000;
|
||||||
@@ -1517,11 +1529,9 @@ async function getUrlInfos(urls) {
|
|||||||
let result = [];
|
let result = [];
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
youtubedl.exec(urls.join(' '), ['--dump-json'], {}, (err, output) => {
|
youtubedl.exec(urls.join(' '), ['--dump-json'], {}, (err, output) => {
|
||||||
if (debugMode) {
|
let new_date = Date.now();
|
||||||
let new_date = Date.now();
|
let difference = (new_date - startDate)/1000;
|
||||||
let difference = (new_date - startDate)/1000;
|
logger.debug(`URL info retrieval delay: ${difference} seconds.`);
|
||||||
logger.info(`URL info retrieval delay: ${difference} seconds.`);
|
|
||||||
}
|
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Error during parsing:' + err);
|
logger.error('Error during parsing:' + err);
|
||||||
resolve(null);
|
resolve(null);
|
||||||
@@ -1600,7 +1610,7 @@ function getDownloadPercent(download_obj) {
|
|||||||
|
|
||||||
async function startYoutubeDL() {
|
async function startYoutubeDL() {
|
||||||
// auto update youtube-dl
|
// auto update youtube-dl
|
||||||
await autoUpdateYoutubeDL();
|
if (!debugMode) await autoUpdateYoutubeDL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto updates the underlying youtube-dl binary, not YoutubeDL-Material
|
// auto updates the underlying youtube-dl binary, not YoutubeDL-Material
|
||||||
@@ -1652,10 +1662,9 @@ async function autoUpdateYoutubeDL() {
|
|||||||
logger.error(`Failed to update youtube-dl - ${e}`);
|
logger.error(`Failed to update youtube-dl - ${e}`);
|
||||||
}
|
}
|
||||||
downloader(binary_path, function error(err, done) {
|
downloader(binary_path, function error(err, done) {
|
||||||
'use strict'
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
logger.error(err);
|
||||||
resolve(false);
|
resolve(false);
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
logger.info(`Binary successfully updated: ${current_version} -> ${latest_update_version}`);
|
logger.info(`Binary successfully updated: ${current_version} -> ${latest_update_version}`);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
@@ -1777,6 +1786,7 @@ app.post('/api/setConfig', function(req, res) {
|
|||||||
let new_config_file = req.body.new_config_file;
|
let new_config_file = req.body.new_config_file;
|
||||||
if (new_config_file && new_config_file['YoutubeDLMaterial']) {
|
if (new_config_file && new_config_file['YoutubeDLMaterial']) {
|
||||||
let success = config_api.setConfigFile(new_config_file);
|
let success = config_api.setConfigFile(new_config_file);
|
||||||
|
loadConfigValues(); // reloads config values that exist as variables
|
||||||
res.send({
|
res.send({
|
||||||
success: success
|
success: success
|
||||||
});
|
});
|
||||||
@@ -2651,12 +2661,6 @@ app.get('/api/audio/:id', optionalJwt, function(req , res){
|
|||||||
// Downloads management
|
// Downloads management
|
||||||
|
|
||||||
app.get('/api/downloads', async (req, res) => {
|
app.get('/api/downloads', async (req, res) => {
|
||||||
/*
|
|
||||||
if (!last_downloads_check || Date.now() - last_downloads_check > downloads_check_interval) {
|
|
||||||
last_downloads_check = Date.now();
|
|
||||||
updateDownloads();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
res.send({downloads: downloads});
|
res.send({downloads: downloads});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
"allow_quality_select": true,
|
"allow_quality_select": true,
|
||||||
"download_only_mode": false,
|
"download_only_mode": false,
|
||||||
"allow_multi_download_mode": true,
|
"allow_multi_download_mode": true,
|
||||||
"settings_pin_required": false
|
"settings_pin_required": false,
|
||||||
|
"enable_downloads_manager": true
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
"use_API_key": false,
|
"use_API_key": false,
|
||||||
@@ -40,13 +41,15 @@
|
|||||||
"subscriptions_use_youtubedl_archive": true
|
"subscriptions_use_youtubedl_archive": true
|
||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"base_path": "users/"
|
"base_path": "users/",
|
||||||
|
"allow_registration": true
|
||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": "",
|
"custom_downloading_agent": "",
|
||||||
"multi_user_mode": false,
|
"multi_user_mode": false,
|
||||||
"allow_advanced_download": false
|
"allow_advanced_download": false,
|
||||||
|
"logger_level": "info"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
"allow_quality_select": true,
|
"allow_quality_select": true,
|
||||||
"download_only_mode": false,
|
"download_only_mode": false,
|
||||||
"allow_multi_download_mode": true,
|
"allow_multi_download_mode": true,
|
||||||
"settings_pin_required": false
|
"settings_pin_required": false,
|
||||||
|
"enable_downloads_manager": true
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
"use_API_key": false,
|
"use_API_key": false,
|
||||||
@@ -40,13 +41,15 @@
|
|||||||
"subscriptions_use_youtubedl_archive": true
|
"subscriptions_use_youtubedl_archive": true
|
||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"base_path": "users/"
|
"base_path": "users/",
|
||||||
|
"allow_registration": true
|
||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": "",
|
"custom_downloading_agent": "",
|
||||||
"multi_user_mode": false,
|
"multi_user_mode": false,
|
||||||
"allow_advanced_download": false
|
"allow_advanced_download": false,
|
||||||
|
"logger_level": "info"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ exports.registerUser = function(req, res) {
|
|||||||
var username = req.body.username;
|
var username = req.body.username;
|
||||||
var plaintextPassword = req.body.password;
|
var plaintextPassword = req.body.password;
|
||||||
|
|
||||||
|
if (userid !== 'admin' && !config_api.getConfigItem('ytdl_allow_registration')) {
|
||||||
|
res.sendStatus(409);
|
||||||
|
logger.error(`Registration failed for user ${userid}. Registration is disabled.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bcrypt.hash(plaintextPassword, saltRounds)
|
bcrypt.hash(plaintextPassword, saltRounds)
|
||||||
.then(function(hash) {
|
.then(function(hash) {
|
||||||
let new_user = {
|
let new_user = {
|
||||||
|
|||||||
@@ -140,10 +140,10 @@ module.exports = {
|
|||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"YoutubeDLMaterial": {
|
"YoutubeDLMaterial": {
|
||||||
"Host": {
|
"Host": {
|
||||||
"url": "http://example.com",
|
"url": "http://example.com",
|
||||||
"port": "17442"
|
"port": "17442"
|
||||||
},
|
},
|
||||||
"Encryption": {
|
"Encryption": {
|
||||||
"use-encryption": false,
|
"use-encryption": false,
|
||||||
"cert-file-path": "/etc/letsencrypt/live/example.com/fullchain.pem",
|
"cert-file-path": "/etc/letsencrypt/live/example.com/fullchain.pem",
|
||||||
@@ -156,12 +156,13 @@ DEFAULT_CONFIG = {
|
|||||||
"custom_args": ""
|
"custom_args": ""
|
||||||
},
|
},
|
||||||
"Extra": {
|
"Extra": {
|
||||||
"title_top": "Youtube Downloader",
|
"title_top": "YoutubeDL-Material",
|
||||||
"file_manager_enabled": true,
|
"file_manager_enabled": true,
|
||||||
"allow_quality_select": true,
|
"allow_quality_select": true,
|
||||||
"download_only_mode": false,
|
"download_only_mode": false,
|
||||||
"allow_multi_download_mode": true,
|
"allow_multi_download_mode": true,
|
||||||
"settings_pin_required": false
|
"settings_pin_required": false,
|
||||||
|
"enable_downloads_manager": true
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
"use_API_key": false,
|
"use_API_key": false,
|
||||||
@@ -180,13 +181,15 @@ DEFAULT_CONFIG = {
|
|||||||
"subscriptions_use_youtubedl_archive": true
|
"subscriptions_use_youtubedl_archive": true
|
||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"base_path": "users/"
|
"base_path": "users/",
|
||||||
|
"allow_registration": true
|
||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": "",
|
"custom_downloading_agent": "",
|
||||||
"multi_user_mode": false,
|
"multi_user_mode": false,
|
||||||
"allow_advanced_download": false
|
"allow_advanced_download": false,
|
||||||
|
"logger_level": "info"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ let CONFIG_ITEMS = {
|
|||||||
'key': 'ytdl_settings_pin_required',
|
'key': 'ytdl_settings_pin_required',
|
||||||
'path': 'YoutubeDLMaterial.Extra.settings_pin_required'
|
'path': 'YoutubeDLMaterial.Extra.settings_pin_required'
|
||||||
},
|
},
|
||||||
|
'ytdl_enable_downloads_manager': {
|
||||||
|
'key': 'ytdl_enable_downloads_manager',
|
||||||
|
'path': 'YoutubeDLMaterial.Extra.enable_downloads_manager'
|
||||||
|
},
|
||||||
|
|
||||||
// API
|
// API
|
||||||
'ytdl_use_api_key': {
|
'ytdl_use_api_key': {
|
||||||
@@ -122,6 +126,10 @@ let CONFIG_ITEMS = {
|
|||||||
'key': 'ytdl_users_base_path',
|
'key': 'ytdl_users_base_path',
|
||||||
'path': 'YoutubeDLMaterial.Users.base_path'
|
'path': 'YoutubeDLMaterial.Users.base_path'
|
||||||
},
|
},
|
||||||
|
'ytdl_allow_registration': {
|
||||||
|
'key': 'ytdl_allow_registration',
|
||||||
|
'path': 'YoutubeDLMaterial.Users.allow_registration'
|
||||||
|
},
|
||||||
|
|
||||||
// Advanced
|
// Advanced
|
||||||
'ytdl_use_default_downloading_agent': {
|
'ytdl_use_default_downloading_agent': {
|
||||||
@@ -140,6 +148,10 @@ let CONFIG_ITEMS = {
|
|||||||
'key': 'ytdl_allow_advanced_download',
|
'key': 'ytdl_allow_advanced_download',
|
||||||
'path': 'YoutubeDLMaterial.Advanced.allow_advanced_download'
|
'path': 'YoutubeDLMaterial.Advanced.allow_advanced_download'
|
||||||
},
|
},
|
||||||
|
'ytdl_logger_level': {
|
||||||
|
'key': 'ytdl_logger_level',
|
||||||
|
'path': 'YoutubeDLMaterial.Advanced.logger_level'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AVAILABLE_PERMISSIONS = [
|
AVAILABLE_PERMISSIONS = [
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<a mat-list-item (click)="sidenav.close()" routerLink='/home'><ng-container i18n="Navigation menu Home Page title">Home</ng-container></a>
|
<a mat-list-item (click)="sidenav.close()" routerLink='/home'><ng-container i18n="Navigation menu Home Page title">Home</ng-container></a>
|
||||||
<a *ngIf="allowSubscriptions && (!postsService.isLoggedIn || postsService.permissions.includes('subscriptions'))" mat-list-item (click)="sidenav.close()" routerLink='/subscriptions'><ng-container i18n="Navigation menu Subscriptions Page title">Subscriptions</ng-container></a>
|
<a *ngIf="allowSubscriptions && (!postsService.isLoggedIn || postsService.permissions.includes('subscriptions'))" mat-list-item (click)="sidenav.close()" routerLink='/subscriptions'><ng-container i18n="Navigation menu Subscriptions Page title">Subscriptions</ng-container></a>
|
||||||
<a *ngIf="!postsService.isLoggedIn || postsService.permissions.includes('downloads_manager')" mat-list-item (click)="sidenav.close()" routerLink='/downloads'><ng-container i18n="Navigation menu Downloads Page title">Downloads</ng-container></a>
|
<a *ngIf="enableDownloadsManager && (!postsService.isLoggedIn || postsService.permissions.includes('downloads_manager'))" mat-list-item (click)="sidenav.close()" routerLink='/downloads'><ng-container i18n="Navigation menu Downloads Page title">Downloads</ng-container></a>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content [style.background]="postsService.theme ? postsService.theme.background_color : null">
|
<mat-sidenav-content [style.background]="postsService.theme ? postsService.theme.background_color : null">
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export class AppComponent implements OnInit {
|
|||||||
defaultTheme = null;
|
defaultTheme = null;
|
||||||
allowThemeChange = null;
|
allowThemeChange = null;
|
||||||
allowSubscriptions = false;
|
allowSubscriptions = false;
|
||||||
|
enableDownloadsManager = false;
|
||||||
// defaults to true to prevent attack
|
// defaults to true to prevent attack
|
||||||
settingsPinRequired = true;
|
settingsPinRequired = true;
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ export class AppComponent implements OnInit {
|
|||||||
this.defaultTheme = themingExists ? this.postsService.config['Themes']['default_theme'] : 'default';
|
this.defaultTheme = themingExists ? this.postsService.config['Themes']['default_theme'] : 'default';
|
||||||
this.allowThemeChange = themingExists ? this.postsService.config['Themes']['allow_theme_change'] : true;
|
this.allowThemeChange = themingExists ? this.postsService.config['Themes']['allow_theme_change'] : true;
|
||||||
this.allowSubscriptions = this.postsService.config['Subscriptions']['allow_subscriptions'];
|
this.allowSubscriptions = this.postsService.config['Subscriptions']['allow_subscriptions'];
|
||||||
|
this.enableDownloadsManager = this.postsService.config['Extra']['enable_downloads_manager'];
|
||||||
|
|
||||||
// sets theme to config default if it doesn't exist
|
// sets theme to config default if it doesn't exist
|
||||||
if (!localStorage.getItem('theme')) {
|
if (!localStorage.getItem('theme')) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Component, OnInit, ViewChildren, QueryList, ElementRef } from '@angular/core';
|
import { Component, OnInit, ViewChildren, QueryList, ElementRef } from '@angular/core';
|
||||||
import { PostsService } from 'app/posts.services';
|
import { PostsService } from 'app/posts.services';
|
||||||
import { trigger, transition, animateChild, stagger, query, style, animate } from '@angular/animations';
|
import { trigger, transition, animateChild, stagger, query, style, animate } from '@angular/animations';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-downloads',
|
selector: 'app-downloads',
|
||||||
@@ -40,13 +41,21 @@ export class DownloadsComponent implements OnInit {
|
|||||||
|
|
||||||
valid_sessions_length = 0;
|
valid_sessions_length = 0;
|
||||||
|
|
||||||
constructor(public postsService: PostsService) { }
|
constructor(public postsService: PostsService, private router: Router) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.getCurrentDownloads();
|
this.getCurrentDownloads();
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.getCurrentDownloads();
|
this.getCurrentDownloads();
|
||||||
}, this.downloads_check_interval);
|
}, this.downloads_check_interval);
|
||||||
|
|
||||||
|
this.postsService.service_initialized.subscribe(init => {
|
||||||
|
if (init) {
|
||||||
|
if (!this.postsService.config['Extra']['enable_downloads_manager']) {
|
||||||
|
this.router.navigate(['/home']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentDownloads() {
|
getCurrentDownloads() {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export class LoginComponent implements OnInit {
|
|||||||
loggingIn = false;
|
loggingIn = false;
|
||||||
|
|
||||||
// registration
|
// registration
|
||||||
registrationEnabled = true;
|
registrationEnabled = false;
|
||||||
registrationUsernameInput = '';
|
registrationUsernameInput = '';
|
||||||
registrationPasswordInput = '';
|
registrationPasswordInput = '';
|
||||||
registrationPasswordConfirmationInput = '';
|
registrationPasswordConfirmationInput = '';
|
||||||
@@ -35,6 +35,7 @@ export class LoginComponent implements OnInit {
|
|||||||
if (!this.postsService.config['Advanced']['multi_user_mode']) {
|
if (!this.postsService.config['Advanced']['multi_user_mode']) {
|
||||||
this.router.navigate(['/home']);
|
this.router.navigate(['/home']);
|
||||||
}
|
}
|
||||||
|
this.registrationEnabled = this.postsService.config['Users'] && this.postsService.config['Users']['allow_registration'];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div *ngIf="dataSource; else loading">
|
<div *ngIf="dataSource; else loading">
|
||||||
<div style="padding: 15px">
|
<div style="padding: 15px">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="table table-responsive p-5">
|
<div class="table table-responsive px-5 pb-4 pt-2">
|
||||||
<div class="example-header">
|
<div class="example-header">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Search">
|
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Search">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.edit-role {
|
.edit-role {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -80px;
|
top: -50px;
|
||||||
left: 35px;
|
left: 35px;
|
||||||
}
|
}
|
||||||
@@ -14,13 +14,13 @@
|
|||||||
<div *ngIf="new_config" class="container-fluid">
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [(ngModel)]="new_config['Host']['url']" matInput placeholder="URL" i18n-placeholder="URL input placeholder" required>
|
<input [(ngModel)]="new_config['Host']['url']" matInput placeholder="URL" i18n-placeholder="URL input placeholder" required>
|
||||||
<mat-hint><ng-container i18n="URL setting input hint">URL this app will be accessed from, without the port.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="URL setting input hint">URL this app will be accessed from, without the port.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mb-4">
|
<div class="col-12 mb-4">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [(ngModel)]="new_config['Host']['port']" matInput placeholder="Port" i18n-placeholder="Port input placeholder" required>
|
<input [(ngModel)]="new_config['Host']['port']" matInput placeholder="Port" i18n-placeholder="Port input placeholder" required>
|
||||||
<mat-hint><ng-container i18n="Port setting input hint">The desired port. Default is 17442.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Port setting input hint">The desired port. Default is 17442.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -28,6 +28,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Advanced']['multi_user_mode']"><ng-container i18n="Multi user mode setting">Multi-user mode</ng-container></mat-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-3 mb-4">
|
||||||
|
<mat-form-field class="text-field">
|
||||||
|
<input [(ngModel)]="new_config['Users']['base_path']" matInput placeholder="Users base path" i18n-placeholder="Users base path placeholder" required>
|
||||||
|
<mat-hint><ng-container i18n="Users base path hint">Base path for users and their downloaded videos.</ng-container></mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
<div *ngIf="new_config" class="container-fluid">
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
@@ -35,13 +49,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['Encryption']['use-encryption']" [(ngModel)]="new_config['Encryption']['cert-file-path']" matInput placeholder="Cert file path" i18n-placeholder="Cert file path input placeholder">
|
<input [disabled]="!new_config['Encryption']['use-encryption']" [(ngModel)]="new_config['Encryption']['cert-file-path']" matInput placeholder="Cert file path" i18n-placeholder="Cert file path input placeholder">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['Encryption']['use-encryption']" [(ngModel)]="new_config['Encryption']['key-file-path']" matInput placeholder="Key file path" i18n-placeholder="Key file path input placeholder">
|
<input [disabled]="!new_config['Encryption']['use-encryption']" [(ngModel)]="new_config['Encryption']['key-file-path']" matInput placeholder="Key file path" i18n-placeholder="Key file path input placeholder">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,13 +68,13 @@
|
|||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Subscriptions']['allow_subscriptions']"><ng-container i18n="Allow subscriptions setting">Allow subscriptions</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Subscriptions']['allow_subscriptions']"><ng-container i18n="Allow subscriptions setting">Allow subscriptions</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['Subscriptions']['allow_subscriptions']" [(ngModel)]="new_config['Subscriptions']['subscriptions_base_path']" matInput placeholder="Subscriptions base path" i18n-placeholder="Subscriptions base path input setting placeholder">
|
<input [disabled]="!new_config['Subscriptions']['allow_subscriptions']" [(ngModel)]="new_config['Subscriptions']['subscriptions_base_path']" matInput placeholder="Subscriptions base path" i18n-placeholder="Subscriptions base path input setting placeholder">
|
||||||
<mat-hint><ng-container i18n="Subscriptions base path setting input hint">Base path for videos from your subscribed channels and playlists. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Subscriptions base path setting input hint">Base path for videos from your subscribed channels and playlists. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mt-5">
|
<div class="col-12 mt-5">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['Subscriptions']['allow_subscriptions']" [(ngModel)]="new_config['Subscriptions']['subscriptions_check_interval']" matInput placeholder="Check interval" i18n-placeholder="Check interval input setting placeholder">
|
<input [disabled]="!new_config['Subscriptions']['allow_subscriptions']" [(ngModel)]="new_config['Subscriptions']['subscriptions_check_interval']" matInput placeholder="Check interval" i18n-placeholder="Check interval input setting placeholder">
|
||||||
<mat-hint><ng-container i18n="Check interval setting input hint">Unit is seconds, only include numbers.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Check interval setting input hint">Unit is seconds, only include numbers.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -93,7 +107,7 @@
|
|||||||
<div *ngIf="new_config" class="container-fluid">
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<mat-form-field>
|
<mat-form-field color="accent">
|
||||||
<mat-label><ng-container i18n="Language select label">Language</ng-container></mat-label>
|
<mat-label><ng-container i18n="Language select label">Language</ng-container></mat-label>
|
||||||
<mat-select (selectionChange)="localeSelectChanged($event.value)" [(value)]="initialLocale">
|
<mat-select (selectionChange)="localeSelectChanged($event.value)" [(value)]="initialLocale">
|
||||||
<mat-option *ngFor="let locale of supported_locales" [value]="locale">
|
<mat-option *ngFor="let locale of supported_locales" [value]="locale">
|
||||||
@@ -113,21 +127,21 @@
|
|||||||
<div *ngIf="new_config" class="container-fluid">
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input matInput [(ngModel)]="new_config['Downloader']['path-audio']" placeholder="Audio folder path" i18n-placeholder="Audio folder path input placeholder" required>
|
<input matInput [(ngModel)]="new_config['Downloader']['path-audio']" placeholder="Audio folder path" i18n-placeholder="Audio folder path input placeholder" required>
|
||||||
<mat-hint><ng-container i18n="Aduio path setting input hint">Path for audio only downloads. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Aduio path setting input hint">Path for audio only downloads. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 mt-5">
|
<div class="col-12 mt-5">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input matInput [(ngModel)]="new_config['Downloader']['path-video']" placeholder="Video folder path" i18n-placeholder="Video folder path input placeholder" required>
|
<input matInput [(ngModel)]="new_config['Downloader']['path-video']" placeholder="Video folder path" i18n-placeholder="Video folder path input placeholder" required>
|
||||||
<mat-hint><ng-container i18n="Video path setting input hint">Path for video downloads. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Video path setting input hint">Path for video downloads. It is relative to YTDL-Material's root folder.</ng-container></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 mt-5">
|
<div class="col-12 mt-5">
|
||||||
<mat-form-field style="margin-right: 12px;" color="accent">
|
<mat-form-field class="text-field" style="margin-right: 12px;" color="accent">
|
||||||
<textarea matInput [(ngModel)]="new_config['Downloader']['custom_args']" placeholder="Custom args" i18n-placeholder="Custom args input placeholder"></textarea>
|
<textarea matInput [(ngModel)]="new_config['Downloader']['custom_args']" placeholder="Custom args" i18n-placeholder="Custom args input placeholder"></textarea>
|
||||||
<mat-hint><ng-container i18n="Custom args setting input hint">Global custom args for downloads on the home page.</ng-container></mat-hint>
|
<mat-hint><ng-container i18n="Custom args setting input hint">Global custom args for downloads on the home page.</ng-container></mat-hint>
|
||||||
<button class="args-edit-button" (click)="openArgsModifierDialog()" mat-icon-button><mat-icon>edit</mat-icon></button>
|
<button class="args-edit-button" (click)="openArgsModifierDialog()" mat-icon-button><mat-icon>edit</mat-icon></button>
|
||||||
@@ -148,7 +162,7 @@
|
|||||||
<div *ngIf="new_config" class="container-fluid">
|
<div *ngIf="new_config" class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [(ngModel)]="new_config['Extra']['title_top']" matInput placeholder="Top title" i18n-placeholder="Top title input placeholder" required>
|
<input [(ngModel)]="new_config['Extra']['title_top']" matInput placeholder="Top title" i18n-placeholder="Top title input placeholder" required>
|
||||||
<mat-hint></mat-hint>
|
<mat-hint></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -156,6 +170,9 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['file_manager_enabled']"><ng-container i18n="File manager enabled setting">File manager enabled</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['file_manager_enabled']"><ng-container i18n="File manager enabled setting">File manager enabled</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['enable_downloads_manager']"><ng-container i18n="Downloads manager enabled setting">Downloads manager enabled</ng-container></mat-checkbox>
|
||||||
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['allow_quality_select']"><ng-container i18n="Allow quality seelct setting">Allow quality select</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['allow_quality_select']"><ng-container i18n="Allow quality seelct setting">Allow quality select</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
@@ -163,7 +180,7 @@
|
|||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['download_only_mode']"><ng-container i18n="Download only mode setting">Download only mode</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['download_only_mode']"><ng-container i18n="Download only mode setting">Download only mode</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['allow_multi_download_mode']"><ng-container i18n="Allow multi-downloade mode setting">Allow multi-download mode</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Extra']['allow_multi_download_mode']"><ng-container i18n="Allow multi-download mode setting">Allow multi-download mode</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-checkbox [disabled]="new_config['Advanced']['multi_user_mode']" color="accent" [(ngModel)]="new_config['Extra']['settings_pin_required']"><ng-container i18n="Require pin for settings setting">Require pin for settings</ng-container></mat-checkbox>
|
<mat-checkbox [disabled]="new_config['Advanced']['multi_user_mode']" color="accent" [(ngModel)]="new_config['Extra']['settings_pin_required']"><ng-container i18n="Require pin for settings setting">Require pin for settings</ng-container></mat-checkbox>
|
||||||
@@ -179,7 +196,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12 mb-3">
|
<div class="col-12 mb-3">
|
||||||
<div class="enable-api-key-div">
|
<div class="enable-api-key-div">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['API']['use_API_key']" [(ngModel)]="new_config['API']['API_key']" matInput placeholder="Public API Key" i18n-placeholder="Public API Key setting placeholder" required>
|
<input [disabled]="!new_config['API']['use_API_key']" [(ngModel)]="new_config['API']['API_key']" matInput placeholder="Public API Key" i18n-placeholder="Public API Key setting placeholder" required>
|
||||||
<mat-hint><a target="_blank" href="https://stoplight.io/p/docs/gh/tzahi12345/youtubedl-material"><ng-container i18n="View API docs setting hint">View documentation</ng-container></a></mat-hint>
|
<mat-hint><a target="_blank" href="https://stoplight.io/p/docs/gh/tzahi12345/youtubedl-material"><ng-container i18n="View API docs setting hint">View documentation</ng-container></a></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -197,7 +214,7 @@
|
|||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['API']['use_youtube_API']"><ng-container i18n="Use YouTube API setting">Use YouTube API</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['API']['use_youtube_API']"><ng-container i18n="Use YouTube API setting">Use YouTube API</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mb-3">
|
<div class="col-12 mb-3">
|
||||||
<mat-form-field color="accent">
|
<mat-form-field class="text-field" color="accent">
|
||||||
<input [disabled]="!new_config['API']['use_youtube_API']" [(ngModel)]="new_config['API']['youtube_API_key']" matInput placeholder="Youtube API Key" i18n-placeholder="Youtube API Key setting placeholder" required>
|
<input [disabled]="!new_config['API']['use_youtube_API']" [(ngModel)]="new_config['API']['youtube_API_key']" matInput placeholder="Youtube API Key" i18n-placeholder="Youtube API Key setting placeholder" required>
|
||||||
<mat-hint><a target="_blank" href="https://developers.google.com/youtube/v3/getting-started"><ng-container i18n="Youtube API Key setting hint">Generating a key is easy!</ng-container></a></mat-hint>
|
<mat-hint><a target="_blank" href="https://developers.google.com/youtube/v3/getting-started"><ng-container i18n="Youtube API Key setting hint">Generating a key is easy!</ng-container></a></mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -252,12 +269,21 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-12 mt-2 mb-1">
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label><ng-container i18n="Logger level select label">Select a downloader</ng-container></mat-label>
|
||||||
|
<mat-select color="accent" [(ngModel)]="new_config['Advanced']['logger_level']">
|
||||||
|
<mat-option value="debug">Debug</mat-option>
|
||||||
|
<mat-option value="verbose">Verbose</mat-option>
|
||||||
|
<mat-option value="info">Info</mat-option>
|
||||||
|
<mat-option value="warn">Warn</mat-option>
|
||||||
|
<mat-option value="error">Error</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Advanced']['allow_advanced_download']"><ng-container i18n="Allow advanced downloading setting">Allow advanced download</ng-container></mat-checkbox>
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Advanced']['allow_advanced_download']"><ng-container i18n="Allow advanced downloading setting">Allow advanced download</ng-container></mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mb-3 mt-3">
|
|
||||||
<mat-checkbox color="accent" [(ngModel)]="new_config['Advanced']['multi_user_mode']"><ng-container i18n="Multi user mode setting">Multi-user mode</ng-container></mat-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
@@ -267,6 +293,9 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab *ngIf="postsService.config && postsService.config.Advanced.multi_user_mode" label="Users" i18n-label="Users settings label">
|
<mat-tab *ngIf="postsService.config && postsService.config.Advanced.multi_user_mode" label="Users" i18n-label="Users settings label">
|
||||||
|
<div style="margin-left: 48px; margin-top: 24px;">
|
||||||
|
<mat-checkbox color="accent" [(ngModel)]="new_config['Users']['allow_registration']"><ng-container i18n="Allow registration setting">Allow user registration</ng-container></mat-checkbox>
|
||||||
|
</div>
|
||||||
<app-modify-users></app-modify-users>
|
<app-modify-users></app-modify-users>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
|
|||||||
@@ -21,3 +21,7 @@
|
|||||||
.api-key-div {
|
.api-key-div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-field {
|
||||||
|
min-width: 30%;
|
||||||
|
}
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
"allow_quality_select": true,
|
"allow_quality_select": true,
|
||||||
"download_only_mode": false,
|
"download_only_mode": false,
|
||||||
"allow_multi_download_mode": true,
|
"allow_multi_download_mode": true,
|
||||||
"settings_pin_required": false
|
"settings_pin_required": false,
|
||||||
|
"enable_downloads_manager": true
|
||||||
},
|
},
|
||||||
"API": {
|
"API": {
|
||||||
"use_API_key": false,
|
"use_API_key": false,
|
||||||
@@ -40,13 +41,15 @@
|
|||||||
"subscriptions_use_youtubedl_archive": true
|
"subscriptions_use_youtubedl_archive": true
|
||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
"base_path": "users/"
|
"base_path": "users/",
|
||||||
|
"allow_registration": true
|
||||||
},
|
},
|
||||||
"Advanced": {
|
"Advanced": {
|
||||||
"use_default_downloading_agent": true,
|
"use_default_downloading_agent": true,
|
||||||
"custom_downloading_agent": "",
|
"custom_downloading_agent": "",
|
||||||
"multi_user_mode": true,
|
"multi_user_mode": true,
|
||||||
"allow_advanced_download": true
|
"allow_advanced_download": true,
|
||||||
|
"logger_level": "debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user