remove presets v1.0
This commit is contained in:
parent
ff2139261b
commit
fa9c084397
8 changed files with 112 additions and 237 deletions
|
|
@ -392,7 +392,7 @@ class DownloadQueue(metaclass=Singleton):
|
|||
{ "status": "text" }
|
||||
|
||||
"""
|
||||
_preset = Presets.get_instance().get(name=preset)
|
||||
_preset = Presets.get_instance().get(preset)
|
||||
|
||||
config = config if config else {}
|
||||
if cli:
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ class HttpAPI(Common):
|
|||
|
||||
preset = request.query.get("preset")
|
||||
if preset:
|
||||
exists = Presets.get_instance().get(name=preset)
|
||||
exists = Presets.get_instance().get(preset)
|
||||
if not exists:
|
||||
return web.json_response(
|
||||
data={"status": False, "message": f"Preset '{preset}' does not exist."},
|
||||
|
|
@ -674,7 +674,7 @@ class HttpAPI(Common):
|
|||
|
||||
preset = request.query.get("preset")
|
||||
if preset:
|
||||
exists = Presets.get_instance().get(name=preset)
|
||||
exists = Presets.get_instance().get(preset)
|
||||
if not exists:
|
||||
return web.json_response(
|
||||
data={"status": False, "message": f"Preset '{preset}' does not exist."},
|
||||
|
|
@ -790,18 +790,6 @@ class HttpAPI(Common):
|
|||
if not item.get("id", None) or not validate_uuid(item.get("id"), version=4):
|
||||
item["id"] = str(uuid.uuid4())
|
||||
|
||||
if not item.get("args", None) or str(item.get("args")).strip() == "":
|
||||
item["args"] = {}
|
||||
|
||||
if item.get("args", None) and isinstance(item.get("args"), str):
|
||||
item["args"] = json.loads(item.get("args"))
|
||||
|
||||
if not item.get("postprocessors", None) or str(item.get("postprocessors")).strip() == "":
|
||||
item["postprocessors"] = []
|
||||
|
||||
if item.get("postprocessors", None) and isinstance(item.get("postprocessors"), str):
|
||||
item["postprocessors"] = json.loads(item.get("postprocessors"))
|
||||
|
||||
try:
|
||||
cls.validate(item)
|
||||
except ValueError as e:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from .config import Config
|
|||
from .encoder import Encoder
|
||||
from .Events import EventBus, Events
|
||||
from .Singleton import Singleton
|
||||
from .Utils import arg_converter, clean_item
|
||||
|
||||
LOG = logging.getLogger("presets")
|
||||
|
||||
|
|
@ -26,12 +27,6 @@ class Preset:
|
|||
format: str
|
||||
"""The format of the preset."""
|
||||
|
||||
args: dict[str, list[str] | bool] = field(default_factory=dict)
|
||||
"""The arguments of the preset."""
|
||||
|
||||
postprocessors: list = field(default_factory=list)
|
||||
"""The postprocessors of the preset."""
|
||||
|
||||
folder: str = ""
|
||||
"""The default download folder to use if non is given."""
|
||||
|
||||
|
|
@ -83,13 +78,19 @@ class Presets(metaclass=Singleton):
|
|||
pass
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), "presets.json")) as f:
|
||||
self._default_presets = [Preset(**preset) for preset in json.load(f)]
|
||||
for i, preset in enumerate(json.load(f)):
|
||||
try:
|
||||
self.validate(preset)
|
||||
self._default_presets.append(Preset(**preset))
|
||||
except Exception as e:
|
||||
LOG.error(f"Failed to parse default preset '{i}'. '{e!s}'.")
|
||||
continue
|
||||
|
||||
EventBus.get_instance().subscribe(
|
||||
Events.PRESETS_ADD,
|
||||
lambda data, _, **kwargs: self.add(**data.data), # noqa: ARG005
|
||||
f"{__class__.__name__}.save",
|
||||
)
|
||||
def event_handler(_, __):
|
||||
msg = "Not implemented"
|
||||
raise Exception(msg)
|
||||
|
||||
EventBus.get_instance().subscribe(Events.PRESETS_ADD, event_handler, f"{__class__.__name__}.save")
|
||||
|
||||
@staticmethod
|
||||
def get_instance() -> "Presets":
|
||||
|
|
@ -150,22 +151,27 @@ class Presets(metaclass=Singleton):
|
|||
LOG.info(f"No presets were defined in '{self._file}'.")
|
||||
return self
|
||||
|
||||
needSaving = False
|
||||
need_save = False
|
||||
|
||||
for i, preset in enumerate(presets):
|
||||
try:
|
||||
if "id" not in preset:
|
||||
preset["id"] = str(uuid.uuid4())
|
||||
needSaving = True
|
||||
need_save = True
|
||||
|
||||
preset, preset_status = clean_item(preset, keys=("args", "postprocessors"))
|
||||
preset = Preset(**preset)
|
||||
|
||||
if preset_status:
|
||||
need_save = True
|
||||
|
||||
self._presets.append(preset)
|
||||
except Exception as e:
|
||||
LOG.error(f"Failed to parse preset at list position '{i}'. '{e!s}'.")
|
||||
continue
|
||||
|
||||
if needSaving:
|
||||
LOG.info("Saving presets due to missing ids.")
|
||||
if need_save:
|
||||
LOG.info("Saving presets due to format, or id change.")
|
||||
self.save(self._presets)
|
||||
|
||||
return self
|
||||
|
|
@ -198,7 +204,7 @@ class Presets(metaclass=Singleton):
|
|||
"""
|
||||
if not isinstance(preset, dict):
|
||||
if not isinstance(preset, Preset):
|
||||
msg = "Invalid preset type."
|
||||
msg = f"Invalid preset type. Was expecting a (Preset|dict), but got '{type(preset).__name__}'."
|
||||
raise ValueError(msg) # noqa: TRY004
|
||||
|
||||
preset = preset.serialize()
|
||||
|
|
@ -215,18 +221,8 @@ class Presets(metaclass=Singleton):
|
|||
msg = "No format found."
|
||||
raise ValueError(msg)
|
||||
|
||||
if preset.get("args") and not isinstance(preset.get("args"), dict):
|
||||
msg = "Invalid args type. expected dict."
|
||||
raise ValueError(msg)
|
||||
|
||||
if preset.get("postprocessors") and not isinstance(preset.get("postprocessors"), list):
|
||||
msg = "Invalid postprocessors type. expected list."
|
||||
raise ValueError(msg)
|
||||
|
||||
if preset.get("cli"):
|
||||
try:
|
||||
from .Utils import arg_converter
|
||||
|
||||
arg_converter(args=preset.get("cli"))
|
||||
except Exception as e:
|
||||
msg = f"Invalid cli options. '{e!s}'."
|
||||
|
|
@ -270,26 +266,24 @@ class Presets(metaclass=Singleton):
|
|||
|
||||
return self
|
||||
|
||||
def get(self, id: str | None = None, name: str | None = None) -> Preset | None:
|
||||
def get(self, id_or_name: str) -> Preset | None:
|
||||
"""
|
||||
Get the preset by id or name.
|
||||
|
||||
Args:
|
||||
id (str|None): The id of the preset.
|
||||
name (str|None): The name of the preset.
|
||||
id_or_name (str): The id or name of the preset.
|
||||
|
||||
Returns:
|
||||
Preset|None: The preset if found, None otherwise.
|
||||
|
||||
"""
|
||||
if not id and not name:
|
||||
if not id_or_name:
|
||||
return None
|
||||
|
||||
for preset in self.get_all():
|
||||
if preset.id == id:
|
||||
return preset
|
||||
if id_or_name not in (preset.id, preset.name):
|
||||
continue
|
||||
|
||||
if preset.name == name:
|
||||
return preset
|
||||
return preset
|
||||
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from .encoder import Encoder
|
|||
from .Events import EventBus, Events, error, info, success
|
||||
from .Scheduler import Scheduler
|
||||
from .Singleton import Singleton
|
||||
from .Utils import clean_item
|
||||
|
||||
LOG = logging.getLogger("tasks")
|
||||
|
||||
|
|
@ -140,13 +141,13 @@ class Tasks(metaclass=Singleton):
|
|||
LOG.info(f"No tasks were defined in '{self._file}'.")
|
||||
return self
|
||||
|
||||
need_update = False
|
||||
need_save = False
|
||||
for i, task in enumerate(tasks):
|
||||
try:
|
||||
task, task_status = self.clean_task(task)
|
||||
task, task_status = clean_item(task, keys=("cookies", "config"))
|
||||
task = Task(**task)
|
||||
if task_status:
|
||||
need_update = True
|
||||
need_save = True
|
||||
except Exception as e:
|
||||
LOG.error(f"Failed to parse task at list position '{i}'. '{e!s}'.")
|
||||
continue
|
||||
|
|
@ -160,7 +161,7 @@ class Tasks(metaclass=Singleton):
|
|||
LOG.exception(e)
|
||||
LOG.error(f"Failed to queue task '{i}: {task.name}'. '{e!s}'.")
|
||||
|
||||
if need_update:
|
||||
if need_save:
|
||||
LOG.info("Updating tasks file to remove old keys.")
|
||||
self.save(self.get_all())
|
||||
|
||||
|
|
@ -223,6 +224,7 @@ class Tasks(metaclass=Singleton):
|
|||
if task.get("cli"):
|
||||
try:
|
||||
from .Utils import arg_converter
|
||||
|
||||
arg_converter(args=task.get("cli"))
|
||||
except Exception as e:
|
||||
msg = f"Invalid cli options. '{e!s}'."
|
||||
|
|
@ -266,27 +268,6 @@ class Tasks(metaclass=Singleton):
|
|||
|
||||
return self
|
||||
|
||||
def clean_task(self, task: dict) -> tuple[dict, bool]:
|
||||
"""
|
||||
Clean the task from old keys.
|
||||
|
||||
Args:
|
||||
task (dict): The task to clean.
|
||||
|
||||
Returns:
|
||||
tuple[dict, bool]: The cleaned task and a status if the task was cleaned.
|
||||
|
||||
"""
|
||||
status = False
|
||||
removedKeys = ["cookies", "config"]
|
||||
|
||||
for key in removedKeys:
|
||||
if key in task:
|
||||
status = True
|
||||
task.pop(key)
|
||||
|
||||
return task, status
|
||||
|
||||
async def _runner(self, task: Task):
|
||||
"""
|
||||
Run the task.
|
||||
|
|
|
|||
|
|
@ -522,8 +522,6 @@ def arg_converter(
|
|||
|
||||
bad_options.update(item.items())
|
||||
|
||||
LOG.debug("Removed %i the following options: '%s'.", level, ", ".join(bad_options.values()))
|
||||
|
||||
for key in diff.copy():
|
||||
if key not in bad_options:
|
||||
continue
|
||||
|
|
@ -889,3 +887,41 @@ def get_files(base_path: str, dir: str | None = None):
|
|||
)
|
||||
|
||||
return contents
|
||||
|
||||
|
||||
def clean_item(item: dict, keys: list | tuple) -> tuple[dict, bool]:
|
||||
"""
|
||||
Remove given keys from a dictionary.
|
||||
This function modifies the dictionary in place and returns a tuple
|
||||
containing the modified dictionary and a boolean indicating
|
||||
whether any keys were removed.
|
||||
|
||||
Args:
|
||||
item (dict): The item to clean.
|
||||
keys (list|tuple): The keys to remove.
|
||||
|
||||
Returns:
|
||||
tuple[dict, bool]: The cleaned item and a the status of cleaning operation.
|
||||
|
||||
Raises:
|
||||
TypeError: If item is not a dictionary or keys is not a list or tuple.
|
||||
|
||||
"""
|
||||
status = False
|
||||
|
||||
if not isinstance(item, dict):
|
||||
msg = "Item must be a dictionary."
|
||||
raise TypeError(msg)
|
||||
|
||||
if not isinstance(keys, list | tuple):
|
||||
msg = "Keys must be a list or tuple."
|
||||
raise TypeError(msg)
|
||||
|
||||
for key in keys:
|
||||
if key not in item:
|
||||
continue
|
||||
|
||||
status = True
|
||||
item.pop(key)
|
||||
|
||||
return item, status
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class YTDLPOpts(metaclass=Singleton):
|
|||
YTDLPOpts: The instance of the class
|
||||
|
||||
"""
|
||||
preset = Presets.get_instance().get(name=name)
|
||||
preset = Presets.get_instance().get(name)
|
||||
if not preset or "default" == name:
|
||||
return self
|
||||
|
||||
|
|
@ -118,25 +118,6 @@ class YTDLPOpts(metaclass=Singleton):
|
|||
"temp": self._config.temp_path,
|
||||
}
|
||||
|
||||
# @Deprecated - To be removed in future versions.
|
||||
if not preset.cli:
|
||||
if preset.postprocessors and isinstance(preset.postprocessors, list) and len(preset.postprocessors) > 0:
|
||||
self._preset_opts["postprocessors"] = preset.postprocessors
|
||||
|
||||
if preset.args and isinstance(preset.args, dict) and len(preset.args) > 0:
|
||||
bad_options = {k: v for d in REMOVE_KEYS for k, v in d.items()}
|
||||
removed_options = []
|
||||
for key, value in preset.args.items():
|
||||
if key in bad_options:
|
||||
removed_options.append(bad_options[key])
|
||||
continue
|
||||
self._preset_opts[key] = value
|
||||
|
||||
if len(removed_options) > 0:
|
||||
LOG.warning(
|
||||
"Removed the following options '%s' from '%s' args.", ", ".join(removed_options), preset.name
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
def get_all(self, keep: bool = False) -> dict:
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@
|
|||
|
||||
<div class="column is-12" v-if="showImport || !reference">
|
||||
<label class="label is-inline" for="import_string">
|
||||
<span class="icon"><i class="fa-solid fa-file-import" /></span>
|
||||
Import string
|
||||
</label>
|
||||
|
||||
<div class="field has-addons">
|
||||
<div class="control has-icons-left is-expanded">
|
||||
<div class="control is-expanded">
|
||||
<input type="text" class="input" id="import_string" v-model="import_string" autocomplete="off">
|
||||
<span class="icon is-small is-left"><i class="fa-solid fa-t" /></span>
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
|
|
@ -51,31 +51,35 @@
|
|||
|
||||
<div class="column is-6-tablet is-12-mobile">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="name" v-text="'Name'" />
|
||||
<div class="control has-icons-left">
|
||||
<label class="label is-inline" for="name">
|
||||
<span class="icon"><i class="fa-solid fa-tag" /></span>
|
||||
Name
|
||||
</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input" id="name" v-model="form.name" :disabled="addInProgress">
|
||||
<span class="icon is-small is-left"><i class="fa-solid fa-n" /></span>
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>The name to refers to this custom settings.</span>
|
||||
<span>The name to refers to this preset of settings.</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-6-tablet is-12-mobile">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="format" v-text="'Format'" />
|
||||
<div class="control has-icons-left">
|
||||
<label class="label is-inline" for="format">
|
||||
<span class="icon"><i class="fa-solid fa-f" /></span>
|
||||
Format
|
||||
</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input" id="format" v-model="form.format" :disabled="addInProgress">
|
||||
<span class="icon is-small is-left"><i class="fa-solid fa-f" /></span>
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>The yt-dlp <code>[--format, -f]</code> video format code. see <NuxtLink
|
||||
href="https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#format-selection" target="blank">this
|
||||
url</NuxtLink> for more info.</span>. Note, as this key is required, you can set the value to
|
||||
<code>default</code> to let <code>yt-dlp</code> choose the best format.
|
||||
page</NuxtLink> for more info. Note, as this key is required, you can set the value to
|
||||
<code>default</code> to let <code>yt-dlp</code> choose the best format.</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,12 +87,12 @@
|
|||
<div class="column is-6-tablet is-12-mobile">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="folder">
|
||||
<span class="icon"><i class="fa-solid fa-folder" /></span>
|
||||
Default Download path
|
||||
</label>
|
||||
<div class="control has-icons-left">
|
||||
<div class="control">
|
||||
<input type="text" class="input" id="folder" placeholder="Leave empty to use default download path"
|
||||
v-model="form.folder" :disabled="addInProgress" list="folders">
|
||||
<span class="icon is-small is-left"><i class="fa-solid fa-folder" /></span>
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
|
|
@ -101,19 +105,19 @@
|
|||
<div class="column is-6-tablet is-12-mobile">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="output_template">
|
||||
<span class="icon"><i class="fa-solid fa-file" /></span>
|
||||
Default Output template
|
||||
</label>
|
||||
<div class="control has-icons-left">
|
||||
<div class="control">
|
||||
<input type="text" class="input" id="output_template" :disabled="addInProgress"
|
||||
placeholder="Leave empty to use default template." v-model="form.template">
|
||||
<span class="icon is-small is-left"><i class="fa-solid fa-file" /></span>
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>Use this output template if non are given with URL. if not set, it will defaults to
|
||||
<code>{{ config.app.output_template }}</code>.
|
||||
For more information <NuxtLink href="https://github.com/yt-dlp/yt-dlp#output-template"
|
||||
target="_blank">visit this url</NuxtLink>.
|
||||
For more information visit <NuxtLink href="https://github.com/yt-dlp/yt-dlp#output-template"
|
||||
target="_blank">this page</NuxtLink>.
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -122,11 +126,12 @@
|
|||
<div class="column is-12">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="cli_options">
|
||||
<span class="icon"><i class="fa-solid fa-terminal" /></span>
|
||||
Command arguments for yt-dlp
|
||||
</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input" v-model="form.cli" id="cli_options" :disabled="addInProgress"
|
||||
placeholder="command options to use, e.g. --no-embed-metadata --no-embed-thumbnail">
|
||||
<textarea class="textarea is-pre" v-model="form.cli" id="cli_options" :disabled="addInProgress"
|
||||
placeholder="command options to use, e.g. --no-embed-metadata --no-embed-thumbnail" />
|
||||
</div>
|
||||
<span class="help">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
|
|
@ -141,8 +146,10 @@
|
|||
|
||||
<div class="column is-12">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="cookies"
|
||||
v-tooltip="'Netscape HTTP Cookie format.'">Cookies</label>
|
||||
<label class="label is-inline" for="cookies" v-tooltip="'Netscape HTTP Cookie format.'">
|
||||
<span class="icon"><i class="fa-solid fa-cookie" /></span>
|
||||
Cookies
|
||||
</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea is-pre" id="cookies" v-model="form.cookies" :disabled="addInProgress"
|
||||
placeholder="Leave empty to use default cookies" />
|
||||
|
|
@ -157,56 +164,7 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-12" v-if="has_data(form?.args) || has_data(form?.postprocessors)">
|
||||
<Message title="Deprecation Warning" class="is-background-warning-80 has-text-dark"
|
||||
icon="fas fa-exclamation-circle">
|
||||
<ul>
|
||||
<li>
|
||||
The <code>JSON yt-dlp config</code> and <code>JSON yt-dlp Post-Processors</code> fields are
|
||||
deprecated and will be removed in the future. Please use the <b>Command arguments for yt-dlp</b>
|
||||
field instead. The deprecated fields will still be working for now but they will stop, we suggest
|
||||
that you migrate to the new field. as soon as possible to avoid any issues. No support will be
|
||||
given for the deprecated fields.
|
||||
</li>
|
||||
<li>
|
||||
If both fields are set, the <b>Command arguments for yt-dlp</b> field will take precedence over
|
||||
the deprecated fields. and when you click save it will remove the deprecated fields.
|
||||
</li>
|
||||
</ul>
|
||||
</Message>
|
||||
</div>
|
||||
<div class="column is-6-tablet is-12-mobile" v-if="has_data(form?.args)">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="args" v-tooltip="'Extends current global yt-dlp config. (JSON)'">
|
||||
JSON yt-dlp config <span class="has-text-danger">(DEPRECATED)</span>
|
||||
</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" id="args" v-model="form.args" :disabled="addInProgress"
|
||||
placeholder="{}" />
|
||||
</div>
|
||||
<span class="help has-text-danger">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>Deprecated, use <b>Command arguments for yt-dlp</b> field instead. </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-6-tablet is-12-mobile" v-if="has_data(form?.postprocessors)">
|
||||
<div class="field">
|
||||
<label class="label is-inline" for="postprocessors"
|
||||
v-tooltip="'Things to do after download is done.'">
|
||||
JSON yt-dlp Post-Processors <span class="has-text-danger">(DEPRECATED)</span>
|
||||
</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" id="postprocessors" v-model="form.postprocessors"
|
||||
:disabled="addInProgress" placeholder="[]" />
|
||||
</div>
|
||||
<span class="help has-text-danger">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>Deprecated, use <b>Command arguments for yt-dlp</b> field instead. </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -319,55 +277,11 @@ const checkInfo = async () => {
|
|||
return;
|
||||
}
|
||||
|
||||
if (form?.cli && '' !== form.cli) {
|
||||
if ((has_data(copy?.args) || has_data(copy?.postprocessors))) {
|
||||
if (false === confirm('cli options are set, this will remove the JSON yt-dlp config and Post-Processors. Are you sure?')) {
|
||||
toast.warning('User cancelled the operation.')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (copy?.args) {
|
||||
delete copy.args
|
||||
}
|
||||
|
||||
if (copy?.postprocessors) {
|
||||
delete copy.postprocessors
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeof copy.args === 'object') {
|
||||
copy.args = JSON.stringify(copy.args, null, 2);
|
||||
}
|
||||
|
||||
if (typeof copy.postprocessors === 'object') {
|
||||
copy.postprocessors = JSON.stringify(copy.postprocessors, null, 2);
|
||||
}
|
||||
|
||||
if (copy?.args) {
|
||||
try {
|
||||
copy.args = JSON.parse(copy.args)
|
||||
} catch (e) {
|
||||
toast.error(`Invalid JSON yt-dlp config. ${e.message}`)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy?.postprocessors) {
|
||||
try {
|
||||
copy.postprocessors = JSON.parse(copy.postprocessors)
|
||||
} catch (e) {
|
||||
toast.error(`Invalid JSON yt-dlp Post-Processors. ${e.message}`)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trim all fields in copy only if they are strings
|
||||
for (const key in copy) {
|
||||
if (typeof copy[key] === 'string') {
|
||||
copy[key] = copy[key].trim()
|
||||
if (typeof copy[key] !== 'string') {
|
||||
continue
|
||||
}
|
||||
copy[key] = copy[key].trim()
|
||||
}
|
||||
|
||||
emitter('submit', { reference: toRaw(props.reference), preset: toRaw(copy) });
|
||||
|
|
@ -417,18 +331,13 @@ const importItem = async () => {
|
|||
try {
|
||||
const item = JSON.parse(val)
|
||||
|
||||
console.log(item)
|
||||
|
||||
if ('preset' !== item._type) {
|
||||
toast.error(`Invalid import string. Expected type 'preset', got '${item._type}'.`)
|
||||
import_string.value = ''
|
||||
if (item?._type || 'preset' !== item._type) {
|
||||
toast.error(`Invalid import string. Expected type 'preset', got '${item._type ?? 'unknown'}'.`)
|
||||
return
|
||||
}
|
||||
|
||||
if (form.format || form.cli) {
|
||||
if (false === confirm('This will overwrite the current form fields. Are you sure?')) {
|
||||
return
|
||||
}
|
||||
if ((form.format || form.cli) && false === confirm('This will overwrite the current data. Are you sure?')) {
|
||||
return
|
||||
}
|
||||
|
||||
if (item.name) {
|
||||
|
|
|
|||
|
|
@ -71,15 +71,6 @@ div.is-centered {
|
|||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<template v-if="has_data(item?.args) || has_data(item.postprocessors)">
|
||||
<p class="has-text-danger is-5 has-text-bold">
|
||||
<span class="icon"><i class="fa-solid fa-triangle-exclamation" /></span>
|
||||
<span>The preset is using deprecated options. It is recommended to update the preset to use the
|
||||
new options. It will cease to work in future versions.</span>
|
||||
</p>
|
||||
<hr>
|
||||
</template>
|
||||
|
||||
<p class="is-text-overflow"
|
||||
v-if="item?.format && false === ['default', 'not_set'].includes(item.format)">
|
||||
<span class="icon"><i class="fa-solid fa-f" /></span>
|
||||
|
|
@ -307,11 +298,6 @@ const exportItem = item => {
|
|||
}
|
||||
})
|
||||
|
||||
if (has_data(data?.args) || has_data(data?.postprocessors)) {
|
||||
toast.error("v1.0 presets are no longer supported target for export. Please update your preset.")
|
||||
return
|
||||
}
|
||||
|
||||
let userData = {}
|
||||
|
||||
for (const key of Object.keys(data)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue