Add test button for conditions
This commit is contained in:
parent
bdf50d0ed8
commit
55b2e3e7f2
4 changed files with 141 additions and 7 deletions
|
|
@ -871,6 +871,74 @@ class HttpAPI(Common):
|
|||
await self._notify.emit(Events.CONDITIONS_UPDATE, data=items)
|
||||
return web.json_response(data=items, status=web.HTTPOk.status_code, dumps=self.encoder.encode)
|
||||
|
||||
@route("POST", "api/conditions/test")
|
||||
async def conditions_test(self, request: Request) -> Response:
|
||||
"""
|
||||
Test condition against URL.
|
||||
|
||||
Args:
|
||||
request (Request): The request object.
|
||||
|
||||
Returns:
|
||||
Response: The response object
|
||||
|
||||
"""
|
||||
data = await request.json()
|
||||
|
||||
if not isinstance(data, dict):
|
||||
return web.json_response(
|
||||
{"error": "Invalid request body expecting dict."},
|
||||
status=web.HTTPBadRequest.status_code,
|
||||
)
|
||||
|
||||
url = data.get("url")
|
||||
if not url:
|
||||
return web.json_response({"error": "url is required."}, status=web.HTTPBadRequest.status_code)
|
||||
|
||||
cond = data.get("condition")
|
||||
if not cond:
|
||||
return web.json_response({"error": "condition name is required."}, status=web.HTTPBadRequest.status_code)
|
||||
|
||||
try:
|
||||
opts = {}
|
||||
|
||||
if ytdlp_proxy := self.config.get_ytdlp_args().get("proxy", None):
|
||||
opts["proxy"] = ytdlp_proxy
|
||||
|
||||
preset = data.get("preset", self.config.default_preset)
|
||||
ytdlp_opts = YTDLPOpts.get_instance().preset(name=preset, with_cookies=True).add(opts).get_all()
|
||||
key = self.cache.hash(url + str(preset))
|
||||
if not self.cache.has(key):
|
||||
data = extract_info(
|
||||
config=ytdlp_opts,
|
||||
url=url,
|
||||
debug=False,
|
||||
no_archive=True,
|
||||
follow_redirect=True,
|
||||
sanitize_info=True,
|
||||
)
|
||||
self.cache.set(key=key, value=data, ttl=600)
|
||||
else:
|
||||
data = self.cache.get(key)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
return web.json_response(
|
||||
data={"error": f"Failed to extract video info. '{e!s}'"},
|
||||
status=web.HTTPInternalServerError.status_code,
|
||||
)
|
||||
|
||||
matched = Conditions.get_instance().single_match(name=cond, info=data)
|
||||
if matched is None:
|
||||
return web.json_response(
|
||||
data={"error": f"Condition '{cond}' doesn't match the data from the URL."},
|
||||
status=web.HTTPNotFound.status_code,
|
||||
)
|
||||
|
||||
return web.json_response(
|
||||
data={"message": f"Condition '{cond}' matched the data from the URL."},
|
||||
status=web.HTTPOk.status_code,
|
||||
)
|
||||
|
||||
@route("GET", "api/presets")
|
||||
async def presets(self, request: Request) -> Response:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -317,3 +317,26 @@ class Conditions(metaclass=Singleton):
|
|||
continue
|
||||
|
||||
return None
|
||||
|
||||
def single_match(self, name: str, info: dict) -> Condition | None:
|
||||
"""
|
||||
Check if condition matches the info dict.
|
||||
|
||||
Args:
|
||||
name (str): The condition name to check.
|
||||
info (dict): The info dict to check.
|
||||
|
||||
Returns:
|
||||
Condition|None: The condition if found, None otherwise.
|
||||
|
||||
"""
|
||||
if len(self._items) < 1 or not info or not isinstance(info, dict) or len(info) < 1:
|
||||
return None
|
||||
|
||||
item = self.get(name)
|
||||
if not item or not item.filter:
|
||||
return None
|
||||
|
||||
from yt_dlp.utils import match_str
|
||||
|
||||
return item if match_str(item.filter, info) else None
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ function alert(msg: string): boolean {
|
|||
return window.confirm(msg)
|
||||
}
|
||||
|
||||
export default function useConfirm() {
|
||||
return { confirm, alert, reduceConfirm }
|
||||
function prompt(msg: string, defaultValue: string = ''): string | null {
|
||||
return window.prompt(msg, defaultValue)
|
||||
}
|
||||
|
||||
export default function useConfirm() {
|
||||
return { confirm, alert, prompt, reduceConfirm }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
</div>
|
||||
<div class="card-content" v-if="cond?.raw">
|
||||
<div class="content">
|
||||
<pre><code>{{ filterItem(cond) }}</code></pre>
|
||||
<pre><code>{{ JSON.stringify(cleanObject(cond, remove_keys), null, 2) }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer mt-auto">
|
||||
|
|
@ -82,6 +82,13 @@
|
|||
<span>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-footer-item">
|
||||
<button class="button is-purple is-fullwidth" @click="TestCondition(cond)"
|
||||
:class="{ 'is-loading': cond?.in_progress }">
|
||||
<span class="icon"><i class="fa-solid fa-play" /></span>
|
||||
<span>Test</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -104,6 +111,10 @@
|
|||
filter i am able to bypass it <code>availability = 'needs_auth' & channel_id = 'channel_id'</code>.
|
||||
and set proxy for that specific video, while leaving the rest of the videos to be downloaded normally.
|
||||
</li>
|
||||
<li>
|
||||
The data which the filter is applied on is the same data that yt-dlp returns, simply, click on the
|
||||
information button, and check the data to craft your filter.
|
||||
</li>
|
||||
</ul>
|
||||
</Message>
|
||||
</div>
|
||||
|
|
@ -125,6 +136,7 @@ const toggleForm = ref(false)
|
|||
const isLoading = ref(false)
|
||||
const initialLoad = ref(true)
|
||||
const addInProgress = ref(false)
|
||||
const remove_keys = ['in_progress', 'raw']
|
||||
|
||||
watch(() => config.app.basic_mode, async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
|
|
@ -236,6 +248,7 @@ const deleteItem = async (item) => {
|
|||
}
|
||||
|
||||
const updateItem = async ({ reference, item }) => {
|
||||
item = cleanObject(item, remove_keys)
|
||||
if (reference) {
|
||||
const index = items.value.findIndex(t => t?.id === reference)
|
||||
if (index > -1) {
|
||||
|
|
@ -254,10 +267,7 @@ const updateItem = async ({ reference, item }) => {
|
|||
resetForm(true)
|
||||
}
|
||||
|
||||
const filterItem = item => {
|
||||
const { raw, ...rest } = item
|
||||
return JSON.stringify(rest, null, 2)
|
||||
}
|
||||
const filterItem = i => JSON.stringify(cleanObject(i, remove_keys), null, 2)
|
||||
|
||||
const editItem = _item => {
|
||||
item.value = _item
|
||||
|
|
@ -287,4 +297,33 @@ const exportItem = item => {
|
|||
|
||||
return copyText(base64UrlEncode(JSON.stringify(userData)))
|
||||
}
|
||||
|
||||
const TestCondition = async (item) => {
|
||||
const url = box.prompt("Enter URL to test condition against:")
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
|
||||
item.in_progress = true
|
||||
|
||||
try {
|
||||
const response = await request("/api/conditions/test", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ url: url, condition: item.id || item.name }),
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
toast.error(`Failed to test condition. ${data.error}`)
|
||||
return
|
||||
}
|
||||
|
||||
toast.success(data?.message || "Condition tested successfully.")
|
||||
} catch (e) {
|
||||
toast.error(`Failed to test condition. ${e.message}`)
|
||||
} finally {
|
||||
item.in_progress = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue