diff --git a/app/main.py b/app/main.py index 90554ee..5854acc 100644 --- a/app/main.py +++ b/app/main.py @@ -92,6 +92,20 @@ class Config: sys.exit(1) self.YTDL_OPTIONS.update(opts) + def update_ytdl_options_file(self): + if not self.YTDL_OPTIONS_FILE: + log.info('YTDL_OPTIONS_FILE not set, writing to default location') + self.YTDL_OPTIONS_FILE = os.path.join(self.DOWNLOAD_DIR,'ytdl_options.json') + log.info('Writing YTDL_OPTIONS to %s', self.YTDL_OPTIONS_FILE) + try: + with open(config.YTDL_OPTIONS_FILE, 'w') as f: + f.write(serializer.encode(config.YTDL_OPTIONS)) + except: + log.error('Failed to write YTDL_OPTIONS to %s', self.YTDL_OPTIONS_FILE) + self.YTDL_OPTIONS_FILE = '' + return False + return True + config = Config() class ObjectSerializer(json.JSONEncoder): @@ -242,6 +256,27 @@ def get_custom_dirs(): "audio_download_dir": audio_download_dir } +@routes.get(config.URL_PREFIX + 'ytdl_options') +async def ytdl_options(request): + log.info("Sending yt-dlp options") + return web.Response(text=serializer.encode(config.YTDL_OPTIONS)) + +@routes.post(config.URL_PREFIX + 'ytdl_options') +async def update_ytdl_options(request): + try: + post = await request.json() + assert isinstance(post, dict) + except (json.decoder.JSONDecodeError, AssertionError): + log.info("Bad request: invalid data") + raise web.HTTPBadRequest(reason="invalid data,need json") + config.YTDL_OPTIONS = post + + msg = 'Options updated' + if not config.update_ytdl_options_file(): + msg += ', but failed to write to file' + + return web.Response(text=serializer.encode({'msg':msg,'data':config.YTDL_OPTIONS})) + @routes.get(config.URL_PREFIX) def index(request): response = web.FileResponse(os.path.join(config.BASE_DIR, 'ui/dist/metube/browser/index.html')) diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index 87fb48a..58c2ae8 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -62,6 +62,26 @@ +
diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index d8362b6..b6ec628 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -1,8 +1,10 @@ import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { faTrashAlt, faCheckCircle, faTimesCircle, IconDefinition } from '@fortawesome/free-regular-svg-icons'; import { faRedoAlt, faSun, faMoon, faCircleHalfStroke, faCheck, faExternalLinkAlt, faDownload, faFileImport, faFileExport, faCopy, faClock, faTachometerAlt } from '@fortawesome/free-solid-svg-icons'; import { faGithub } from '@fortawesome/free-brands-svg-icons'; +import { faGear } from "@fortawesome/free-solid-svg-icons"; import { CookieService } from 'ngx-cookie-service'; import { map, Observable, of, distinctUntilChanged } from 'rxjs'; @@ -11,6 +13,8 @@ import { MasterCheckboxComponent } from './master-checkbox.component'; import { Formats, Format, Quality } from './formats'; import { Theme, Themes } from './theme'; import {KeyValue} from "@angular/common"; +import { Setting, Settings } from './settings'; +import { YtdlpOptionComponent } from './settings/ytdlp-option/ytdlp-option.component'; @Component({ selector: 'app-root', @@ -31,6 +35,7 @@ export class AppComponent implements AfterViewInit { playlistItemLimit: number; addInProgress = false; themes: Theme[] = Themes; + settings: Setting[] = Settings; activeTheme: Theme; customDirs$: ObservableEdit the yt-dlp configuration below.
+ + +