Added add_batch endpoint.
This commit is contained in:
parent
b7bf9627a1
commit
83745c1f98
4 changed files with 78 additions and 20 deletions
57
app/main.py
57
app/main.py
|
|
@ -12,8 +12,6 @@ import logging
|
|||
import caribou
|
||||
import sqlite3
|
||||
|
||||
log = logging.getLogger('main')
|
||||
|
||||
|
||||
class Main:
|
||||
config: Config = None
|
||||
|
|
@ -87,7 +85,6 @@ class Main:
|
|||
self.start()
|
||||
|
||||
def start(self):
|
||||
log.info(f"Listening on {self.config.host}:{self.config.port}")
|
||||
web.run_app(
|
||||
self.app,
|
||||
host=self.config.host,
|
||||
|
|
@ -118,7 +115,7 @@ class Main:
|
|||
if ytdlp_config is None:
|
||||
ytdlp_config = {}
|
||||
|
||||
status = await self.dqueue.add(
|
||||
status = await self.add(
|
||||
url=url,
|
||||
quality=quality,
|
||||
format=format,
|
||||
|
|
@ -130,6 +127,33 @@ class Main:
|
|||
|
||||
return web.Response(text=self.serializer.encode(status))
|
||||
|
||||
@self.routes.post(self.config.url_prefix + 'add_batch')
|
||||
async def add_batch(request: Request) -> Response:
|
||||
status = {}
|
||||
|
||||
post = await request.json()
|
||||
if not isinstance(post, list):
|
||||
raise web.HTTPBadRequest()
|
||||
|
||||
for item in post:
|
||||
if not isinstance(item, dict):
|
||||
raise web.HTTPBadRequest(
|
||||
'Invalid request body expecting list with dicts.')
|
||||
if not item.get('url'):
|
||||
raise web.HTTPBadRequest(reason='url is required')
|
||||
|
||||
status[item.get('url')] = await self.add(
|
||||
url=item.get('url'),
|
||||
quality=item.get('quality'),
|
||||
format=item.get('format'),
|
||||
folder=item.get('folder'),
|
||||
ytdlp_cookies=item.get('ytdlp_cookies'),
|
||||
ytdlp_config=item.get('ytdlp_config'),
|
||||
output_template=item.get('output_template')
|
||||
)
|
||||
|
||||
return web.Response(text=self.serializer.encode(status))
|
||||
|
||||
@self.routes.delete(self.config.url_prefix + 'delete')
|
||||
async def delete(request: Request) -> Response:
|
||||
post = await request.json()
|
||||
|
|
@ -208,6 +232,31 @@ class Main:
|
|||
'Could not find the frontend UI static assets. Please run `node_modules/.bin/ng build` inside the frontend folder.') from e
|
||||
raise e
|
||||
|
||||
async def add(
|
||||
self,
|
||||
url: str,
|
||||
quality: str,
|
||||
format: str,
|
||||
folder: str,
|
||||
ytdlp_cookies: str,
|
||||
ytdlp_config: dict,
|
||||
output_template: str
|
||||
) -> dict[str, str]:
|
||||
if ytdlp_config is None:
|
||||
ytdlp_config = {}
|
||||
|
||||
status = await self.dqueue.add(
|
||||
url=url,
|
||||
quality=quality,
|
||||
format=format,
|
||||
folder=folder,
|
||||
ytdlp_cookies=ytdlp_cookies,
|
||||
ytdlp_config=ytdlp_config,
|
||||
output_template=output_template
|
||||
)
|
||||
|
||||
return status
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ import logging
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
log = logging.getLogger('config')
|
||||
|
||||
import coloredlogs
|
||||
|
||||
class Config:
|
||||
config_path: str = '.'
|
||||
|
|
@ -32,6 +30,8 @@ class Config:
|
|||
|
||||
base_path: str = ''
|
||||
|
||||
logging_level: str = 'info'
|
||||
|
||||
_boolean_vars: tuple = ('keep_archive', 'ytdl_debug')
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -59,7 +59,7 @@ class Config:
|
|||
for key in re.findall(r'\{.*?\}', v):
|
||||
localKey: str = key[1:-1]
|
||||
if localKey not in self.__dict__:
|
||||
log.error(
|
||||
logging.error(
|
||||
f'Config variable "{k}" had non exisitng config reference "{key}"')
|
||||
sys.exit(1)
|
||||
v = v.replace(key, getattr(self, localKey))
|
||||
|
|
@ -68,27 +68,41 @@ class Config:
|
|||
|
||||
if k in self._boolean_vars:
|
||||
if str(v).lower() not in (True, False, 'true', 'false', 'on', 'off', '1', '0'):
|
||||
log.error(
|
||||
raise ValueError(
|
||||
f'Config variable "{k}" is set to a non-boolean value "{v}".')
|
||||
sys.exit(1)
|
||||
|
||||
setattr(self, k, str(v).lower() in (True, 'true', 'on', '1'))
|
||||
|
||||
if not self.url_prefix.endswith('/'):
|
||||
self.url_prefix += '/'
|
||||
|
||||
numeric_level = getattr(
|
||||
logging, self.logging_level.upper(), None)
|
||||
|
||||
if not isinstance(numeric_level, int):
|
||||
raise ValueError(f"Invalid log level: {self.logging_level}")
|
||||
|
||||
logging.basicConfig(
|
||||
force=True,
|
||||
level=numeric_level,
|
||||
format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s"
|
||||
)
|
||||
|
||||
coloredlogs.install()
|
||||
|
||||
if isinstance(self.ytdl_options, str):
|
||||
try:
|
||||
self.ytdl_options = json.loads(self.ytdl_options)
|
||||
assert isinstance(self.ytdl_options, dict)
|
||||
except (json.decoder.JSONDecodeError, AssertionError) as e:
|
||||
log.error(f'JSON error in "YTP_YTDL_OPTIONS": {e}')
|
||||
logging.error(f'JSON error in "YTP_YTDL_OPTIONS": {e}')
|
||||
sys.exit(1)
|
||||
|
||||
if self.ytdl_options_file:
|
||||
log.info(
|
||||
logging.info(
|
||||
f'Loading yt-dlp custom options from "{self.ytdl_options_file}"')
|
||||
if not os.path.exists(self.ytdl_options_file):
|
||||
log.error(
|
||||
logging.error(
|
||||
f'"YTP_YTDL_OPTIONS_FILE" ENV points to non-existent file: "{self.ytdl_options_file}"')
|
||||
else:
|
||||
try:
|
||||
|
|
@ -97,7 +111,8 @@ class Config:
|
|||
assert isinstance(opts, dict)
|
||||
self.ytdl_options.update(opts)
|
||||
except (json.decoder.JSONDecodeError, AssertionError) as e:
|
||||
log.error(f'JSON error in "{self.ytdl_options_file}": {e}')
|
||||
logging.error(
|
||||
f'JSON error in "{self.ytdl_options_file}": {e}')
|
||||
sys.exit(1)
|
||||
|
||||
if self.keep_archive:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from collections import OrderedDict
|
||||
import json
|
||||
import logging
|
||||
import sqlite3
|
||||
from src.Utils import calcDownloadPath
|
||||
from src.Config import Config
|
||||
|
|
@ -55,7 +54,6 @@ class DataStore:
|
|||
)
|
||||
|
||||
for row in cursor:
|
||||
logging.debug(row)
|
||||
data: dict = json.loads(row['data'])
|
||||
key: str = data.pop('_id')
|
||||
item: ItemDTO = ItemDTO(**data)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ def get_opts(format: str, quality: str, ytdl_opts: dict) -> dict:
|
|||
Returns:
|
||||
ytdl_opts: Extra options
|
||||
"""
|
||||
logging.debug(f"get_opts: {format} {quality} {ytdl_opts}")
|
||||
opts = copy.deepcopy(ytdl_opts)
|
||||
if not opts:
|
||||
opts: dict = {
|
||||
|
|
@ -107,8 +106,6 @@ def get_opts(format: str, quality: str, ytdl_opts: dict) -> dict:
|
|||
postprocessors.append(
|
||||
{"key": "FFmpegThumbnailsConvertor", "format": "jpg", "when": "before_dl"})
|
||||
|
||||
logging.debug(
|
||||
f"Postprocessors: {opts['postprocessors']} + {postprocessors}")
|
||||
opts["postprocessors"] = postprocessors + \
|
||||
(opts["postprocessors"] if "postprocessors" in opts else [])
|
||||
return opts
|
||||
|
|
@ -119,7 +116,6 @@ def getVideoInfo(url: str, ytdlp_opts: dict = None) -> (Any | dict[str, Any] | N
|
|||
'quiet': True,
|
||||
'no_color': True,
|
||||
'extract_flat': True,
|
||||
|
||||
}
|
||||
|
||||
if ytdlp_opts:
|
||||
|
|
|
|||
Loading…
Reference in a new issue