aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--README.md5
-rw-r--r--make_win.bat2
-rw-r--r--youtube_dlc/YoutubeDL.py11
-rw-r--r--youtube_dlc/extractor/__init__.py6
-rw-r--r--youtube_dlc/options.py9
-rw-r--r--youtube_dlc/utils.py29
-rw-r--r--ytdlp_plugins/extractor/__init__.py2
-rw-r--r--ytdlp_plugins/extractor/sample.py12
9 files changed, 72 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore
index 9ee6e91cf..189ada254 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,6 +65,14 @@ venv/
# VS Code related files
.vscode
+# SublimeText files
+*.sublime-workspace
+
+# Cookies
+cookies
cookies.txt
-*.sublime-workspace \ No newline at end of file
+# Plugins
+ytdlp_plugins/extractor/*
+!ytdlp_plugins/extractor/__init__.py
+!ytdlp_plugins/extractor/sample.py \ No newline at end of file
diff --git a/README.md b/README.md
index a2ddc3db5..59999245b 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,7 @@ This is a fork of [youtube-dlc](https://github.com/blackjack4494/yt-dlc) which i
* [Filtering Formats](#filtering-formats)
* [Sorting Formats](#sorting-formats)
* [Format Selection examples](#format-selection-examples)
+* [PLUGINS](#plugins)
* [MORE](#more)
@@ -1082,9 +1083,11 @@ $ youtube-dlc -S 'res:720,fps'
$ youtube-dlc -S '+res:480,codec,br'
```
+# PLUGINS
+Plugins are loaded from `<root-dir>/ytdlp_plugins/<type>/__init__.py`. Currently only `extractor` plugins are supported. Support for `downloader` and `postprocessor` plugins may be added in the future. See [ytdlp_plugins](ytdlp_plugins) for example.
-
+**Note**: `<root-dir>` is the directory of the binary (`<root-dir>/youtube-dlc`), or the root directory of the module if you are running directly from source-code ((`<root dir>/youtube_dlc/__main__.py`)
# MORE
For FAQ, Developer Instructions etc., see the [original README](https://github.com/ytdl-org/youtube-dl)
diff --git a/make_win.bat b/make_win.bat
index c35d9937e..a3d98155b 100644
--- a/make_win.bat
+++ b/make_win.bat
@@ -1 +1 @@
-py -m PyInstaller youtube_dlc\__main__.py --onefile --name youtube-dlc --version-file win\ver.txt --icon win\icon\cloud.ico --upx-exclude=vcruntime140.dll \ No newline at end of file
+py -m PyInstaller youtube_dlc\__main__.py --onefile --name youtube-dlc --version-file win\ver.txt --icon win\icon\cloud.ico --upx-exclude=vcruntime140.dll --exclude-module ytdlp_plugins \ No newline at end of file
diff --git a/youtube_dlc/YoutubeDL.py b/youtube_dlc/YoutubeDL.py
index b45b1bbba..02cc97625 100644
--- a/youtube_dlc/YoutubeDL.py
+++ b/youtube_dlc/YoutubeDL.py
@@ -105,7 +105,7 @@ from .utils import (
process_communicate_or_kill,
)
from .cache import Cache
-from .extractor import get_info_extractor, gen_extractor_classes, _LAZY_LOADER
+from .extractor import get_info_extractor, gen_extractor_classes, _LAZY_LOADER, _PLUGIN_CLASSES
from .extractor.openload import PhantomJSwrapper
from .downloader import get_suitable_downloader
from .downloader.rtmp import rtmpdump_version
@@ -2652,9 +2652,12 @@ class YoutubeDL(object):
self.get_encoding()))
write_string(encoding_str, encoding=None)
- self._write_string('[debug] yt-dlp version ' + __version__ + '\n')
+ self._write_string('[debug] yt-dlp version %s\n' % __version__)
if _LAZY_LOADER:
- self._write_string('[debug] Lazy loading extractors enabled' + '\n')
+ self._write_string('[debug] Lazy loading extractors enabled\n')
+ if _PLUGIN_CLASSES:
+ self._write_string(
+ '[debug] Plugin Extractors: %s\n' % [ie.ie_key() for ie in _PLUGIN_CLASSES])
try:
sp = subprocess.Popen(
['git', 'rev-parse', '--short', 'HEAD'],
@@ -2663,7 +2666,7 @@ class YoutubeDL(object):
out, err = process_communicate_or_kill(sp)
out = out.decode().strip()
if re.match('[0-9a-f]+', out):
- self._write_string('[debug] Git HEAD: ' + out + '\n')
+ self._write_string('[debug] Git HEAD: %s\n' % out)
except Exception:
try:
sys.exc_clear()
diff --git a/youtube_dlc/extractor/__init__.py b/youtube_dlc/extractor/__init__.py
index 18d8dbcd6..56251384d 100644
--- a/youtube_dlc/extractor/__init__.py
+++ b/youtube_dlc/extractor/__init__.py
@@ -1,13 +1,19 @@
from __future__ import unicode_literals
+from ..utils import load_plugins
+
try:
from .lazy_extractors import *
from .lazy_extractors import _ALL_CLASSES
_LAZY_LOADER = True
+ _PLUGIN_CLASSES = []
+
except ImportError:
_LAZY_LOADER = False
from .extractors import *
+ _PLUGIN_CLASSES = load_plugins('extractor', 'IE', globals())
+
_ALL_CLASSES = [
klass
for name, klass in globals().items()
diff --git a/youtube_dlc/options.py b/youtube_dlc/options.py
index 7a18f0f84..97e8964d6 100644
--- a/youtube_dlc/options.py
+++ b/youtube_dlc/options.py
@@ -15,6 +15,7 @@ from .compat import (
)
from .utils import (
expand_path,
+ get_executable_path,
preferredencoding,
write_string,
)
@@ -1226,13 +1227,7 @@ def parseOpts(overrideArguments=None):
return [], None
return config, current_path
- def get_portable_path():
- path = os.path.dirname(sys.argv[0])
- if os.path.abspath(sys.argv[0]) != os.path.abspath(sys.executable): # Not packaged
- path = os.path.join(path, '..')
- return os.path.abspath(path)
-
- configs['portable'], paths['portable'] = read_options(get_portable_path())
+ configs['portable'], paths['portable'] = read_options(get_executable_path())
if '--ignore-config' in configs['portable']:
return
diff --git a/youtube_dlc/utils.py b/youtube_dlc/utils.py
index 6740f0cdb..34a14424a 100644
--- a/youtube_dlc/utils.py
+++ b/youtube_dlc/utils.py
@@ -16,6 +16,7 @@ import email.header
import errno
import functools
import gzip
+import imp
import io
import itertools
import json
@@ -5905,3 +5906,31 @@ def make_dir(path, to_screen=None):
if callable(to_screen) is not None:
to_screen('unable to create directory ' + error_to_compat_str(err))
return False
+
+
+def get_executable_path():
+ path = os.path.dirname(sys.argv[0])
+ if os.path.abspath(sys.argv[0]) != os.path.abspath(sys.executable): # Not packaged
+ path = os.path.join(path, '..')
+ return os.path.abspath(path)
+
+
+def load_plugins(name, type, namespace):
+ plugin_info = [None]
+ classes = []
+ try:
+ plugin_info = imp.find_module(
+ name, [os.path.join(get_executable_path(), 'ytdlp_plugins')])
+ plugins = imp.load_module(name, *plugin_info)
+ for name in dir(plugins):
+ if not name.endswith(type):
+ continue
+ klass = getattr(plugins, name)
+ classes.append(klass)
+ namespace[name] = klass
+ except ImportError:
+ pass
+ finally:
+ if plugin_info[0] is not None:
+ plugin_info[0].close()
+ return classes
diff --git a/ytdlp_plugins/extractor/__init__.py b/ytdlp_plugins/extractor/__init__.py
new file mode 100644
index 000000000..e1a83b909
--- /dev/null
+++ b/ytdlp_plugins/extractor/__init__.py
@@ -0,0 +1,2 @@
+# flake8: noqa
+from .sample import SamplePluginIE
diff --git a/ytdlp_plugins/extractor/sample.py b/ytdlp_plugins/extractor/sample.py
new file mode 100644
index 000000000..41954b6be
--- /dev/null
+++ b/ytdlp_plugins/extractor/sample.py
@@ -0,0 +1,12 @@
+from __future__ import unicode_literals
+
+from youtube_dlc.extractor.common import InfoExtractor
+
+
+class SamplePluginIE(InfoExtractor):
+ _WORKING = False
+ IE_DESC = False
+ _VALID_URL = r'^sampleplugin:'
+
+ def _real_extract(self, url):
+ self.to_screen('URL "%s" sucessfully captured' % url)