we no longer use json cookies, instead rely on netescape cookies and recommend what yt-dlp recommend as well.

This commit is contained in:
ArabCoders 2025-02-27 00:39:18 +03:00
parent 1934815a41
commit 96260301be
6 changed files with 56 additions and 42 deletions

View file

@ -1,6 +1,5 @@
import asyncio import asyncio
import hashlib import hashlib
import json
import logging import logging
import multiprocessing import multiprocessing
import os import os
@ -15,7 +14,7 @@ from .config import Config
from .Emitter import Emitter from .Emitter import Emitter
from .ffprobe import ffprobe from .ffprobe import ffprobe
from .ItemDTO import ItemDTO from .ItemDTO import ItemDTO
from .Utils import get_opts, json_cookie, merge_config from .Utils import get_opts, merge_config
LOG = logging.getLogger("download") LOG = logging.getLogger("download")
@ -138,17 +137,11 @@ class Download:
if self.info.cookies: if self.info.cookies:
try: try:
data = json_cookie(json.loads(self.info.cookies))
if not data:
LOG.warning(
f"The cookie string that was provided for {self.info.title} is empty or not in expected spec."
)
with open(os.path.join(self.temp_path, f"cookie_{self.info._id}.txt"), "w") as f: with open(os.path.join(self.temp_path, f"cookie_{self.info._id}.txt"), "w") as f:
f.write(data) f.write(self.info.cookies)
params["cookiefile"] = f.name
params["cookiefile"] = f.name
except ValueError as e: except ValueError as e:
LOG.error(f"Invalid cookies: was provided for '{self.info.title}'. '{e!s}'.") LOG.error(f"Failed to create cookie file for '{self.info.id}: {self.info.title}'. '{e!s}'.")
if self.is_live or self.is_manifestless: if self.is_live or self.is_manifestless:
hasDeletedOptions = False hasDeletedOptions = False

View file

@ -3,10 +3,12 @@ import json
import logging import logging
import os import os
import time import time
import uuid
from datetime import UTC, datetime from datetime import UTC, datetime
from email.utils import formatdate from email.utils import formatdate
from sqlite3 import Connection from sqlite3 import Connection
import anyio
import yt_dlp import yt_dlp
from aiohttp import web from aiohttp import web
@ -354,9 +356,11 @@ class DownloadQueue(metaclass=Singleton):
folder = str(folder) if folder else "" folder = str(folder) if folder else ""
filePath = calc_download_path(base_path=self.config.download_path, folder=folder) filePath = calc_download_path(base_path=self.config.download_path, folder=folder)
yt_conf = {}
cookie_file = os.path.join(self.config.temp_path, f"c_{uuid.uuid4().hex}.txt")
LOG.info( LOG.info(
f"Adding 'URL: {url}' to 'Folder: {filePath}' with 'Preset: {preset}' 'Naming: {template}', 'Cookies: {cookies}' 'YTConfig: {config}'." f"Adding 'URL: {url}' to 'Folder: {filePath}' with 'Preset: {preset}' 'Naming: {template}', 'Cookies: {len(cookies)}/chars' 'YTConfig: {config}'."
) )
if isinstance(config, str): if isinstance(config, str):
@ -384,19 +388,33 @@ class DownloadQueue(metaclass=Singleton):
started = time.perf_counter() started = time.perf_counter()
LOG.debug(f"extract_info: checking {url=}") LOG.debug(f"extract_info: checking {url=}")
logs = []
yt_conf = {
"callback": {
"func": lambda _, msg: logs.append(msg),
"level": logging.WARNING,
},
**merge_config(self.config.ytdl_options, config),
}
if cookies:
try:
async with await anyio.open_file(cookie_file, "w") as f:
await f.write(cookies)
yt_conf["cookiefile"] = f.name
except ValueError as e:
LOG.error(f"Failed to create cookie file for '{self.info.id}: {self.info.title}'. '{e!s}'.")
entry = await asyncio.wait_for( entry = await asyncio.wait_for(
fut=asyncio.get_running_loop().run_in_executor( fut=asyncio.get_running_loop().run_in_executor(
None, None, extract_info, get_opts(preset, yt_conf), url, bool(self.config.ytdl_debug)
extract_info,
get_opts(preset, merge_config(self.config.ytdl_options, config)),
url,
bool(self.config.ytdl_debug),
), ),
timeout=self.config.extract_info_timeout, timeout=self.config.extract_info_timeout,
) )
if not entry: if not entry:
return {"status": "error", "msg": "Unable to extract info check logs."} return {"status": "error", "msg": "Unable to extract info." + "\n".join(logs)}
LOG.debug( LOG.debug(
f"extract_info: for 'URL: {url}' is done in '{time.perf_counter() - started}'. Length: '{len(entry)}'." f"extract_info: for 'URL: {url}' is done in '{time.perf_counter() - started}'. Length: '{len(entry)}'."
@ -413,6 +431,13 @@ class DownloadQueue(metaclass=Singleton):
"status": "error", "status": "error",
"msg": f"TimeoutError: {self.config.extract_info_timeout}s reached Unable to extract info.", "msg": f"TimeoutError: {self.config.extract_info_timeout}s reached Unable to extract info.",
} }
finally:
if cookie_file and os.path.exists(cookie_file):
try:
os.remove(yt_conf["cookiefile"])
del yt_conf["cookiefile"]
except Exception as e:
LOG.error(f"Failed to remove cookie file '{yt_conf['cookiefile']}'. {e!s}")
return await self.__add_entry( return await self.__add_entry(
entry=entry, entry=entry,

View file

@ -17,7 +17,7 @@ from .encoder import Encoder
from .EventsSubscriber import Event, Events, EventsSubscriber from .EventsSubscriber import Event, Events, EventsSubscriber
from .Singleton import Singleton from .Singleton import Singleton
LOG = logging.getLogger("notifications") LOG = logging.getLogger("tasks")
@dataclass(kw_only=True) @dataclass(kw_only=True)

View file

@ -100,7 +100,7 @@
</div> </div>
<div class="column is-6-tablet is-12-mobile"> <div class="column is-6-tablet is-12-mobile">
<div class="field"> <div class="field">
<label class="label is-inline" for="ytdlpCookies" v-tooltip="'JSON exported cookies for downloading.'"> <label class="label is-inline" for="ytdlpCookies" v-tooltip="'Netscape HTTP Cookie format'">
Cookies Cookies
</label> </label>
<div class="control"> <div class="control">
@ -109,8 +109,10 @@
</div> </div>
<span class="help"> <span class="help">
<span class="icon"><i class="fa-solid fa-info" /></span> <span class="icon"><i class="fa-solid fa-info" /></span>
<span>Use <NuxtLink target="_blank" to="https://github.com/jrie/flagCookies"> <span>Use the <NuxtLink target="_blank"
flagCookies</NuxtLink> to extract cookies as JSON string.</span> to="https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp">
Recommended addon</NuxtLink> by yt-dlp to export cookies. The cookies MUST be in Netscape HTTP
Cookie format.</span>
</span> </span>
</div> </div>
</div> </div>

View file

@ -127,7 +127,8 @@
<div class="column is-6-tablet is-12-mobile"> <div class="column is-6-tablet is-12-mobile">
<div class="field"> <div class="field">
<label class="label is-inline" for="config" v-tooltip="'Extends current global yt-dlp config. (JSON)'"> <label class="label is-inline" for="config" v-tooltip="'Extends current global yt-dlp config. (JSON)'">
JSON yt-dlp config or CLI options. <NuxtLink v-if="form.config && !form.config.trim().startsWith('{')" JSON yt-dlp config or CLI options. <NuxtLink
v-if="form.config && (typeof form.config === 'string') && !form.config.trim().startsWith('{')"
@click="convertOptions()">Convert to JSON</NuxtLink> @click="convertOptions()">Convert to JSON</NuxtLink>
</label> </label>
<div class="control"> <div class="control">
@ -145,17 +146,16 @@
<div class="column is-6-tablet is-12-mobile"> <div class="column is-6-tablet is-12-mobile">
<div class="field"> <div class="field">
<label class="label is-inline" for="cookies" v-tooltip="'JSON exported cookies for downloading.'"> <label class="label is-inline" for="cookies" v-tooltip="'Netscape HTTP Cookie format.'">Cookies</label>
JSON Cookies
</label>
<div class="control"> <div class="control">
<textarea class="textarea" id="cookies" v-model="form.cookies" :disabled="addInProgress"></textarea> <textarea class="textarea" id="cookies" v-model="form.cookies" :disabled="addInProgress"></textarea>
</div> </div>
<span class="help"> <span class="help">
<span class="icon"><i class="fa-solid fa-info" /></span> <span class="icon"><i class="fa-solid fa-info" /></span>
<span>Use <NuxtLink target="_blank" to="https://github.com/jrie/flagCookies">flagCookies</NuxtLink> to <span>Use the <NuxtLink target="_blank"
extract cookies as JSON string. to="https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp">
</span> Recommended addon</NuxtLink> by yt-dlp to export cookies. The cookies MUST be in Netscape HTTP
Cookie format.</span>
</span> </span>
</div> </div>
</div> </div>
@ -217,7 +217,6 @@ const props = defineProps({
const form = reactive(props.task); const form = reactive(props.task);
onMounted(() => { onMounted(() => {
if (props.task?.config && (typeof props.task.config === 'object')) { if (props.task?.config && (typeof props.task.config === 'object')) {
form.config = JSON.stringify(props.task.config, null, 4); form.config = JSON.stringify(props.task.config, null, 4);
} }
@ -252,7 +251,11 @@ const checkInfo = async () => {
return; return;
} }
if (form.config && !form.config.trim().startsWith('{')) { if (typeof form.config === 'object') {
form.config = JSON.stringify(form.config, null, 4);
}
if (form.config && form.config && !form.config.trim().startsWith('{')) {
await convertOptions(); await convertOptions();
} }
@ -265,15 +268,6 @@ const checkInfo = async () => {
} }
} }
if (form.cookies) {
try {
JSON.parse(form.cookies);
} catch (e) {
toast.error(`Invalid JSON yt-dlp cookies. ${e.message}`)
return;
}
}
emitter('submit', { reference: toRaw(props.reference), task: toRaw(form) }); emitter('submit', { reference: toRaw(props.reference), task: toRaw(form) });
} }

View file

@ -269,10 +269,10 @@ const editItem = item => {
} }
const calcPath = path => { const calcPath = path => {
let loc = config.app.download_path const loc = config.app.download_path || '/downloads'
if (path) { if (path) {
let loc = loc + '/' + sTrim(path, '/') return loc + '/' + sTrim(path, '/')
} }
return loc return loc