2021-07-10 20:47:33 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2022-03-10 23:32:16 +01:00
|
|
|
# Copyright 2021-2022 Mike Fährmann
|
2021-07-10 20:47:33 +02:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
|
|
# published by the Free Software Foundation.
|
|
|
|
|
|
|
|
"""Extractors for sites supported by youtube-dl"""
|
|
|
|
|
|
|
|
from .common import Extractor, Message
|
2021-11-07 02:44:11 +01:00
|
|
|
from .. import ytdl, config, exception
|
2021-07-10 20:47:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
class YoutubeDLExtractor(Extractor):
|
|
|
|
"""Generic extractor for youtube-dl supported URLs"""
|
|
|
|
category = "ytdl"
|
|
|
|
directory_fmt = ("{category}", "{subcategory}")
|
|
|
|
filename_fmt = "{title}-{id}.{extension}"
|
|
|
|
archive_fmt = "{extractor_key} {id}"
|
|
|
|
pattern = r"ytdl:(.*)"
|
|
|
|
test = ("ytdl:https://www.youtube.com/watch?v=BaW_jenozKc&t=1s&end=9",)
|
|
|
|
|
|
|
|
def __init__(self, match):
|
2021-07-12 18:47:12 +02:00
|
|
|
# import main youtube_dl module
|
2021-11-29 04:36:43 +01:00
|
|
|
ytdl_module = ytdl.import_module(config.get(
|
|
|
|
("extractor", "ytdl"), "module"))
|
|
|
|
self.ytdl_module_name = ytdl_module.__name__
|
2021-07-10 20:47:33 +02:00
|
|
|
|
|
|
|
# find suitable youtube_dl extractor
|
|
|
|
self.ytdl_url = url = match.group(1)
|
2021-07-11 23:01:57 +02:00
|
|
|
generic = config.interpolate(("extractor", "ytdl"), "generic", True)
|
|
|
|
if generic == "force":
|
2021-07-13 16:59:55 +02:00
|
|
|
self.ytdl_ie_key = "Generic"
|
2021-07-11 23:01:57 +02:00
|
|
|
self.force_generic_extractor = True
|
|
|
|
else:
|
2021-11-29 04:36:43 +01:00
|
|
|
for ie in ytdl_module.extractor.gen_extractor_classes():
|
2021-07-11 23:01:57 +02:00
|
|
|
if ie.suitable(url):
|
2021-07-13 16:59:55 +02:00
|
|
|
self.ytdl_ie_key = ie.ie_key()
|
2021-07-11 23:01:57 +02:00
|
|
|
break
|
2021-07-13 16:59:55 +02:00
|
|
|
if not generic and self.ytdl_ie_key == "Generic":
|
2021-07-11 23:01:57 +02:00
|
|
|
raise exception.NoExtractorError()
|
|
|
|
self.force_generic_extractor = False
|
2021-07-10 20:47:33 +02:00
|
|
|
|
|
|
|
# set subcategory to youtube_dl extractor's key
|
2021-07-13 16:59:55 +02:00
|
|
|
self.subcategory = self.ytdl_ie_key
|
2021-07-10 20:47:33 +02:00
|
|
|
Extractor.__init__(self, match)
|
|
|
|
|
|
|
|
def items(self):
|
2021-07-13 16:59:55 +02:00
|
|
|
# import subcategory module
|
2021-11-29 04:36:43 +01:00
|
|
|
ytdl_module = ytdl.import_module(
|
2021-07-13 16:59:55 +02:00
|
|
|
config.get(("extractor", "ytdl", self.subcategory), "module") or
|
|
|
|
self.ytdl_module_name)
|
2021-07-12 18:47:12 +02:00
|
|
|
self.log.debug("Using %s", ytdl_module)
|
|
|
|
|
2021-07-10 20:47:33 +02:00
|
|
|
# construct YoutubeDL object
|
2021-11-07 02:44:11 +01:00
|
|
|
extr_opts = {
|
|
|
|
"extract_flat" : "in_playlist",
|
|
|
|
"force_generic_extractor": self.force_generic_extractor,
|
|
|
|
}
|
|
|
|
user_opts = {
|
2021-07-16 03:42:13 +02:00
|
|
|
"retries" : self._retries,
|
|
|
|
"socket_timeout" : self._timeout,
|
|
|
|
"nocheckcertificate" : not self._verify,
|
2021-07-10 20:47:33 +02:00
|
|
|
}
|
|
|
|
|
2022-03-10 23:32:16 +01:00
|
|
|
if self._proxies:
|
|
|
|
user_opts["proxy"] = self._proxies.get("http")
|
|
|
|
|
2021-07-11 01:12:55 +02:00
|
|
|
username, password = self._get_auth_info()
|
|
|
|
if username:
|
2021-11-07 02:44:11 +01:00
|
|
|
user_opts["username"], user_opts["password"] = username, password
|
2021-07-11 01:12:55 +02:00
|
|
|
del username, password
|
|
|
|
|
2021-11-07 02:44:11 +01:00
|
|
|
ytdl_instance = ytdl.construct_YoutubeDL(
|
|
|
|
ytdl_module, self, user_opts, extr_opts)
|
2021-07-12 18:50:25 +02:00
|
|
|
|
|
|
|
# transfer cookies to ytdl
|
|
|
|
cookies = self.session.cookies
|
|
|
|
if cookies:
|
2021-11-07 02:44:11 +01:00
|
|
|
set_cookie = ytdl_instance.cookiejar.set_cookie
|
|
|
|
for cookie in cookies:
|
2021-07-12 18:50:25 +02:00
|
|
|
set_cookie(cookie)
|
2021-07-10 20:47:33 +02:00
|
|
|
|
|
|
|
# extract youtube_dl info_dict
|
2021-11-15 22:56:42 +01:00
|
|
|
try:
|
|
|
|
info_dict = ytdl_instance._YoutubeDL__extract_info(
|
|
|
|
self.ytdl_url,
|
|
|
|
ytdl_instance.get_info_extractor(self.ytdl_ie_key),
|
|
|
|
False, {}, True)
|
|
|
|
except ytdl_module.utils.YoutubeDLError:
|
|
|
|
raise exception.StopExtraction("Failed to extract video data")
|
|
|
|
|
|
|
|
if not info_dict:
|
|
|
|
return
|
|
|
|
elif "entries" in info_dict:
|
2021-11-07 02:44:11 +01:00
|
|
|
results = self._process_entries(
|
2021-11-15 22:56:42 +01:00
|
|
|
ytdl_module, ytdl_instance, info_dict["entries"])
|
2021-07-10 20:47:33 +02:00
|
|
|
else:
|
|
|
|
results = (info_dict,)
|
|
|
|
|
|
|
|
# yield results
|
|
|
|
for info_dict in results:
|
|
|
|
info_dict["extension"] = None
|
|
|
|
info_dict["_ytdl_info_dict"] = info_dict
|
2021-11-07 02:44:11 +01:00
|
|
|
info_dict["_ytdl_instance"] = ytdl_instance
|
2021-07-10 20:47:33 +02:00
|
|
|
|
|
|
|
url = "ytdl:" + (info_dict.get("url") or
|
|
|
|
info_dict.get("webpage_url") or
|
|
|
|
self.ytdl_url)
|
|
|
|
|
|
|
|
yield Message.Directory, info_dict
|
|
|
|
yield Message.Url, url, info_dict
|
|
|
|
|
2021-11-15 22:56:42 +01:00
|
|
|
def _process_entries(self, ytdl_module, ytdl_instance, entries):
|
2021-07-10 20:47:33 +02:00
|
|
|
for entry in entries:
|
2021-11-15 22:56:42 +01:00
|
|
|
if not entry:
|
|
|
|
continue
|
|
|
|
elif entry.get("_type") in ("url", "url_transparent"):
|
|
|
|
try:
|
|
|
|
info_dict = ytdl_instance.extract_info(
|
|
|
|
entry["url"], False,
|
|
|
|
ie_key=entry.get("ie_key"))
|
|
|
|
except ytdl_module.utils.YoutubeDLError:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if not info_dict:
|
|
|
|
continue
|
|
|
|
elif "entries" in info_dict:
|
2021-07-10 20:47:33 +02:00
|
|
|
yield from self._process_entries(
|
2021-11-15 22:56:42 +01:00
|
|
|
ytdl_module, ytdl_instance, info_dict["entries"])
|
2021-07-10 20:47:33 +02:00
|
|
|
else:
|
|
|
|
yield info_dict
|
|
|
|
else:
|
|
|
|
yield entry
|
|
|
|
|
|
|
|
|
|
|
|
if config.get(("extractor", "ytdl"), "enabled"):
|
|
|
|
# make 'ytdl:' prefix optional
|
|
|
|
YoutubeDLExtractor.pattern = r"(?:ytdl:)?(.*)"
|