diff options
author | Nikolay G <crushoverdrive@mail.ru> | 2023-02-17 20:51:50 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-17 20:51:50 +0300 |
commit | f30bd109f7573472c288280b28abb7dd9d30ac7f (patch) | |
tree | 247d01d84268d0211f426b0dba30c410e7247797 /app/ytdl.py | |
parent | Update README.md (diff) | |
parent | Merge pull request #219 from PikuZheng/patch-1 (diff) | |
download | metube-f30bd109f7573472c288280b28abb7dd9d30ac7f.tar.gz metube-f30bd109f7573472c288280b28abb7dd9d30ac7f.tar.bz2 metube-f30bd109f7573472c288280b28abb7dd9d30ac7f.zip |
Merge branch 'master' into master
Diffstat (limited to 'app/ytdl.py')
-rw-r--r-- | app/ytdl.py | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/app/ytdl.py b/app/ytdl.py index 21b82da..0a74b14 100644 --- a/app/ytdl.py +++ b/app/ytdl.py @@ -6,6 +6,7 @@ import time import asyncio
import multiprocessing
import logging
+import re
from dl_formats import get_format, get_opts
log = logging.getLogger('ytdl')
@@ -27,10 +28,11 @@ class DownloadQueueNotifier: raise NotImplementedError
class DownloadInfo:
- def __init__(self, id, title, url, quality, format):
+ def __init__(self, id, title, url, quality, format, folder):
self.id, self.title, self.url = id, title, url
self.quality = quality
self.format = format
+ self.folder = folder
self.status = self.msg = self.percent = self.speed = self.eta = None
self.filename = None
self.timestamp = time.time_ns()
@@ -126,6 +128,10 @@ class Download: self.tmpfilename = status.get('tmpfilename')
if 'filename' in status:
self.info.filename = os.path.relpath(status.get('filename'), self.download_dir)
+
+ # Set correct file extension for thumbnails
+ if(self.info.format == 'thumbnail'):
+ self.info.filename = re.sub(r'\.webm$', '.jpg', self.info.filename)
self.info.status = status['status']
self.info.msg = status.get('msg')
if 'downloaded_bytes' in status:
@@ -164,7 +170,7 @@ class PersistentQueue: return sorted(shelf.items(), key=lambda item: item[1].timestamp)
def put(self, value):
- key = value.info.id
+ key = value.info.url
self.dict[key] = value
with shelve.open(self.path, 'w') as shelf:
shelf[key] = value.info
@@ -192,7 +198,7 @@ class DownloadQueue: async def __import_queue(self):
for k, v in self.queue.saved_items():
- await self.add(v.url, v.quality, v.format)
+ await self.add(v.url, v.quality, v.format, folder=v.folder)
async def initialize(self):
self.event = asyncio.Event()
@@ -207,7 +213,7 @@ class DownloadQueue: **self.config.YTDL_OPTIONS,
}).extract_info(url, download=False)
- async def __add_entry(self, entry, quality, format, already):
+ async def __add_entry(self, entry, quality, format, folder, already):
etype = entry.get('_type') or 'video'
if etype == 'playlist':
entries = entry['entries']
@@ -220,14 +226,28 @@ class DownloadQueue: for property in ("id", "title", "uploader", "uploader_id"):
if property in entry:
etr[f"playlist_{property}"] = entry[property]
- results.append(await self.__add_entry(etr, quality, format, already))
+ results.append(await self.__add_entry(etr, quality, format, folder, already))
if any(res['status'] == 'error' for res in results):
return {'status': 'error', 'msg': ', '.join(res['msg'] for res in results if res['status'] == 'error' and 'msg' in res)}
return {'status': 'ok'}
elif etype == 'video' or etype.startswith('url') and 'id' in entry and 'title' in entry:
if not self.queue.exists(entry['id']):
- dl = DownloadInfo(entry['id'], entry['title'], entry.get('webpage_url') or entry['url'], quality, format)
- dldirectory = self.config.DOWNLOAD_DIR if (quality != 'audio' and format != 'mp3') else self.config.AUDIO_DOWNLOAD_DIR
+ dl = DownloadInfo(entry['id'], entry['title'], entry.get('webpage_url') or entry['url'], quality, format, folder)
+ # Keep consistent with frontend
+ base_directory = self.config.DOWNLOAD_DIR if (quality != 'audio' and format != 'mp3') else self.config.AUDIO_DOWNLOAD_DIR
+ if folder:
+ if not self.config.CUSTOM_DIRS:
+ return {'status': 'error', 'msg': f'A folder for the download was specified but CUSTOM_DIRS is not true in the configuration.'}
+ dldirectory = os.path.realpath(os.path.join(base_directory, folder))
+ real_base_directory = os.path.realpath(base_directory)
+ if not dldirectory.startswith(real_base_directory):
+ return {'status': 'error', 'msg': f'Folder "{folder}" must resolve inside the base download directory "{real_base_directory}"'}
+ if not os.path.isdir(dldirectory):
+ if not self.config.CREATE_CUSTOM_DIRS:
+ return {'status': 'error', 'msg': f'Folder "{folder}" for download does not exist inside base directory "{real_base_directory}", and CREATE_CUSTOM_DIRS is not true in the configuration.'}
+ os.makedirs(dldirectory, exist_ok=True)
+ else:
+ dldirectory = base_directory
output = self.config.OUTPUT_TEMPLATE
output_chapter = self.config.OUTPUT_TEMPLATE_CHAPTER
for property, value in entry.items():
@@ -238,11 +258,11 @@ class DownloadQueue: await self.notifier.added(dl)
return {'status': 'ok'}
elif etype.startswith('url'):
- return await self.add(entry['url'], quality, format, already)
+ return await self.add(entry['url'], quality, format, folder, already)
return {'status': 'error', 'msg': f'Unsupported resource "{etype}"'}
- async def add(self, url, quality, format, already=None):
- log.info(f'adding {url}')
+ async def add(self, url, quality, format, folder, already=None):
+ log.info(f'adding {url}: {quality=} {format=} {already=} {folder=}')
already = set() if already is None else already
if url in already:
log.info('recursion detected, skipping')
@@ -253,7 +273,7 @@ class DownloadQueue: entry = await asyncio.get_running_loop().run_in_executor(None, self.__extract_info, url)
except yt_dlp.utils.YoutubeDLError as exc:
return {'status': 'error', 'msg': str(exc)}
- return await self.__add_entry(entry, quality, format, already)
+ return await self.__add_entry(entry, quality, format, folder, already)
async def cancel(self, ids):
for id in ids:
|