mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-15 21:53:21 +00:00
Compare commits
10 Commits
c4b6c5c7c9
...
c220d9efc8
Author | SHA1 | Date | |
---|---|---|---|
|
c220d9efc8 | ||
|
81e0195998 | ||
|
f1e2d4a9a2 | ||
|
3157158f76 | ||
|
16d4535abc | ||
|
2a5e5477bc | ||
|
e251986cbe | ||
|
f0ad6f8c51 | ||
|
70b2340909 | ||
|
115add4387 |
15
.github/ISSUE_TEMPLATE/1_broken_site.yml
vendored
15
.github/ISSUE_TEMPLATE/1_broken_site.yml
vendored
@ -2,6 +2,13 @@ name: Broken site
|
|||||||
description: Report broken or misfunctioning site
|
description: Report broken or misfunctioning site
|
||||||
labels: [triage, site-bug]
|
labels: [triage, site-bug]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -11,7 +18,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I'm reporting a broken site
|
- label: I'm reporting a broken site
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
||||||
required: true
|
required: true
|
||||||
@ -55,7 +62,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -63,8 +70,8 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
|
@ -2,6 +2,13 @@ name: Site support request
|
|||||||
description: Request support for a new site
|
description: Request support for a new site
|
||||||
labels: [triage, site-request]
|
labels: [triage, site-request]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -11,7 +18,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I'm reporting a new site support request
|
- label: I'm reporting a new site support request
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
||||||
required: true
|
required: true
|
||||||
@ -67,7 +74,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -75,8 +82,8 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
|
@ -2,6 +2,13 @@ name: Site feature request
|
|||||||
description: Request a new functionality for a supported site
|
description: Request a new functionality for a supported site
|
||||||
labels: [triage, site-enhancement]
|
labels: [triage, site-enhancement]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -11,7 +18,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I'm requesting a site-specific feature
|
- label: I'm requesting a site-specific feature
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
||||||
required: true
|
required: true
|
||||||
@ -63,7 +70,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -71,8 +78,8 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
|
15
.github/ISSUE_TEMPLATE/4_bug_report.yml
vendored
15
.github/ISSUE_TEMPLATE/4_bug_report.yml
vendored
@ -2,6 +2,13 @@ name: Bug report
|
|||||||
description: Report a bug unrelated to any particular site or extractor
|
description: Report a bug unrelated to any particular site or extractor
|
||||||
labels: [triage, bug]
|
labels: [triage, bug]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -11,7 +18,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I'm reporting a bug unrelated to a specific site
|
- label: I'm reporting a bug unrelated to a specific site
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
- label: I've checked that all provided URLs are playable in a browser with the same IP and same login details
|
||||||
required: true
|
required: true
|
||||||
@ -48,7 +55,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -56,8 +63,8 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
|
15
.github/ISSUE_TEMPLATE/5_feature_request.yml
vendored
15
.github/ISSUE_TEMPLATE/5_feature_request.yml
vendored
@ -2,6 +2,13 @@ name: Feature request
|
|||||||
description: Request a new functionality unrelated to any particular site or extractor
|
description: Request a new functionality unrelated to any particular site or extractor
|
||||||
labels: [triage, enhancement]
|
labels: [triage, enhancement]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -13,7 +20,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
|
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
|
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
|
||||||
required: true
|
required: true
|
||||||
@ -44,7 +51,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -52,7 +59,7 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
|
17
.github/ISSUE_TEMPLATE/6_question.yml
vendored
17
.github/ISSUE_TEMPLATE/6_question.yml
vendored
@ -2,12 +2,19 @@ name: Ask question
|
|||||||
description: Ask yt-dlp related question
|
description: Ask yt-dlp related question
|
||||||
labels: [question]
|
labels: [question]
|
||||||
body:
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\* field
|
||||||
|
required: true
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
### Make sure you are **only** asking a question and not reporting a bug or requesting a feature.
|
### Make sure you are **only** asking a question and not reporting a bug or requesting a feature.
|
||||||
If your question contains "isn't working" or "can you add", this is most likely the wrong template.
|
If your question contains "isn't working" or "can you add", this is most likely the wrong template.
|
||||||
If you are in doubt whether this is the right template, **use another template**!
|
If you are in doubt whether this is the right template, **USE ANOTHER TEMPLATE**!
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
@ -19,7 +26,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
|
- label: I've looked through the [README](https://github.com/yt-dlp/yt-dlp#readme)
|
||||||
required: true
|
required: true
|
||||||
- label: I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
- label: I've verified that I'm running yt-dlp version **2022.08.08** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
|
||||||
required: true
|
required: true
|
||||||
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar questions **including closed ones**. DO NOT post duplicates
|
- label: I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar questions **including closed ones**. DO NOT post duplicates
|
||||||
required: true
|
required: true
|
||||||
@ -50,7 +57,7 @@ body:
|
|||||||
[debug] Command-line config: ['-vU', 'test:youtube']
|
[debug] Command-line config: ['-vU', 'test:youtube']
|
||||||
[debug] Portable config "yt-dlp.conf": ['-i']
|
[debug] Portable config "yt-dlp.conf": ['-i']
|
||||||
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
|
||||||
[debug] yt-dlp version 2022.07.18 [9d339c4] (win32_exe)
|
[debug] yt-dlp version 2022.08.08 [9d339c4] (win32_exe)
|
||||||
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
[debug] Python 3.8.10 (CPython 64bit) - Windows-10-10.0.22000-SP0
|
||||||
[debug] Checking exe version: ffmpeg -bsfs
|
[debug] Checking exe version: ffmpeg -bsfs
|
||||||
[debug] Checking exe version: ffprobe -bsfs
|
[debug] Checking exe version: ffprobe -bsfs
|
||||||
@ -58,7 +65,7 @@ body:
|
|||||||
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
|
||||||
Latest version: 2022.07.18, Current version: 2022.07.18
|
Latest version: 2022.08.08, Current version: 2022.08.08
|
||||||
yt-dlp is up to date (2022.07.18)
|
yt-dlp is up to date (2022.08.08)
|
||||||
<more lines>
|
<more lines>
|
||||||
render: shell
|
render: shell
|
||||||
|
@ -2,6 +2,7 @@ name: Broken site
|
|||||||
description: Report broken or misfunctioning site
|
description: Report broken or misfunctioning site
|
||||||
labels: [triage, site-bug]
|
labels: [triage, site-bug]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -2,6 +2,7 @@ name: Site support request
|
|||||||
description: Request support for a new site
|
description: Request support for a new site
|
||||||
labels: [triage, site-request]
|
labels: [triage, site-request]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -2,6 +2,7 @@ name: Site feature request
|
|||||||
description: Request a new functionality for a supported site
|
description: Request a new functionality for a supported site
|
||||||
labels: [triage, site-enhancement]
|
labels: [triage, site-enhancement]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
1
.github/ISSUE_TEMPLATE_tmpl/4_bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE_tmpl/4_bug_report.yml
vendored
@ -2,6 +2,7 @@ name: Bug report
|
|||||||
description: Report a bug unrelated to any particular site or extractor
|
description: Report a bug unrelated to any particular site or extractor
|
||||||
labels: [triage, bug]
|
labels: [triage, bug]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -2,6 +2,7 @@ name: Feature request
|
|||||||
description: Request a new functionality unrelated to any particular site or extractor
|
description: Request a new functionality unrelated to any particular site or extractor
|
||||||
labels: [triage, enhancement]
|
labels: [triage, enhancement]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
3
.github/ISSUE_TEMPLATE_tmpl/6_question.yml
vendored
3
.github/ISSUE_TEMPLATE_tmpl/6_question.yml
vendored
@ -2,12 +2,13 @@ name: Ask question
|
|||||||
description: Ask yt-dlp related question
|
description: Ask yt-dlp related question
|
||||||
labels: [question]
|
labels: [question]
|
||||||
body:
|
body:
|
||||||
|
%(no_skip)s
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
### Make sure you are **only** asking a question and not reporting a bug or requesting a feature.
|
### Make sure you are **only** asking a question and not reporting a bug or requesting a feature.
|
||||||
If your question contains "isn't working" or "can you add", this is most likely the wrong template.
|
If your question contains "isn't working" or "can you add", this is most likely the wrong template.
|
||||||
If you are in doubt whether this is the right template, **use another template**!
|
If you are in doubt whether this is the right template, **USE ANOTHER TEMPLATE**!
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,3 +1,5 @@
|
|||||||
|
**IMPORTANT**: PRs without the template will be CLOSED
|
||||||
|
|
||||||
### Description of your *pull request* and other information
|
### Description of your *pull request* and other information
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -89,6 +89,7 @@ jobs:
|
|||||||
if: "env.TWINE_PASSWORD != ''"
|
if: "env.TWINE_PASSWORD != ''"
|
||||||
run: |
|
run: |
|
||||||
rm -rf dist/*
|
rm -rf dist/*
|
||||||
|
python devscripts/set-variant.py pip -M "You installed yt-dlp with pip or using the wheel from PyPi; Use that to update"
|
||||||
python setup.py sdist bdist_wheel
|
python setup.py sdist bdist_wheel
|
||||||
twine upload dist/*
|
twine upload dist/*
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Get Changelog
|
- name: Get Changelog
|
||||||
run: |
|
run: |
|
||||||
changelog=$(grep -oPz '(?s)(?<=### ${{ steps.bump_version.outputs.ytdlp_version }}\n{2}).+?(?=\n{2,3}###)' Changelog.md) || true
|
changelog=$(grep -oPz '(?s)(?<=### ${{ needs.prepare.outputs.ytdlp_version }}\n{2}).+?(?=\n{2,3}###)' Changelog.md) || true
|
||||||
echo "changelog<<EOF" >> $GITHUB_ENV
|
echo "changelog<<EOF" >> $GITHUB_ENV
|
||||||
echo "$changelog" >> $GITHUB_ENV
|
echo "$changelog" >> $GITHUB_ENV
|
||||||
echo "EOF" >> $GITHUB_ENV
|
echo "EOF" >> $GITHUB_ENV
|
||||||
|
@ -285,3 +285,12 @@ odo2063
|
|||||||
pritam20ps05
|
pritam20ps05
|
||||||
scy
|
scy
|
||||||
sheerluck
|
sheerluck
|
||||||
|
AxiosDeminence
|
||||||
|
DjesonPV
|
||||||
|
eren-kemer
|
||||||
|
freezboltz
|
||||||
|
Galiley
|
||||||
|
haobinliang
|
||||||
|
Mehavoid
|
||||||
|
winterbird-code
|
||||||
|
yashkc2025
|
||||||
|
86
Changelog.md
86
Changelog.md
@ -11,6 +11,92 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
### 2022.08.08
|
||||||
|
|
||||||
|
* **Remove Python 3.6 support**
|
||||||
|
* Determine merge container better by [pukkandan](https://github.com/pukkandan), [selfisekai](https://github.com/selfisekai)
|
||||||
|
* Framework for embed detection by [coletdjnz](https://github.com/coletdjnz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* Merge youtube-dl: Upto [commit/adb5294](https://github.com/ytdl-org/youtube-dl/commit/adb5294)
|
||||||
|
* `--compat-option no-live-chat` should disable danmaku
|
||||||
|
* Fix misleading DRM message
|
||||||
|
* Import ctypes only when necessary
|
||||||
|
* Minor bugfixes by [pukkandan](https://github.com/pukkandan)
|
||||||
|
* Reject entire playlists faster with `--match-filter` by [pukkandan](https://github.com/pukkandan)
|
||||||
|
* Remove filtered entries from `-J`
|
||||||
|
* Standardize retry mechanism by [pukkandan](https://github.com/pukkandan)
|
||||||
|
* Validate `--merge-output-format`
|
||||||
|
* [downloader] Add average speed to final progress line
|
||||||
|
* [extractor] Add field `audio_channels`
|
||||||
|
* [extractor] Support multiple archive ids for one video
|
||||||
|
* [ffmpeg] Set `ffmpeg_location` in a contextvar
|
||||||
|
* [FFmpegThumbnailsConvertor] Fix conversion from GIF
|
||||||
|
* [MetadataParser] Don't set `None` when the field didn't match
|
||||||
|
* [outtmpl] Smarter replacing of unsupported characters by [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [outtmpl] Treat empty values as None in filenames
|
||||||
|
* [utils] sanitize_open: Allow any IO stream as stdout
|
||||||
|
* [build, devscripts] Add devscript to set a build variant
|
||||||
|
* [build] Improve build process by [shirt-dev](https://github.com/shirt-dev)
|
||||||
|
* [build] Update pyinstaller
|
||||||
|
* [devscripts] Create `utils` and refactor
|
||||||
|
* [docs] Clarify `best*`
|
||||||
|
* [docs] Fix bug report issue template
|
||||||
|
* [docs] Fix capitalization in references by [christoph-heinrich](https://github.com/christoph-heinrich)
|
||||||
|
* [cleanup, mhtml] Use imghdr
|
||||||
|
* [cleanup, utils] Consolidate known media extensions
|
||||||
|
* [cleanup] Misc fixes and cleanup
|
||||||
|
* [extractor/angel] Add extractor by [AxiosDeminence](https://github.com/AxiosDeminence)
|
||||||
|
* [extractor/dplay] Add MotorTrend extractor by [Sipherdrakon](https://github.com/Sipherdrakon)
|
||||||
|
* [extractor/harpodeon] Add extractor by [eren-kemer](https://github.com/eren-kemer)
|
||||||
|
* [extractor/holodex] Add extractor by [pukkandan](https://github.com/pukkandan), [sqrtNOT](https://github.com/sqrtNOT)
|
||||||
|
* [extractor/kompas] Add extractor by [HobbyistDev](https://github.com/HobbyistDev)
|
||||||
|
* [extractor/rai] Add raisudtirol extractor by [nixxo](https://github.com/nixxo)
|
||||||
|
* [extractor/tempo] Add extractor by [HobbyistDev](https://github.com/HobbyistDev)
|
||||||
|
* [extractor/youtube] **Fixes for third party client detection** by [coletdjnz](https://github.com/coletdjnz)
|
||||||
|
* [extractor/youtube] Add `live_status=post_live` by [lazypete365](https://github.com/lazypete365)
|
||||||
|
* [extractor/youtube] Extract more format info
|
||||||
|
* [extractor/youtube] Parse translated subtitles only when requested
|
||||||
|
* [extractor/youtube, extractor/twitch] Allow waiting for channels to become live
|
||||||
|
* [extractor/youtube, webvtt] Extract auto-subs from livestream VODs by [fstirlitz](https://github.com/fstirlitz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/AbemaTVTitle] Implement paging by [Lesmiscore](https://github.com/Lesmiscore)
|
||||||
|
* [extractor/archiveorg] Improve handling of formats by [coletdjnz](https://github.com/coletdjnz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/arte] Fix title extraction
|
||||||
|
* [extractor/arte] **Move to v2 API** by [fstirlitz](https://github.com/fstirlitz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/bbc] Fix news articles by [ajj8](https://github.com/ajj8)
|
||||||
|
* [extractor/camtasia] Separate into own extractor by [coletdjnz](https://github.com/coletdjnz)
|
||||||
|
* [extractor/cloudflarestream] Fix video_id padding by [haobinliang](https://github.com/haobinliang)
|
||||||
|
* [extractor/crunchyroll] Fix conversion of thumbnail from GIF by [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/crunchyroll] Handle missing metadata correctly by [Burve](https://github.com/Burve), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/crunchyroll:beta] Extract timestamp and fix tests by [tejing1](https://github.com/tejing1)
|
||||||
|
* [extractor/crunchyroll:beta] Use streams API by [tejing1](https://github.com/tejing1)
|
||||||
|
* [extractor/doodstream] Support more domains by [Galiley](https://github.com/Galiley)
|
||||||
|
* [extractor/ESPN] Extract duration by [ischmidt20](https://github.com/ischmidt20)
|
||||||
|
* [extractor/FIFA] Change API endpoint by [Bricio](https://github.com/Bricio), [yashkc2025](https://github.com/yashkc2025)
|
||||||
|
* [extractor/globo:article] Remove false positives by [Bricio](https://github.com/Bricio)
|
||||||
|
* [extractor/Go] Extract timestamp by [ischmidt20](https://github.com/ischmidt20)
|
||||||
|
* [extractor/hidive] Fix cookie login when netrc is also given by [winterbird-code](https://github.com/winterbird-code)
|
||||||
|
* [extractor/html5] Separate into own extractor by [coletdjnz](https://github.com/coletdjnz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/ina] Improve extractor by [elyse0](https://github.com/elyse0)
|
||||||
|
* [extractor/NaverNow] Change endpoint by [ping](https://github.com/ping)
|
||||||
|
* [extractor/ninegag] Extract uploader by [DjesonPV](https://github.com/DjesonPV)
|
||||||
|
* [extractor/NovaPlay] Fix extractor by [Bojidarist](https://github.com/Bojidarist)
|
||||||
|
* [extractor/orf:radio] Rewrite extractors
|
||||||
|
* [extractor/patreon] Fix and improve extractors by [coletdjnz](https://github.com/coletdjnz), [pukkandan](https://github.com/pukkandan)
|
||||||
|
* [extractor/rai] Fix RaiNews extraction by [nixxo](https://github.com/nixxo)
|
||||||
|
* [extractor/redbee] Unify and update extractors by [elyse0](https://github.com/elyse0)
|
||||||
|
* [extractor/stripchat] Fix _VALID_URL by [freezboltz](https://github.com/freezboltz)
|
||||||
|
* [extractor/tubi] Exclude playlists from playlist entries by [sqrtNOT](https://github.com/sqrtNOT)
|
||||||
|
* [extractor/tviplayer] Improve `_VALID_URL` by [HobbyistDev](https://github.com/HobbyistDev)
|
||||||
|
* [extractor/twitch] Extract chapters for single chapter VODs by [mpeter50](https://github.com/mpeter50)
|
||||||
|
* [extractor/vgtv] Support tv.vg.no by [sqrtNOT](https://github.com/sqrtNOT)
|
||||||
|
* [extractor/vidio] Support embed link by [HobbyistDev](https://github.com/HobbyistDev)
|
||||||
|
* [extractor/vk] Fix extractor by [Mehavoid](https://github.com/Mehavoid)
|
||||||
|
* [extractor/WASDTV:record] Fix `_VALID_URL`
|
||||||
|
* [extractor/xfileshare] Add Referer by [Galiley](https://github.com/Galiley)
|
||||||
|
* [extractor/YahooJapanNews] Fix extractor by [Lesmiscore](https://github.com/Lesmiscore)
|
||||||
|
* [extractor/yandexmusic] Extract higher quality format
|
||||||
|
* [extractor/zee5] Update Device ID by [m4tu4g](https://github.com/m4tu4g)
|
||||||
|
|
||||||
|
|
||||||
### 2022.07.18
|
### 2022.07.18
|
||||||
|
|
||||||
* Allow users to specify encoding in each config files by [Lesmiscore](https://github.com/Lesmiscore)
|
* Allow users to specify encoding in each config files by [Lesmiscore](https://github.com/Lesmiscore)
|
||||||
|
11
README.md
11
README.md
@ -71,7 +71,7 @@ yt-dlp is a [youtube-dl](https://github.com/ytdl-org/youtube-dl) fork based on t
|
|||||||
|
|
||||||
# NEW FEATURES
|
# NEW FEATURES
|
||||||
|
|
||||||
* Merged with **youtube-dl v2021.12.17+ [commit/a03b977](https://github.com/ytdl-org/youtube-dl/commit/a03b9775d544b06a5b4f2aa630214c7c22fc2229)**<!--([exceptions](https://github.com/yt-dlp/yt-dlp/issues/21))--> and **youtube-dlc v2020.11.11-3+ [commit/f9401f2](https://github.com/blackjack4494/yt-dlc/commit/f9401f2a91987068139c5f757b12fc711d4c0cee)**: You get all the features and patches of [youtube-dlc](https://github.com/blackjack4494/yt-dlc) in addition to the latest [youtube-dl](https://github.com/ytdl-org/youtube-dl)
|
* Merged with **youtube-dl v2021.12.17+ [commit/adb5294](https://github.com/ytdl-org/youtube-dl/commit/adb5294177265ba35b45746dbb600965076ed150)**<!--([exceptions](https://github.com/yt-dlp/yt-dlp/issues/21))--> and **youtube-dlc v2020.11.11-3+ [commit/f9401f2](https://github.com/blackjack4494/yt-dlc/commit/f9401f2a91987068139c5f757b12fc711d4c0cee)**: You get all the features and patches of [youtube-dlc](https://github.com/blackjack4494/yt-dlc) in addition to the latest [youtube-dl](https://github.com/ytdl-org/youtube-dl)
|
||||||
|
|
||||||
* **[SponsorBlock Integration](#sponsorblock-options)**: You can mark/remove sponsor sections in youtube videos by utilizing the [SponsorBlock](https://sponsor.ajay.app) API
|
* **[SponsorBlock Integration](#sponsorblock-options)**: You can mark/remove sponsor sections in youtube videos by utilizing the [SponsorBlock](https://sponsor.ajay.app) API
|
||||||
|
|
||||||
@ -312,7 +312,7 @@ If you do not have the necessary dependencies for a task you are attempting, yt-
|
|||||||
## COMPILE
|
## COMPILE
|
||||||
|
|
||||||
### Standalone PyInstaller Builds
|
### Standalone PyInstaller Builds
|
||||||
To build the Windows/MacOS executable, you must have Python and `pyinstaller` (plus any of yt-dlp's [optional dependencies](#dependencies) if needed). Once you have all the necessary dependencies installed, simply run `pyinst.py`. The executable will be built for the same architecture (32/64 bit) as the Python used.
|
To build the standalone executable, you must have Python and `pyinstaller` (plus any of yt-dlp's [optional dependencies](#dependencies) if needed). Once you have all the necessary dependencies installed, simply run `pyinst.py`. The executable will be built for the same architecture (x86/ARM, 32/64 bit) as the Python used.
|
||||||
|
|
||||||
python3 -m pip install -U pyinstaller -r requirements.txt
|
python3 -m pip install -U pyinstaller -r requirements.txt
|
||||||
python3 devscripts/make_lazy_extractors.py
|
python3 devscripts/make_lazy_extractors.py
|
||||||
@ -343,7 +343,8 @@ If you wish to build it anyway, install Python and py2exe, and then simply run `
|
|||||||
|
|
||||||
### Related scripts
|
### Related scripts
|
||||||
|
|
||||||
* **`devscripts/update-version.py`** - Update the version number based on current timestamp
|
* **`devscripts/update-version.py [revision]`** - Update the version number based on current date
|
||||||
|
* **`devscripts/set-variant.py variant [-M update_message]`** - Set the build variant of the executable
|
||||||
* **`devscripts/make_lazy_extractors.py`** - Create lazy extractors. Running this before building the binaries (any variant) will improve their startup performance. Set the environment variable `YTDLP_NO_LAZY_EXTRACTORS=1` if you wish to forcefully disable lazy extractor loading.
|
* **`devscripts/make_lazy_extractors.py`** - Create lazy extractors. Running this before building the binaries (any variant) will improve their startup performance. Set the environment variable `YTDLP_NO_LAZY_EXTRACTORS=1` if you wish to forcefully disable lazy extractor loading.
|
||||||
|
|
||||||
You can also fork the project on github and run your fork's [build workflow](.github/workflows/build.yml) to automatically build a full release
|
You can also fork the project on github and run your fork's [build workflow](.github/workflows/build.yml) to automatically build a full release
|
||||||
@ -360,8 +361,8 @@ You can also fork the project on github and run your fork's [build workflow](.gi
|
|||||||
## General Options:
|
## General Options:
|
||||||
-h, --help Print this help text and exit
|
-h, --help Print this help text and exit
|
||||||
--version Print program version and exit
|
--version Print program version and exit
|
||||||
-U, --update Update this program to latest version
|
-U, --update Update this program to the latest version
|
||||||
--no-update Do not update (default)
|
--no-update Do not check for updates (default)
|
||||||
-i, --ignore-errors Ignore download and postprocessing errors.
|
-i, --ignore-errors Ignore download and postprocessing errors.
|
||||||
The download will be considered successful
|
The download will be considered successful
|
||||||
even if the postprocessing fails
|
even if the postprocessing fails
|
||||||
|
@ -7,20 +7,14 @@ import sys
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
import optparse
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from devscripts.utils import (
|
||||||
def read(fname):
|
get_filename_args,
|
||||||
with open(fname, encoding='utf-8') as f:
|
read_file,
|
||||||
return f.read()
|
read_version,
|
||||||
|
write_file,
|
||||||
|
)
|
||||||
# Get the version without importing the package
|
|
||||||
def read_version(fname):
|
|
||||||
exec(compile(read(fname), fname, 'exec'))
|
|
||||||
return locals()['__version__']
|
|
||||||
|
|
||||||
|
|
||||||
VERBOSE_TMPL = '''
|
VERBOSE_TMPL = '''
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
@ -58,20 +52,24 @@ VERBOSE_TMPL = '''
|
|||||||
required: true
|
required: true
|
||||||
'''.strip()
|
'''.strip()
|
||||||
|
|
||||||
|
NO_SKIP = '''
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE
|
||||||
|
description: Fill all fields even if you think it is irrelevant for the issue
|
||||||
|
options:
|
||||||
|
- label: I understand that I will be **blocked** if I remove or skip any mandatory\\* field
|
||||||
|
required: true
|
||||||
|
'''.strip()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = optparse.OptionParser(usage='%prog INFILE OUTFILE')
|
fields = {'version': read_version(), 'no_skip': NO_SKIP}
|
||||||
_, args = parser.parse_args()
|
|
||||||
if len(args) != 2:
|
|
||||||
parser.error('Expected an input and an output filename')
|
|
||||||
|
|
||||||
fields = {'version': read_version('yt_dlp/version.py')}
|
|
||||||
fields['verbose'] = VERBOSE_TMPL % fields
|
fields['verbose'] = VERBOSE_TMPL % fields
|
||||||
fields['verbose_optional'] = re.sub(r'(\n\s+validations:)?\n\s+required: true', '', fields['verbose'])
|
fields['verbose_optional'] = re.sub(r'(\n\s+validations:)?\n\s+required: true', '', fields['verbose'])
|
||||||
|
|
||||||
infile, outfile = args
|
infile, outfile = get_filename_args(has_infile=True)
|
||||||
with open(outfile, 'w', encoding='utf-8') as outf:
|
write_file(outfile, read_file(infile) % fields)
|
||||||
outf.write(read(infile) % fields)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -7,9 +7,10 @@ import sys
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
import optparse
|
|
||||||
from inspect import getsource
|
from inspect import getsource
|
||||||
|
|
||||||
|
from devscripts.utils import get_filename_args, read_file, write_file
|
||||||
|
|
||||||
NO_ATTR = object()
|
NO_ATTR = object()
|
||||||
STATIC_CLASS_PROPERTIES = ['IE_NAME', 'IE_DESC', 'SEARCH_KEY', '_VALID_URL', '_WORKING', '_NETRC_MACHINE', 'age_limit']
|
STATIC_CLASS_PROPERTIES = ['IE_NAME', 'IE_DESC', 'SEARCH_KEY', '_VALID_URL', '_WORKING', '_NETRC_MACHINE', 'age_limit']
|
||||||
CLASS_METHODS = [
|
CLASS_METHODS = [
|
||||||
@ -19,17 +20,11 @@ IE_TEMPLATE = '''
|
|||||||
class {name}({bases}):
|
class {name}({bases}):
|
||||||
_module = {module!r}
|
_module = {module!r}
|
||||||
'''
|
'''
|
||||||
with open('devscripts/lazy_load_template.py', encoding='utf-8') as f:
|
MODULE_TEMPLATE = read_file('devscripts/lazy_load_template.py')
|
||||||
MODULE_TEMPLATE = f.read()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = optparse.OptionParser(usage='%prog [OUTFILE.py]')
|
lazy_extractors_filename = get_filename_args(default_outfile='yt_dlp/extractor/lazy_extractors.py')
|
||||||
args = parser.parse_args()[1] or ['yt_dlp/extractor/lazy_extractors.py']
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.error('Expected only an output filename')
|
|
||||||
|
|
||||||
lazy_extractors_filename = args[0]
|
|
||||||
if os.path.exists(lazy_extractors_filename):
|
if os.path.exists(lazy_extractors_filename):
|
||||||
os.remove(lazy_extractors_filename)
|
os.remove(lazy_extractors_filename)
|
||||||
|
|
||||||
@ -46,8 +41,7 @@ def main():
|
|||||||
*build_ies(_ALL_CLASSES, (InfoExtractor, SearchInfoExtractor), DummyInfoExtractor),
|
*build_ies(_ALL_CLASSES, (InfoExtractor, SearchInfoExtractor), DummyInfoExtractor),
|
||||||
))
|
))
|
||||||
|
|
||||||
with open(lazy_extractors_filename, 'wt', encoding='utf-8') as f:
|
write_file(lazy_extractors_filename, f'{module_src}\n')
|
||||||
f.write(f'{module_src}\n')
|
|
||||||
|
|
||||||
|
|
||||||
def get_all_ies():
|
def get_all_ies():
|
||||||
|
@ -5,10 +5,17 @@ yt-dlp --help | make_readme.py
|
|||||||
This must be run in a console of correct width
|
This must be run in a console of correct width
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Allow direct execution
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
from devscripts.utils import read_file, write_file
|
||||||
|
|
||||||
README_FILE = 'README.md'
|
README_FILE = 'README.md'
|
||||||
|
|
||||||
@ -38,6 +45,10 @@ switch_col_width = len(re.search(r'(?m)^\s{5,}', options).group())
|
|||||||
delim = f'\n{" " * switch_col_width}'
|
delim = f'\n{" " * switch_col_width}'
|
||||||
|
|
||||||
PATCHES = (
|
PATCHES = (
|
||||||
|
( # Standardize update message
|
||||||
|
r'(?m)^( -U, --update\s+).+(\n \s.+)*$',
|
||||||
|
r'\1Update this program to the latest version',
|
||||||
|
),
|
||||||
( # Headings
|
( # Headings
|
||||||
r'(?m)^ (\w.+\n)( (?=\w))?',
|
r'(?m)^ (\w.+\n)( (?=\w))?',
|
||||||
r'## \1'
|
r'## \1'
|
||||||
@ -63,12 +74,10 @@ PATCHES = (
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(README_FILE, encoding='utf-8') as f:
|
readme = read_file(README_FILE)
|
||||||
readme = f.read()
|
|
||||||
|
|
||||||
with open(README_FILE, 'w', encoding='utf-8') as f:
|
write_file(README_FILE, ''.join((
|
||||||
f.write(''.join((
|
take_section(readme, end=f'## {OPTIONS_START}'),
|
||||||
take_section(readme, end=f'## {OPTIONS_START}'),
|
functools.reduce(apply_patch, PATCHES, options),
|
||||||
functools.reduce(apply_patch, PATCHES, options),
|
take_section(readme, f'# {OPTIONS_END}'),
|
||||||
take_section(readme, f'# {OPTIONS_END}'),
|
)))
|
||||||
)))
|
|
||||||
|
@ -7,21 +7,13 @@ import sys
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
import optparse
|
from devscripts.utils import get_filename_args, write_file
|
||||||
|
|
||||||
from yt_dlp.extractor import list_extractor_classes
|
from yt_dlp.extractor import list_extractor_classes
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = optparse.OptionParser(usage='%prog OUTFILE.md')
|
|
||||||
_, args = parser.parse_args()
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.error('Expected an output filename')
|
|
||||||
|
|
||||||
out = '\n'.join(ie.description() for ie in list_extractor_classes() if ie.IE_DESC is not False)
|
out = '\n'.join(ie.description() for ie in list_extractor_classes() if ie.IE_DESC is not False)
|
||||||
|
write_file(get_filename_args(), f'# Supported sites\n{out}\n')
|
||||||
with open(args[0], 'w', encoding='utf-8') as outf:
|
|
||||||
outf.write(f'# Supported sites\n{out}\n')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import optparse
|
# Allow direct execution
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from devscripts.utils import (
|
||||||
|
compose_functions,
|
||||||
|
get_filename_args,
|
||||||
|
read_file,
|
||||||
|
write_file,
|
||||||
|
)
|
||||||
|
|
||||||
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
README_FILE = os.path.join(ROOT_DIR, 'README.md')
|
README_FILE = os.path.join(ROOT_DIR, 'README.md')
|
||||||
|
|
||||||
@ -22,25 +35,6 @@ yt\-dlp \- A youtube-dl fork with additional features and patches
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = optparse.OptionParser(usage='%prog OUTFILE.md')
|
|
||||||
_, args = parser.parse_args()
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.error('Expected an output filename')
|
|
||||||
|
|
||||||
outfile, = args
|
|
||||||
|
|
||||||
with open(README_FILE, encoding='utf-8') as f:
|
|
||||||
readme = f.read()
|
|
||||||
|
|
||||||
readme = filter_excluded_sections(readme)
|
|
||||||
readme = move_sections(readme)
|
|
||||||
readme = filter_options(readme)
|
|
||||||
|
|
||||||
with open(outfile, 'w', encoding='utf-8') as outf:
|
|
||||||
outf.write(PREFIX + readme)
|
|
||||||
|
|
||||||
|
|
||||||
def filter_excluded_sections(readme):
|
def filter_excluded_sections(readme):
|
||||||
EXCLUDED_SECTION_BEGIN_STRING = re.escape('<!-- MANPAGE: BEGIN EXCLUDED SECTION -->')
|
EXCLUDED_SECTION_BEGIN_STRING = re.escape('<!-- MANPAGE: BEGIN EXCLUDED SECTION -->')
|
||||||
EXCLUDED_SECTION_END_STRING = re.escape('<!-- MANPAGE: END EXCLUDED SECTION -->')
|
EXCLUDED_SECTION_END_STRING = re.escape('<!-- MANPAGE: END EXCLUDED SECTION -->')
|
||||||
@ -92,5 +86,12 @@ def filter_options(readme):
|
|||||||
return readme.replace(section, options, 1)
|
return readme.replace(section, options, 1)
|
||||||
|
|
||||||
|
|
||||||
|
TRANSFORM = compose_functions(filter_excluded_sections, move_sections, filter_options)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
write_file(get_filename_args(), PREFIX + TRANSFORM(read_file(README_FILE)))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
36
devscripts/set-variant.py
Normal file
36
devscripts/set-variant.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Allow direct execution
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import functools
|
||||||
|
import re
|
||||||
|
|
||||||
|
from devscripts.utils import compose_functions, read_file, write_file
|
||||||
|
|
||||||
|
VERSION_FILE = 'yt_dlp/version.py'
|
||||||
|
|
||||||
|
|
||||||
|
def parse_options():
|
||||||
|
parser = argparse.ArgumentParser(description='Set the build variant of the package')
|
||||||
|
parser.add_argument('variant', help='Name of the variant')
|
||||||
|
parser.add_argument('-M', '--update-message', default=None, help='Message to show in -U')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def property_setter(name, value):
|
||||||
|
return functools.partial(re.sub, rf'(?m)^{name}\s*=\s*.+$', f'{name} = {value!r}')
|
||||||
|
|
||||||
|
|
||||||
|
opts = parse_options()
|
||||||
|
transform = compose_functions(
|
||||||
|
property_setter('VARIANT', opts.variant),
|
||||||
|
property_setter('UPDATE_HINT', opts.update_message)
|
||||||
|
)
|
||||||
|
|
||||||
|
write_file(VERSION_FILE, transform(read_file(VERSION_FILE)))
|
@ -1,5 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Usage: python3 ./devscripts/update-formulae.py <path-to-formulae-rb> <version>
|
||||||
|
version can be either 0-aligned (yt-dlp version) or normalized (PyPi version)
|
||||||
|
"""
|
||||||
|
|
||||||
# Allow direct execution
|
# Allow direct execution
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -11,8 +16,7 @@ import json
|
|||||||
import re
|
import re
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
# usage: python3 ./devscripts/update-formulae.py <path-to-formulae-rb> <version>
|
from devscripts.utils import read_file, write_file
|
||||||
# version can be either 0-aligned (yt-dlp version) or normalized (PyPl version)
|
|
||||||
|
|
||||||
filename, version = sys.argv[1:]
|
filename, version = sys.argv[1:]
|
||||||
|
|
||||||
@ -27,11 +31,9 @@ tarball_file = next(x for x in pypi_release['urls'] if x['filename'].endswith('.
|
|||||||
sha256sum = tarball_file['digests']['sha256']
|
sha256sum = tarball_file['digests']['sha256']
|
||||||
url = tarball_file['url']
|
url = tarball_file['url']
|
||||||
|
|
||||||
with open(filename) as r:
|
formulae_text = read_file(filename)
|
||||||
formulae_text = r.read()
|
|
||||||
|
|
||||||
formulae_text = re.sub(r'sha256 "[0-9a-f]*?"', 'sha256 "%s"' % sha256sum, formulae_text, count=1)
|
formulae_text = re.sub(r'sha256 "[0-9a-f]*?"', 'sha256 "%s"' % sha256sum, formulae_text, count=1)
|
||||||
formulae_text = re.sub(r'url "[^"]*?"', 'url "%s"' % url, formulae_text, count=1)
|
formulae_text = re.sub(r'url "[^"]*?"', 'url "%s"' % url, formulae_text, count=1)
|
||||||
|
|
||||||
with open(filename, 'w') as w:
|
write_file(filename, formulae_text)
|
||||||
w.write(formulae_text)
|
|
||||||
|
@ -7,32 +7,35 @@ import sys
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
with open('yt_dlp/version.py') as f:
|
from devscripts.utils import read_version, write_file
|
||||||
exec(compile(f.read(), 'yt_dlp/version.py', 'exec'))
|
|
||||||
old_version = locals()['__version__']
|
|
||||||
|
|
||||||
old_version_list = old_version.split('.')
|
|
||||||
|
|
||||||
old_ver = '.'.join(old_version_list[:3])
|
def get_new_version(revision):
|
||||||
old_rev = old_version_list[3] if len(old_version_list) > 3 else ''
|
version = datetime.utcnow().strftime('%Y.%m.%d')
|
||||||
|
|
||||||
ver = datetime.utcnow().strftime("%Y.%m.%d")
|
if revision:
|
||||||
|
assert revision.isdigit(), 'Revision must be a number'
|
||||||
|
else:
|
||||||
|
old_version = read_version().split('.')
|
||||||
|
if version.split('.') == old_version[:3]:
|
||||||
|
revision = str(int((old_version + [0])[3]) + 1)
|
||||||
|
|
||||||
rev = (sys.argv[1:] or [''])[0] # Use first argument, if present as revision number
|
return f'{version}.{revision}' if revision else version
|
||||||
if not rev:
|
|
||||||
rev = str(int(old_rev or 0) + 1) if old_ver == ver else ''
|
|
||||||
|
|
||||||
VERSION = '.'.join((ver, rev)) if rev else ver
|
|
||||||
|
|
||||||
try:
|
def get_git_head():
|
||||||
sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE)
|
with contextlib.suppress(Exception):
|
||||||
GIT_HEAD = sp.communicate()[0].decode().strip() or None
|
sp = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE)
|
||||||
except Exception:
|
return sp.communicate()[0].decode().strip() or None
|
||||||
GIT_HEAD = None
|
|
||||||
|
|
||||||
|
VERSION = get_new_version((sys.argv + [''])[1])
|
||||||
|
GIT_HEAD = get_git_head()
|
||||||
|
|
||||||
VERSION_FILE = f'''\
|
VERSION_FILE = f'''\
|
||||||
# Autogenerated by devscripts/update-version.py
|
# Autogenerated by devscripts/update-version.py
|
||||||
@ -40,10 +43,12 @@ VERSION_FILE = f'''\
|
|||||||
__version__ = {VERSION!r}
|
__version__ = {VERSION!r}
|
||||||
|
|
||||||
RELEASE_GIT_HEAD = {GIT_HEAD!r}
|
RELEASE_GIT_HEAD = {GIT_HEAD!r}
|
||||||
|
|
||||||
|
VARIANT = None
|
||||||
|
|
||||||
|
UPDATE_HINT = None
|
||||||
'''
|
'''
|
||||||
|
|
||||||
with open('yt_dlp/version.py', 'wt') as f:
|
write_file('yt_dlp/version.py', VERSION_FILE)
|
||||||
f.write(VERSION_FILE)
|
print(f'::set-output name=ytdlp_version::{VERSION}')
|
||||||
|
|
||||||
print('::set-output name=ytdlp_version::' + VERSION)
|
|
||||||
print(f'\nVersion = {VERSION}, Git HEAD = {GIT_HEAD}')
|
print(f'\nVersion = {VERSION}, Git HEAD = {GIT_HEAD}')
|
||||||
|
35
devscripts/utils.py
Normal file
35
devscripts/utils.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import argparse
|
||||||
|
import functools
|
||||||
|
|
||||||
|
|
||||||
|
def read_file(fname):
|
||||||
|
with open(fname, encoding='utf-8') as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(fname, content):
|
||||||
|
with open(fname, 'w', encoding='utf-8') as f:
|
||||||
|
return f.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
# Get the version without importing the package
|
||||||
|
def read_version(fname='yt_dlp/version.py'):
|
||||||
|
exec(compile(read_file(fname), fname, 'exec'))
|
||||||
|
return locals()['__version__']
|
||||||
|
|
||||||
|
|
||||||
|
def get_filename_args(has_infile=False, default_outfile=None):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
if has_infile:
|
||||||
|
parser.add_argument('infile', help='Input file')
|
||||||
|
kwargs = {'nargs': '?', 'default': default_outfile} if default_outfile else {}
|
||||||
|
parser.add_argument('outfile', **kwargs, help='Output file')
|
||||||
|
|
||||||
|
opts = parser.parse_args()
|
||||||
|
if has_infile:
|
||||||
|
return opts.infile, opts.outfile
|
||||||
|
return opts.outfile
|
||||||
|
|
||||||
|
|
||||||
|
def compose_functions(*functions):
|
||||||
|
return lambda x: functools.reduce(lambda y, f: f(y), functions, x)
|
18
pyinst.py
18
pyinst.py
@ -1,11 +1,17 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Allow direct execution
|
||||||
import os
|
import os
|
||||||
import platform
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
from PyInstaller.__main__ import run as run_pyinstaller
|
from PyInstaller.__main__ import run as run_pyinstaller
|
||||||
|
|
||||||
|
from devscripts.utils import read_version
|
||||||
|
|
||||||
OS_NAME, MACHINE, ARCH = sys.platform, platform.machine(), platform.architecture()[0][:2]
|
OS_NAME, MACHINE, ARCH = sys.platform, platform.machine(), platform.architecture()[0][:2]
|
||||||
if MACHINE in ('x86_64', 'AMD64') or ('i' in MACHINE and '86' in MACHINE):
|
if MACHINE in ('x86_64', 'AMD64') or ('i' in MACHINE and '86' in MACHINE):
|
||||||
# NB: Windows x86 has MACHINE = AMD64 irrespective of bitness
|
# NB: Windows x86 has MACHINE = AMD64 irrespective of bitness
|
||||||
@ -13,8 +19,7 @@ if MACHINE in ('x86_64', 'AMD64') or ('i' in MACHINE and '86' in MACHINE):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
opts = parse_options()
|
opts, version = parse_options(), read_version()
|
||||||
version = read_version('yt_dlp/version.py')
|
|
||||||
|
|
||||||
onedir = '--onedir' in opts or '-D' in opts
|
onedir = '--onedir' in opts or '-D' in opts
|
||||||
if not onedir and '-F' not in opts and '--onefile' not in opts:
|
if not onedir and '-F' not in opts and '--onefile' not in opts:
|
||||||
@ -53,13 +58,6 @@ def parse_options():
|
|||||||
return opts
|
return opts
|
||||||
|
|
||||||
|
|
||||||
# Get the version from yt_dlp/version.py without importing the package
|
|
||||||
def read_version(fname):
|
|
||||||
with open(fname, encoding='utf-8') as f:
|
|
||||||
exec(compile(f.read(), fname, 'exec'))
|
|
||||||
return locals()['__version__']
|
|
||||||
|
|
||||||
|
|
||||||
def exe(onedir):
|
def exe(onedir):
|
||||||
"""@returns (name, path)"""
|
"""@returns (name, path)"""
|
||||||
name = '_'.join(filter(None, (
|
name = '_'.join(filter(None, (
|
||||||
|
20
setup.py
20
setup.py
@ -12,28 +12,18 @@ except ImportError:
|
|||||||
from distutils.core import Command, setup
|
from distutils.core import Command, setup
|
||||||
setuptools_available = False
|
setuptools_available = False
|
||||||
|
|
||||||
|
from devscripts.utils import read_file, read_version
|
||||||
|
|
||||||
def read(fname):
|
VERSION = read_version()
|
||||||
with open(fname, encoding='utf-8') as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
|
|
||||||
# Get the version from yt_dlp/version.py without importing the package
|
|
||||||
def read_version(fname):
|
|
||||||
exec(compile(read(fname), fname, 'exec'))
|
|
||||||
return locals()['__version__']
|
|
||||||
|
|
||||||
|
|
||||||
VERSION = read_version('yt_dlp/version.py')
|
|
||||||
|
|
||||||
DESCRIPTION = 'A youtube-dl fork with additional features and patches'
|
DESCRIPTION = 'A youtube-dl fork with additional features and patches'
|
||||||
|
|
||||||
LONG_DESCRIPTION = '\n\n'.join((
|
LONG_DESCRIPTION = '\n\n'.join((
|
||||||
'Official repository: <https://github.com/yt-dlp/yt-dlp>',
|
'Official repository: <https://github.com/yt-dlp/yt-dlp>',
|
||||||
'**PS**: Some links in this document will not work since this is a copy of the README.md from Github',
|
'**PS**: Some links in this document will not work since this is a copy of the README.md from Github',
|
||||||
read('README.md')))
|
read_file('README.md')))
|
||||||
|
|
||||||
REQUIREMENTS = read('requirements.txt').splitlines()
|
REQUIREMENTS = read_file('requirements.txt').splitlines()
|
||||||
|
|
||||||
|
|
||||||
def packages():
|
def packages():
|
||||||
@ -121,7 +111,7 @@ class build_lazy_extractors(Command):
|
|||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print('Skipping build of lazy extractors in dry run mode')
|
print('Skipping build of lazy extractors in dry run mode')
|
||||||
return
|
return
|
||||||
subprocess.run([sys.executable, 'devscripts/make_lazy_extractors.py', 'yt_dlp/extractor/lazy_extractors.py'])
|
subprocess.run([sys.executable, 'devscripts/make_lazy_extractors.py'])
|
||||||
|
|
||||||
|
|
||||||
params = py2exe_params() if sys.argv[1:2] == ['py2exe'] else build_params()
|
params = py2exe_params() if sys.argv[1:2] == ['py2exe'] else build_params()
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
- **8tracks**
|
- **8tracks**
|
||||||
- **91porn**
|
- **91porn**
|
||||||
- **9c9media**
|
- **9c9media**
|
||||||
- **9gag**
|
- **9gag**: 9GAG
|
||||||
- **9now.com.au**
|
- **9now.com.au**
|
||||||
- **abc.net.au**
|
- **abc.net.au**
|
||||||
- **abc.net.au:iview**
|
- **abc.net.au:iview**
|
||||||
@ -64,6 +64,7 @@
|
|||||||
- **AmericasTestKitchenSeason**
|
- **AmericasTestKitchenSeason**
|
||||||
- **AmHistoryChannel**
|
- **AmHistoryChannel**
|
||||||
- **anderetijden**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
- **anderetijden**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
||||||
|
- **Angel**
|
||||||
- **AnimalPlanet**
|
- **AnimalPlanet**
|
||||||
- **AnimeOnDemand**: [<abbr title="netrc machine"><em>animeondemand</em></abbr>]
|
- **AnimeOnDemand**: [<abbr title="netrc machine"><em>animeondemand</em></abbr>]
|
||||||
- **ant1newsgr:article**: ant1news.gr articles
|
- **ant1newsgr:article**: ant1news.gr articles
|
||||||
@ -187,6 +188,7 @@
|
|||||||
- **Camdemy**
|
- **Camdemy**
|
||||||
- **CamdemyFolder**
|
- **CamdemyFolder**
|
||||||
- **CamModels**
|
- **CamModels**
|
||||||
|
- **CamtasiaEmbed**
|
||||||
- **CamWithHer**
|
- **CamWithHer**
|
||||||
- **CanalAlpha**
|
- **CanalAlpha**
|
||||||
- **canalc2.tv**
|
- **canalc2.tv**
|
||||||
@ -232,6 +234,7 @@
|
|||||||
- **Clippit**
|
- **Clippit**
|
||||||
- **ClipRs**
|
- **ClipRs**
|
||||||
- **Clipsyndicate**
|
- **Clipsyndicate**
|
||||||
|
- **ClipYouEmbed**
|
||||||
- **CloserToTruth**
|
- **CloserToTruth**
|
||||||
- **CloudflareStream**
|
- **CloudflareStream**
|
||||||
- **Cloudy**
|
- **Cloudy**
|
||||||
@ -473,6 +476,7 @@
|
|||||||
- **gronkh:feed**
|
- **gronkh:feed**
|
||||||
- **gronkh:vods**
|
- **gronkh:vods**
|
||||||
- **Groupon**
|
- **Groupon**
|
||||||
|
- **Harpodeon**
|
||||||
- **hbo**
|
- **hbo**
|
||||||
- **HearThisAt**
|
- **HearThisAt**
|
||||||
- **Heise**
|
- **Heise**
|
||||||
@ -491,6 +495,7 @@
|
|||||||
- **hitbox:live**
|
- **hitbox:live**
|
||||||
- **HitRecord**
|
- **HitRecord**
|
||||||
- **hketv**: 香港教育局教育電視 (HKETV) Educational Television, Hong Kong Educational Bureau
|
- **hketv**: 香港教育局教育電視 (HKETV) Educational Television, Hong Kong Educational Bureau
|
||||||
|
- **Holodex**
|
||||||
- **HotNewHipHop**
|
- **HotNewHipHop**
|
||||||
- **hotstar**
|
- **hotstar**
|
||||||
- **hotstar:playlist**
|
- **hotstar:playlist**
|
||||||
@ -502,6 +507,7 @@
|
|||||||
- **HRTiPlaylist**: [<abbr title="netrc machine"><em>hrti</em></abbr>]
|
- **HRTiPlaylist**: [<abbr title="netrc machine"><em>hrti</em></abbr>]
|
||||||
- **HSEProduct**
|
- **HSEProduct**
|
||||||
- **HSEShow**
|
- **HSEShow**
|
||||||
|
- **html5**
|
||||||
- **Huajiao**: 花椒直播
|
- **Huajiao**: 花椒直播
|
||||||
- **HuffPost**: Huffington Post
|
- **HuffPost**: Huffington Post
|
||||||
- **Hungama**
|
- **Hungama**
|
||||||
@ -573,6 +579,7 @@
|
|||||||
- **KickStarter**
|
- **KickStarter**
|
||||||
- **KinjaEmbed**
|
- **KinjaEmbed**
|
||||||
- **KinoPoisk**
|
- **KinoPoisk**
|
||||||
|
- **KompasVideo**
|
||||||
- **KonserthusetPlay**
|
- **KonserthusetPlay**
|
||||||
- **Koo**
|
- **Koo**
|
||||||
- **KrasView**: Красвью
|
- **KrasView**: Красвью
|
||||||
@ -715,6 +722,7 @@
|
|||||||
- **Motherless**
|
- **Motherless**
|
||||||
- **MotherlessGroup**
|
- **MotherlessGroup**
|
||||||
- **Motorsport**: motorsport.com
|
- **Motorsport**: motorsport.com
|
||||||
|
- **MotorTrend**
|
||||||
- **MovieClips**
|
- **MovieClips**
|
||||||
- **MovieFap**
|
- **MovieFap**
|
||||||
- **Moviepilot**
|
- **Moviepilot**
|
||||||
@ -890,21 +898,10 @@
|
|||||||
- **openrec:capture**
|
- **openrec:capture**
|
||||||
- **openrec:movie**
|
- **openrec:movie**
|
||||||
- **OraTV**
|
- **OraTV**
|
||||||
- **orf:burgenland**: Radio Burgenland
|
|
||||||
- **orf:fm4**: radio FM4
|
|
||||||
- **orf:fm4:story**: fm4.orf.at stories
|
- **orf:fm4:story**: fm4.orf.at stories
|
||||||
- **orf:iptv**: iptv.ORF.at
|
- **orf:iptv**: iptv.ORF.at
|
||||||
- **orf:kaernten**: Radio Kärnten
|
- **orf:radio**
|
||||||
- **orf:noe**: Radio Niederösterreich
|
|
||||||
- **orf:oberoesterreich**: Radio Oberösterreich
|
|
||||||
- **orf:oe1**: Radio Österreich 1
|
|
||||||
- **orf:oe3**: Radio Österreich 3
|
|
||||||
- **orf:salzburg**: Radio Salzburg
|
|
||||||
- **orf:steiermark**: Radio Steiermark
|
|
||||||
- **orf:tirol**: Radio Tirol
|
|
||||||
- **orf:tvthek**: ORF TVthek
|
- **orf:tvthek**: ORF TVthek
|
||||||
- **orf:vorarlberg**: Radio Vorarlberg
|
|
||||||
- **orf:wien**: Radio Wien
|
|
||||||
- **OsnatelTV**: [<abbr title="netrc machine"><em>osnateltv</em></abbr>]
|
- **OsnatelTV**: [<abbr title="netrc machine"><em>osnateltv</em></abbr>]
|
||||||
- **OutsideTV**
|
- **OutsideTV**
|
||||||
- **PacktPub**: [<abbr title="netrc machine"><em>packtpub</em></abbr>]
|
- **PacktPub**: [<abbr title="netrc machine"><em>packtpub</em></abbr>]
|
||||||
@ -922,7 +919,7 @@
|
|||||||
- **parliamentlive.tv**: UK parliament videos
|
- **parliamentlive.tv**: UK parliament videos
|
||||||
- **Parlview**
|
- **Parlview**
|
||||||
- **Patreon**
|
- **Patreon**
|
||||||
- **PatreonUser**
|
- **PatreonCampaign**
|
||||||
- **pbs**: Public Broadcasting Service (PBS) and member stations: PBS: Public Broadcasting Service, APT - Alabama Public Television (WBIQ), GPB/Georgia Public Broadcasting (WGTV), Mississippi Public Broadcasting (WMPN), Nashville Public Television (WNPT), WFSU-TV (WFSU), WSRE (WSRE), WTCI (WTCI), WPBA/Channel 30 (WPBA), Alaska Public Media (KAKM), Arizona PBS (KAET), KNME-TV/Channel 5 (KNME), Vegas PBS (KLVX), AETN/ARKANSAS ETV NETWORK (KETS), KET (WKLE), WKNO/Channel 10 (WKNO), LPB/LOUISIANA PUBLIC BROADCASTING (WLPB), OETA (KETA), Ozarks Public Television (KOZK), WSIU Public Broadcasting (WSIU), KEET TV (KEET), KIXE/Channel 9 (KIXE), KPBS San Diego (KPBS), KQED (KQED), KVIE Public Television (KVIE), PBS SoCal/KOCE (KOCE), ValleyPBS (KVPT), CONNECTICUT PUBLIC TELEVISION (WEDH), KNPB Channel 5 (KNPB), SOPTV (KSYS), Rocky Mountain PBS (KRMA), KENW-TV3 (KENW), KUED Channel 7 (KUED), Wyoming PBS (KCWC), Colorado Public Television / KBDI 12 (KBDI), KBYU-TV (KBYU), Thirteen/WNET New York (WNET), WGBH/Channel 2 (WGBH), WGBY (WGBY), NJTV Public Media NJ (WNJT), WLIW21 (WLIW), mpt/Maryland Public Television (WMPB), WETA Television and Radio (WETA), WHYY (WHYY), PBS 39 (WLVT), WVPT - Your Source for PBS and More! (WVPT), Howard University Television (WHUT), WEDU PBS (WEDU), WGCU Public Media (WGCU), WPBT2 (WPBT), WUCF TV (WUCF), WUFT/Channel 5 (WUFT), WXEL/Channel 42 (WXEL), WLRN/Channel 17 (WLRN), WUSF Public Broadcasting (WUSF), ETV (WRLK), UNC-TV (WUNC), PBS Hawaii - Oceanic Cable Channel 10 (KHET), Idaho Public Television (KAID), KSPS (KSPS), OPB (KOPB), KWSU/Channel 10 & KTNW/Channel 31 (KWSU), WILL-TV (WILL), Network Knowledge - WSEC/Springfield (WSEC), WTTW11 (WTTW), Iowa Public Television/IPTV (KDIN), Nine Network (KETC), PBS39 Fort Wayne (WFWA), WFYI Indianapolis (WFYI), Milwaukee Public Television (WMVS), WNIN (WNIN), WNIT Public Television (WNIT), WPT (WPNE), WVUT/Channel 22 (WVUT), WEIU/Channel 51 (WEIU), WQPT-TV (WQPT), WYCC PBS Chicago (WYCC), WIPB-TV (WIPB), WTIU (WTIU), CET (WCET), ThinkTVNetwork (WPTD), WBGU-TV (WBGU), WGVU TV (WGVU), NET1 (KUON), Pioneer Public Television (KWCM), SDPB Television (KUSD), TPT (KTCA), KSMQ (KSMQ), KPTS/Channel 8 (KPTS), KTWU/Channel 11 (KTWU), East Tennessee PBS (WSJK), WCTE-TV (WCTE), WLJT, Channel 11 (WLJT), WOSU TV (WOSU), WOUB/WOUC (WOUB), WVPB (WVPB), WKYU-PBS (WKYU), KERA 13 (KERA), MPBN (WCBB), Mountain Lake PBS (WCFE), NHPTV (WENH), Vermont PBS (WETK), witf (WITF), WQED Multimedia (WQED), WMHT Educational Telecommunications (WMHT), Q-TV (WDCQ), WTVS Detroit Public TV (WTVS), CMU Public Television (WCMU), WKAR-TV (WKAR), WNMU-TV Public TV 13 (WNMU), WDSE - WRPT (WDSE), WGTE TV (WGTE), Lakeland Public Television (KAWE), KMOS-TV - Channels 6.1, 6.2 and 6.3 (KMOS), MontanaPBS (KUSM), KRWG/Channel 22 (KRWG), KACV (KACV), KCOS/Channel 13 (KCOS), WCNY/Channel 24 (WCNY), WNED (WNED), WPBS (WPBS), WSKG Public TV (WSKG), WXXI (WXXI), WPSU (WPSU), WVIA Public Media Studios (WVIA), WTVI (WTVI), Western Reserve PBS (WNEO), WVIZ/PBS ideastream (WVIZ), KCTS 9 (KCTS), Basin PBS (KPBT), KUHT / Channel 8 (KUHT), KLRN (KLRN), KLRU (KLRU), WTJX Channel 12 (WTJX), WCVE PBS (WCVE), KBTC Public Television (KBTC)
|
- **pbs**: Public Broadcasting Service (PBS) and member stations: PBS: Public Broadcasting Service, APT - Alabama Public Television (WBIQ), GPB/Georgia Public Broadcasting (WGTV), Mississippi Public Broadcasting (WMPN), Nashville Public Television (WNPT), WFSU-TV (WFSU), WSRE (WSRE), WTCI (WTCI), WPBA/Channel 30 (WPBA), Alaska Public Media (KAKM), Arizona PBS (KAET), KNME-TV/Channel 5 (KNME), Vegas PBS (KLVX), AETN/ARKANSAS ETV NETWORK (KETS), KET (WKLE), WKNO/Channel 10 (WKNO), LPB/LOUISIANA PUBLIC BROADCASTING (WLPB), OETA (KETA), Ozarks Public Television (KOZK), WSIU Public Broadcasting (WSIU), KEET TV (KEET), KIXE/Channel 9 (KIXE), KPBS San Diego (KPBS), KQED (KQED), KVIE Public Television (KVIE), PBS SoCal/KOCE (KOCE), ValleyPBS (KVPT), CONNECTICUT PUBLIC TELEVISION (WEDH), KNPB Channel 5 (KNPB), SOPTV (KSYS), Rocky Mountain PBS (KRMA), KENW-TV3 (KENW), KUED Channel 7 (KUED), Wyoming PBS (KCWC), Colorado Public Television / KBDI 12 (KBDI), KBYU-TV (KBYU), Thirteen/WNET New York (WNET), WGBH/Channel 2 (WGBH), WGBY (WGBY), NJTV Public Media NJ (WNJT), WLIW21 (WLIW), mpt/Maryland Public Television (WMPB), WETA Television and Radio (WETA), WHYY (WHYY), PBS 39 (WLVT), WVPT - Your Source for PBS and More! (WVPT), Howard University Television (WHUT), WEDU PBS (WEDU), WGCU Public Media (WGCU), WPBT2 (WPBT), WUCF TV (WUCF), WUFT/Channel 5 (WUFT), WXEL/Channel 42 (WXEL), WLRN/Channel 17 (WLRN), WUSF Public Broadcasting (WUSF), ETV (WRLK), UNC-TV (WUNC), PBS Hawaii - Oceanic Cable Channel 10 (KHET), Idaho Public Television (KAID), KSPS (KSPS), OPB (KOPB), KWSU/Channel 10 & KTNW/Channel 31 (KWSU), WILL-TV (WILL), Network Knowledge - WSEC/Springfield (WSEC), WTTW11 (WTTW), Iowa Public Television/IPTV (KDIN), Nine Network (KETC), PBS39 Fort Wayne (WFWA), WFYI Indianapolis (WFYI), Milwaukee Public Television (WMVS), WNIN (WNIN), WNIT Public Television (WNIT), WPT (WPNE), WVUT/Channel 22 (WVUT), WEIU/Channel 51 (WEIU), WQPT-TV (WQPT), WYCC PBS Chicago (WYCC), WIPB-TV (WIPB), WTIU (WTIU), CET (WCET), ThinkTVNetwork (WPTD), WBGU-TV (WBGU), WGVU TV (WGVU), NET1 (KUON), Pioneer Public Television (KWCM), SDPB Television (KUSD), TPT (KTCA), KSMQ (KSMQ), KPTS/Channel 8 (KPTS), KTWU/Channel 11 (KTWU), East Tennessee PBS (WSJK), WCTE-TV (WCTE), WLJT, Channel 11 (WLJT), WOSU TV (WOSU), WOUB/WOUC (WOUB), WVPB (WVPB), WKYU-PBS (WKYU), KERA 13 (KERA), MPBN (WCBB), Mountain Lake PBS (WCFE), NHPTV (WENH), Vermont PBS (WETK), witf (WITF), WQED Multimedia (WQED), WMHT Educational Telecommunications (WMHT), Q-TV (WDCQ), WTVS Detroit Public TV (WTVS), CMU Public Television (WCMU), WKAR-TV (WKAR), WNMU-TV Public TV 13 (WNMU), WDSE - WRPT (WDSE), WGTE TV (WGTE), Lakeland Public Television (KAWE), KMOS-TV - Channels 6.1, 6.2 and 6.3 (KMOS), MontanaPBS (KUSM), KRWG/Channel 22 (KRWG), KACV (KACV), KCOS/Channel 13 (KCOS), WCNY/Channel 24 (WCNY), WNED (WNED), WPBS (WPBS), WSKG Public TV (WSKG), WXXI (WXXI), WPSU (WPSU), WVIA Public Media Studios (WVIA), WTVI (WTVI), Western Reserve PBS (WNEO), WVIZ/PBS ideastream (WVIZ), KCTS 9 (KCTS), Basin PBS (KPBT), KUHT / Channel 8 (KUHT), KLRN (KLRN), KLRU (KLRU), WTJX Channel 12 (WTJX), WCVE PBS (WCVE), KBTC Public Television (KBTC)
|
||||||
- **PearVideo**
|
- **PearVideo**
|
||||||
- **PeekVids**
|
- **PeekVids**
|
||||||
@ -1030,12 +1027,14 @@
|
|||||||
- **radlive:channel**
|
- **radlive:channel**
|
||||||
- **radlive:season**
|
- **radlive:season**
|
||||||
- **Rai**
|
- **Rai**
|
||||||
|
- **RaiNews**
|
||||||
- **RaiPlay**
|
- **RaiPlay**
|
||||||
- **RaiPlayLive**
|
- **RaiPlayLive**
|
||||||
- **RaiPlayPlaylist**
|
- **RaiPlayPlaylist**
|
||||||
- **RaiPlaySound**
|
- **RaiPlaySound**
|
||||||
- **RaiPlaySoundLive**
|
- **RaiPlaySoundLive**
|
||||||
- **RaiPlaySoundPlaylist**
|
- **RaiPlaySoundPlaylist**
|
||||||
|
- **RaiSudtirol**
|
||||||
- **RayWenderlich**
|
- **RayWenderlich**
|
||||||
- **RayWenderlichCourse**
|
- **RayWenderlichCourse**
|
||||||
- **RBMARadio**
|
- **RBMARadio**
|
||||||
@ -1072,7 +1071,7 @@
|
|||||||
- **RoosterTeethSeries**: [<abbr title="netrc machine"><em>roosterteeth</em></abbr>]
|
- **RoosterTeethSeries**: [<abbr title="netrc machine"><em>roosterteeth</em></abbr>]
|
||||||
- **RottenTomatoes**
|
- **RottenTomatoes**
|
||||||
- **Rozhlas**
|
- **Rozhlas**
|
||||||
- **RTBF**
|
- **RTBF**: [<abbr title="netrc machine"><em>rtbf</em></abbr>]
|
||||||
- **RTDocumentry**
|
- **RTDocumentry**
|
||||||
- **RTDocumentryPlaylist**
|
- **RTDocumentryPlaylist**
|
||||||
- **rte**: Raidió Teilifís Éireann TV
|
- **rte**: Raidió Teilifís Éireann TV
|
||||||
@ -1144,6 +1143,7 @@
|
|||||||
- **Shahid**: [<abbr title="netrc machine"><em>shahid</em></abbr>]
|
- **Shahid**: [<abbr title="netrc machine"><em>shahid</em></abbr>]
|
||||||
- **ShahidShow**
|
- **ShahidShow**
|
||||||
- **Shared**: shared.sx
|
- **Shared**: shared.sx
|
||||||
|
- **ShareVideosEmbed**
|
||||||
- **ShemarooMe**
|
- **ShemarooMe**
|
||||||
- **ShowRoomLive**
|
- **ShowRoomLive**
|
||||||
- **simplecast**
|
- **simplecast**
|
||||||
@ -1268,6 +1268,7 @@
|
|||||||
- **TeleQuebecVideo**
|
- **TeleQuebecVideo**
|
||||||
- **TeleTask**
|
- **TeleTask**
|
||||||
- **Telewebion**
|
- **Telewebion**
|
||||||
|
- **Tempo**
|
||||||
- **TennisTV**: [<abbr title="netrc machine"><em>tennistv</em></abbr>]
|
- **TennisTV**: [<abbr title="netrc machine"><em>tennistv</em></abbr>]
|
||||||
- **TenPlay**: [<abbr title="netrc machine"><em>10play</em></abbr>]
|
- **TenPlay**: [<abbr title="netrc machine"><em>10play</em></abbr>]
|
||||||
- **TF1**
|
- **TF1**
|
||||||
|
@ -144,7 +144,7 @@ from .utils import (
|
|||||||
write_json_file,
|
write_json_file,
|
||||||
write_string,
|
write_string,
|
||||||
)
|
)
|
||||||
from .version import RELEASE_GIT_HEAD, __version__
|
from .version import RELEASE_GIT_HEAD, VARIANT, __version__
|
||||||
|
|
||||||
if compat_os_name == 'nt':
|
if compat_os_name == 'nt':
|
||||||
import ctypes
|
import ctypes
|
||||||
@ -1797,6 +1797,8 @@ class YoutubeDL:
|
|||||||
})
|
})
|
||||||
|
|
||||||
if self._match_entry(entry_copy, incomplete=True) is not None:
|
if self._match_entry(entry_copy, incomplete=True) is not None:
|
||||||
|
# For compatabilty with youtube-dl. See https://github.com/yt-dlp/yt-dlp/issues/4369
|
||||||
|
resolved_entries[i] = (playlist_index, NO_DEFAULT)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.to_screen('[download] Downloading video %s of %s' % (
|
self.to_screen('[download] Downloading video %s of %s' % (
|
||||||
@ -1817,7 +1819,8 @@ class YoutubeDL:
|
|||||||
resolved_entries[i] = (playlist_index, entry_result)
|
resolved_entries[i] = (playlist_index, entry_result)
|
||||||
|
|
||||||
# Update with processed data
|
# Update with processed data
|
||||||
ie_result['requested_entries'], ie_result['entries'] = tuple(zip(*resolved_entries)) or ([], [])
|
ie_result['requested_entries'] = [i for i, e in resolved_entries if e is not NO_DEFAULT]
|
||||||
|
ie_result['entries'] = [e for _, e in resolved_entries if e is not NO_DEFAULT]
|
||||||
|
|
||||||
# Write the updated info to json
|
# Write the updated info to json
|
||||||
if _infojson_written is True and self._write_info_json(
|
if _infojson_written is True and self._write_info_json(
|
||||||
@ -3676,6 +3679,8 @@ class YoutubeDL:
|
|||||||
write_debug = lambda msg: self._write_string(f'[debug] {msg}\n')
|
write_debug = lambda msg: self._write_string(f'[debug] {msg}\n')
|
||||||
|
|
||||||
source = detect_variant()
|
source = detect_variant()
|
||||||
|
if VARIANT not in (None, 'pip'):
|
||||||
|
source += '*'
|
||||||
write_debug(join_nonempty(
|
write_debug(join_nonempty(
|
||||||
'yt-dlp version', __version__,
|
'yt-dlp version', __version__,
|
||||||
f'[{RELEASE_GIT_HEAD}]' if RELEASE_GIT_HEAD else '',
|
f'[{RELEASE_GIT_HEAD}]' if RELEASE_GIT_HEAD else '',
|
||||||
|
@ -631,6 +631,7 @@ from .gronkh import (
|
|||||||
GronkhVodsIE
|
GronkhVodsIE
|
||||||
)
|
)
|
||||||
from .groupon import GrouponIE
|
from .groupon import GrouponIE
|
||||||
|
from .harpodeon import HarpodeonIE
|
||||||
from .hbo import HBOIE
|
from .hbo import HBOIE
|
||||||
from .hearthisat import HearThisAtIE
|
from .hearthisat import HearThisAtIE
|
||||||
from .heise import HeiseIE
|
from .heise import HeiseIE
|
||||||
@ -1235,7 +1236,6 @@ from .paramountplus import (
|
|||||||
ParamountPlusIE,
|
ParamountPlusIE,
|
||||||
ParamountPlusSeriesIE,
|
ParamountPlusSeriesIE,
|
||||||
)
|
)
|
||||||
from .parliamentliveuk import ParliamentLiveUKIE
|
|
||||||
from .parlview import ParlviewIE
|
from .parlview import ParlviewIE
|
||||||
from .patreon import (
|
from .patreon import (
|
||||||
PatreonIE,
|
PatreonIE,
|
||||||
@ -1406,6 +1406,7 @@ from .rcti import (
|
|||||||
RCTIPlusTVIE,
|
RCTIPlusTVIE,
|
||||||
)
|
)
|
||||||
from .rds import RDSIE
|
from .rds import RDSIE
|
||||||
|
from .redbee import ParliamentLiveUKIE, RTBFIE
|
||||||
from .redbulltv import (
|
from .redbulltv import (
|
||||||
RedBullTVIE,
|
RedBullTVIE,
|
||||||
RedBullEmbedIE,
|
RedBullEmbedIE,
|
||||||
@ -1439,7 +1440,6 @@ from .rokfin import (
|
|||||||
from .roosterteeth import RoosterTeethIE, RoosterTeethSeriesIE
|
from .roosterteeth import RoosterTeethIE, RoosterTeethSeriesIE
|
||||||
from .rottentomatoes import RottenTomatoesIE
|
from .rottentomatoes import RottenTomatoesIE
|
||||||
from .rozhlas import RozhlasIE
|
from .rozhlas import RozhlasIE
|
||||||
from .rtbf import RTBFIE
|
|
||||||
from .rte import RteIE, RteRadioIE
|
from .rte import RteIE, RteRadioIE
|
||||||
from .rtlnl import (
|
from .rtlnl import (
|
||||||
RtlNlIE,
|
RtlNlIE,
|
||||||
|
70
yt_dlp/extractor/harpodeon.py
Normal file
70
yt_dlp/extractor/harpodeon.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import unified_strdate
|
||||||
|
|
||||||
|
|
||||||
|
class HarpodeonIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?harpodeon\.com/(?:video|preview)/\w+/(?P<id>\d+)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.harpodeon.com/video/The_Smoking_Out_of_Bella_Butts/268068288',
|
||||||
|
'md5': '727371564a6a9ebccef2073535b5b6bd',
|
||||||
|
'skip': 'Free video could become unavailable',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '268068288',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'The Smoking Out of Bella Butts',
|
||||||
|
'description': 'md5:47e16bdb41fc8a79c83ab83af11c8b77',
|
||||||
|
'creator': 'Vitagraph Company of America',
|
||||||
|
'release_date': '19150101'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.harpodeon.com/preview/The_Smoking_Out_of_Bella_Butts/268068288',
|
||||||
|
'md5': '6dfea5412845f690c7331be703f884db',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '268068288',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'The Smoking Out of Bella Butts',
|
||||||
|
'description': 'md5:47e16bdb41fc8a79c83ab83af11c8b77',
|
||||||
|
'creator': 'Vitagraph Company of America',
|
||||||
|
'release_date': '19150101'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.harpodeon.com/preview/Behind_the_Screen/421838710',
|
||||||
|
'md5': '7979df9ca04637282cb7d172ab3a9c3b',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '421838710',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Behind the Screen',
|
||||||
|
'description': 'md5:008972a3dc51fba3965ee517d2ba9155',
|
||||||
|
'creator': 'Lone Star Corporation',
|
||||||
|
'release_date': '19160101'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
|
title, creator, release_year = self._search_regex(
|
||||||
|
r'''(?x)
|
||||||
|
<div[^>]+videoInfo[^<]*<h2[^>]*>(?P<title>[^>]+)</h2>
|
||||||
|
(?:\s*<p[^>]*>\((?P<creator>.+),\s*)?(?P<release_year>\d{4})?''',
|
||||||
|
webpage, 'title', group=('title', 'creator', 'release_year'),
|
||||||
|
fatal=False) or (None, None, None)
|
||||||
|
|
||||||
|
hp_base = self._html_search_regex(r'hpBase\(\s*["\']([^"\']+)', webpage, 'hp_base')
|
||||||
|
|
||||||
|
hp_inject_video, hp_resolution = self._search_regex(
|
||||||
|
r'''(?x)
|
||||||
|
hpInjectVideo\([\'\"](?P<hp_inject_video>\w+)[\'\"],
|
||||||
|
[\'\"](?P<hp_resolution>\d+)[\'\"]''',
|
||||||
|
webpage, 'hp_inject_video', group=['hp_inject_video', 'hp_resolution'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
'url': f'{hp_base}{hp_inject_video}_{hp_resolution}.mp4',
|
||||||
|
'http_headers': {'Referer': url},
|
||||||
|
'description': self._html_search_meta('description', webpage, fatal=False),
|
||||||
|
'creator': creator,
|
||||||
|
'release_date': unified_strdate(f'{release_year}0101')
|
||||||
|
}
|
@ -141,6 +141,10 @@ class MediasetIE(ThePlatformBaseIE):
|
|||||||
# iframe twitter (from http://www.wittytv.it/se-prima-mi-fidavo-zero/)
|
# iframe twitter (from http://www.wittytv.it/se-prima-mi-fidavo-zero/)
|
||||||
'url': 'https://static3.mediasetplay.mediaset.it/player/index.html?appKey=5ad3966b1de1c4000d5cec48&programGuid=FAFU000000665104&id=665104',
|
'url': 'https://static3.mediasetplay.mediaset.it/player/index.html?appKey=5ad3966b1de1c4000d5cec48&programGuid=FAFU000000665104&id=665104',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# embedUrl (from https://www.wittytv.it/amici/est-ce-que-tu-maimes-gabriele-5-dicembre-copia/)
|
||||||
|
'url': 'https://static3.mediasetplay.mediaset.it/player/v2/index.html?partnerId=wittytv&configId=&programGuid=FD00000000153323&autoplay=true&purl=http://www.wittytv.it/amici/est-ce-que-tu-maimes-gabriele-5-dicembre-copia/',
|
||||||
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'mediaset:FAFU000000665924',
|
'url': 'mediaset:FAFU000000665924',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
import json
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from .common import InfoExtractor
|
|
||||||
from ..utils import (
|
|
||||||
unified_timestamp,
|
|
||||||
try_get,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ParliamentLiveUKIE(InfoExtractor):
|
|
||||||
IE_NAME = 'parliamentlive.tv'
|
|
||||||
IE_DESC = 'UK parliament videos'
|
|
||||||
_VALID_URL = r'(?i)https?://(?:www\.)?parliamentlive\.tv/Event/Index/(?P<id>[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})'
|
|
||||||
|
|
||||||
_TESTS = [{
|
|
||||||
'url': 'http://parliamentlive.tv/Event/Index/c1e9d44d-fd6c-4263-b50f-97ed26cc998b',
|
|
||||||
'info_dict': {
|
|
||||||
'id': 'c1e9d44d-fd6c-4263-b50f-97ed26cc998b',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Home Affairs Committee',
|
|
||||||
'timestamp': 1395153872,
|
|
||||||
'upload_date': '20140318',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
'url': 'http://parliamentlive.tv/event/index/3f24936f-130f-40bf-9a5d-b3d6479da6a4',
|
|
||||||
'only_matching': True,
|
|
||||||
}]
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
|
||||||
video_id = self._match_id(url)
|
|
||||||
video_info = self._download_json(f'https://www.parliamentlive.tv/Event/GetShareVideo/{video_id}', video_id)
|
|
||||||
_DEVICE_ID = str(uuid.uuid4())
|
|
||||||
auth = 'Bearer ' + self._download_json(
|
|
||||||
'https://exposure.api.redbee.live/v2/customer/UKParliament/businessunit/ParliamentLive/auth/anonymous',
|
|
||||||
video_id, headers={
|
|
||||||
'Origin': 'https://videoplayback.parliamentlive.tv',
|
|
||||||
'Accept': 'application/json, text/plain, */*',
|
|
||||||
'Content-Type': 'application/json;charset=utf-8'
|
|
||||||
}, data=json.dumps({
|
|
||||||
'deviceId': _DEVICE_ID,
|
|
||||||
'device': {
|
|
||||||
'deviceId': _DEVICE_ID,
|
|
||||||
'width': 653,
|
|
||||||
'height': 368,
|
|
||||||
'type': 'WEB',
|
|
||||||
'name': ' Mozilla Firefox 91'
|
|
||||||
}
|
|
||||||
}).encode('utf-8'))['sessionToken']
|
|
||||||
|
|
||||||
video_urls = self._download_json(
|
|
||||||
f'https://exposure.api.redbee.live/v2/customer/UKParliament/businessunit/ParliamentLive/entitlement/{video_id}/play',
|
|
||||||
video_id, headers={'Authorization': auth, 'Accept': 'application/json, text/plain, */*'})['formats']
|
|
||||||
|
|
||||||
formats = []
|
|
||||||
for format in video_urls:
|
|
||||||
if not format.get('mediaLocator'):
|
|
||||||
continue
|
|
||||||
if format.get('format') == 'DASH':
|
|
||||||
formats.extend(self._extract_mpd_formats(
|
|
||||||
format['mediaLocator'], video_id, mpd_id='dash', fatal=False))
|
|
||||||
elif format.get('format') == 'SMOOTHSTREAMING':
|
|
||||||
formats.extend(self._extract_ism_formats(
|
|
||||||
format['mediaLocator'], video_id, ism_id='ism', fatal=False))
|
|
||||||
elif format.get('format') == 'HLS':
|
|
||||||
formats.extend(self._extract_m3u8_formats(
|
|
||||||
format['mediaLocator'], video_id, m3u8_id='hls', fatal=False))
|
|
||||||
|
|
||||||
self._sort_formats(formats)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'id': video_id,
|
|
||||||
'formats': formats,
|
|
||||||
'title': video_info['event']['title'],
|
|
||||||
'timestamp': unified_timestamp(try_get(video_info, lambda x: x['event']['publishedStartTime'])),
|
|
||||||
'thumbnail': video_info.get('thumbnailUrl'),
|
|
||||||
}
|
|
361
yt_dlp/extractor/redbee.py
Normal file
361
yt_dlp/extractor/redbee.py
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
import json
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
float_or_none,
|
||||||
|
int_or_none,
|
||||||
|
strip_or_none,
|
||||||
|
traverse_obj,
|
||||||
|
unified_timestamp,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RedBeeBaseIE(InfoExtractor):
|
||||||
|
_DEVICE_ID = str(uuid.uuid4())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _API_URL(self):
|
||||||
|
"""
|
||||||
|
Ref: https://apidocs.emp.ebsd.ericsson.net
|
||||||
|
Subclasses must set _REDBEE_CUSTOMER, _REDBEE_BUSINESS_UNIT
|
||||||
|
"""
|
||||||
|
return f'https://exposure.api.redbee.live/v2/customer/{self._REDBEE_CUSTOMER}/businessunit/{self._REDBEE_BUSINESS_UNIT}'
|
||||||
|
|
||||||
|
def _get_bearer_token(self, asset_id, jwt=None):
|
||||||
|
request = {
|
||||||
|
'deviceId': self._DEVICE_ID,
|
||||||
|
'device': {
|
||||||
|
'deviceId': self._DEVICE_ID,
|
||||||
|
'name': 'Mozilla Firefox 102',
|
||||||
|
'type': 'WEB',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if jwt:
|
||||||
|
request['jwt'] = jwt
|
||||||
|
|
||||||
|
return self._download_json(
|
||||||
|
f'{self._API_URL}/auth/{"gigyaLogin" if jwt else "anonymous"}',
|
||||||
|
asset_id, data=json.dumps(request).encode('utf-8'), headers={
|
||||||
|
'Content-Type': 'application/json;charset=utf-8'
|
||||||
|
})['sessionToken']
|
||||||
|
|
||||||
|
def _get_formats_and_subtitles(self, asset_id, **kwargs):
|
||||||
|
bearer_token = self._get_bearer_token(asset_id, **kwargs)
|
||||||
|
api_response = self._download_json(
|
||||||
|
f'{self._API_URL}/entitlement/{asset_id}/play',
|
||||||
|
asset_id, headers={
|
||||||
|
'Authorization': f'Bearer {bearer_token}',
|
||||||
|
'Accept': 'application/json, text/plain, */*'
|
||||||
|
})
|
||||||
|
|
||||||
|
formats, subtitles = [], {}
|
||||||
|
for format in api_response['formats']:
|
||||||
|
if not format.get('mediaLocator'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
fmts, subs = [], {}
|
||||||
|
if format.get('format') == 'DASH':
|
||||||
|
fmts, subs = self._extract_mpd_formats_and_subtitles(
|
||||||
|
format['mediaLocator'], asset_id, fatal=False)
|
||||||
|
elif format.get('format') == 'SMOOTHSTREAMING':
|
||||||
|
fmts, subs = self._extract_ism_formats_and_subtitles(
|
||||||
|
format['mediaLocator'], asset_id, fatal=False)
|
||||||
|
elif format.get('format') == 'HLS':
|
||||||
|
fmts, subs = self._extract_m3u8_formats_and_subtitles(
|
||||||
|
format['mediaLocator'], asset_id, fatal=False)
|
||||||
|
|
||||||
|
formats.extend(fmts)
|
||||||
|
self._merge_subtitles(subs, target=subtitles)
|
||||||
|
|
||||||
|
return formats, subtitles
|
||||||
|
|
||||||
|
|
||||||
|
class ParliamentLiveUKIE(RedBeeBaseIE):
|
||||||
|
IE_NAME = 'parliamentlive.tv'
|
||||||
|
IE_DESC = 'UK parliament videos'
|
||||||
|
_VALID_URL = r'(?i)https?://(?:www\.)?parliamentlive\.tv/Event/Index/(?P<id>[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})'
|
||||||
|
|
||||||
|
_REDBEE_CUSTOMER = 'UKParliament'
|
||||||
|
_REDBEE_BUSINESS_UNIT = 'ParliamentLive'
|
||||||
|
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'http://parliamentlive.tv/Event/Index/c1e9d44d-fd6c-4263-b50f-97ed26cc998b',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'c1e9d44d-fd6c-4263-b50f-97ed26cc998b',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Home Affairs Committee',
|
||||||
|
'timestamp': 1395153872,
|
||||||
|
'upload_date': '20140318',
|
||||||
|
'thumbnail': r're:https?://[^?#]+c1e9d44d-fd6c-4263-b50f-97ed26cc998b[^/]*/thumbnail',
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'http://parliamentlive.tv/event/index/3f24936f-130f-40bf-9a5d-b3d6479da6a4',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://parliamentlive.tv/Event/Index/27cf25e4-e77b-42a3-93c5-c815cd6d7377',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '27cf25e4-e77b-42a3-93c5-c815cd6d7377',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'House of Commons',
|
||||||
|
'timestamp': 1658392447,
|
||||||
|
'upload_date': '20220721',
|
||||||
|
'thumbnail': r're:https?://[^?#]+27cf25e4-e77b-42a3-93c5-c815cd6d7377[^/]*/thumbnail',
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
|
formats, subtitles = self._get_formats_and_subtitles(video_id)
|
||||||
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
video_info = self._download_json(
|
||||||
|
f'https://www.parliamentlive.tv/Event/GetShareVideo/{video_id}', video_id, fatal=False)
|
||||||
|
|
||||||
|
self._sort_formats(formats, ['res', 'proto'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_id,
|
||||||
|
'formats': formats,
|
||||||
|
'subtitles': subtitles,
|
||||||
|
'title': traverse_obj(video_info, ('event', 'title')),
|
||||||
|
'thumbnail': traverse_obj(video_info, 'thumbnailUrl'),
|
||||||
|
'timestamp': traverse_obj(
|
||||||
|
video_info, ('event', 'publishedStartTime'), expected_type=unified_timestamp),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RTBFIE(RedBeeBaseIE):
|
||||||
|
_VALID_URL = r'''(?x)
|
||||||
|
https?://(?:www\.)?rtbf\.be/
|
||||||
|
(?:
|
||||||
|
video/[^?]+\?.*\bid=|
|
||||||
|
ouftivi/(?:[^/]+/)*[^?]+\?.*\bvideoId=|
|
||||||
|
auvio/[^/]+\?.*\b(?P<live>l)?id=
|
||||||
|
)(?P<id>\d+)'''
|
||||||
|
_NETRC_MACHINE = 'rtbf'
|
||||||
|
|
||||||
|
_REDBEE_CUSTOMER = 'RTBF'
|
||||||
|
_REDBEE_BUSINESS_UNIT = 'Auvio'
|
||||||
|
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.rtbf.be/video/detail_les-diables-au-coeur-episode-2?id=1921274',
|
||||||
|
'md5': '8c876a1cceeb6cf31b476461ade72384',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '1921274',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Les Diables au coeur (épisode 2)',
|
||||||
|
'description': '(du 25/04/2014)',
|
||||||
|
'duration': 3099.54,
|
||||||
|
'upload_date': '20140425',
|
||||||
|
'timestamp': 1398456300,
|
||||||
|
},
|
||||||
|
'skip': 'No longer available',
|
||||||
|
}, {
|
||||||
|
# geo restricted
|
||||||
|
'url': 'http://www.rtbf.be/ouftivi/heros/detail_scooby-doo-mysteres-associes?id=1097&videoId=2057442',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'http://www.rtbf.be/ouftivi/niouzz?videoId=2055858',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'http://www.rtbf.be/auvio/detail_jeudi-en-prime-siegfried-bracke?id=2102996',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# Live
|
||||||
|
'url': 'https://www.rtbf.be/auvio/direct_pure-fm?lid=134775',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# Audio
|
||||||
|
'url': 'https://www.rtbf.be/auvio/detail_cinq-heures-cinema?id=2360811',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# With Subtitle
|
||||||
|
'url': 'https://www.rtbf.be/auvio/detail_les-carnets-du-bourlingueur?id=2361588',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.rtbf.be/auvio/detail_investigation?id=2921926',
|
||||||
|
'md5': 'd5d11bb62169fef38d7ce7ac531e034f',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '2921926',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Le handicap un confinement perpétuel - Maladie de Lyme',
|
||||||
|
'description': 'md5:dcbd5dcf6015488c9069b057c15ccc52',
|
||||||
|
'duration': 5258.8,
|
||||||
|
'upload_date': '20220727',
|
||||||
|
'timestamp': 1658934000,
|
||||||
|
'series': '#Investigation',
|
||||||
|
'thumbnail': r're:^https?://[^?&]+\.jpg$',
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.rtbf.be/auvio/detail_la-belgique-criminelle?id=2920492',
|
||||||
|
'md5': '054f9f143bc79c89647c35e5a7d35fa8',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '2920492',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': '04 - Le crime de la rue Royale',
|
||||||
|
'description': 'md5:0c3da1efab286df83f2ab3f8f96bd7a6',
|
||||||
|
'duration': 1574.6,
|
||||||
|
'upload_date': '20220723',
|
||||||
|
'timestamp': 1658596887,
|
||||||
|
'series': 'La Belgique criminelle - TV',
|
||||||
|
'thumbnail': r're:^https?://[^?&]+\.jpg$',
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
|
||||||
|
_IMAGE_HOST = 'http://ds1.ds.static.rtbf.be'
|
||||||
|
_PROVIDERS = {
|
||||||
|
'YOUTUBE': 'Youtube',
|
||||||
|
'DAILYMOTION': 'Dailymotion',
|
||||||
|
'VIMEO': 'Vimeo',
|
||||||
|
}
|
||||||
|
_QUALITIES = [
|
||||||
|
('mobile', 'SD'),
|
||||||
|
('web', 'MD'),
|
||||||
|
('high', 'HD'),
|
||||||
|
]
|
||||||
|
_LOGIN_URL = 'https://login.rtbf.be/accounts.login'
|
||||||
|
_GIGYA_API_KEY = '3_kWKuPgcdAybqnqxq_MvHVk0-6PN8Zk8pIIkJM_yXOu-qLPDDsGOtIDFfpGivtbeO'
|
||||||
|
_LOGIN_COOKIE_ID = f'glt_{_GIGYA_API_KEY}'
|
||||||
|
|
||||||
|
def _perform_login(self, username, password):
|
||||||
|
if self._get_cookies(self._LOGIN_URL).get(self._LOGIN_COOKIE_ID):
|
||||||
|
return
|
||||||
|
|
||||||
|
self._set_cookie('.rtbf.be', 'gmid', 'gmid.ver4', secure=True, expire_time=time.time() + 3600)
|
||||||
|
|
||||||
|
login_response = self._download_json(
|
||||||
|
self._LOGIN_URL, None, data=urllib.parse.urlencode({
|
||||||
|
'loginID': username,
|
||||||
|
'password': password,
|
||||||
|
'APIKey': self._GIGYA_API_KEY,
|
||||||
|
'targetEnv': 'jssdk',
|
||||||
|
'sessionExpiration': '-2',
|
||||||
|
}).encode('utf-8'), headers={
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
})
|
||||||
|
|
||||||
|
if login_response['statusCode'] != 200:
|
||||||
|
raise ExtractorError('Login failed. Server message: %s' % login_response['errorMessage'], expected=True)
|
||||||
|
|
||||||
|
self._set_cookie('.rtbf.be', self._LOGIN_COOKIE_ID, login_response['sessionInfo']['login_token'],
|
||||||
|
secure=True, expire_time=time.time() + 3600)
|
||||||
|
|
||||||
|
def _get_formats_and_subtitles(self, url, media_id):
|
||||||
|
login_token = self._get_cookies(url).get(self._LOGIN_COOKIE_ID)
|
||||||
|
if not login_token:
|
||||||
|
self.raise_login_required()
|
||||||
|
|
||||||
|
session_jwt = self._download_json(
|
||||||
|
'https://login.rtbf.be/accounts.getJWT', media_id, query={
|
||||||
|
'login_token': login_token.value,
|
||||||
|
'APIKey': self._GIGYA_API_KEY,
|
||||||
|
'sdk': 'js_latest',
|
||||||
|
'authMode': 'cookie',
|
||||||
|
'pageURL': url,
|
||||||
|
'sdkBuild': '13273',
|
||||||
|
'format': 'json',
|
||||||
|
})['id_token']
|
||||||
|
|
||||||
|
return super()._get_formats_and_subtitles(media_id, jwt=session_jwt)
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
live, media_id = self._match_valid_url(url).groups()
|
||||||
|
embed_page = self._download_webpage(
|
||||||
|
'https://www.rtbf.be/auvio/embed/' + ('direct' if live else 'media'),
|
||||||
|
media_id, query={'id': media_id})
|
||||||
|
data = self._parse_json(self._html_search_regex(
|
||||||
|
r'data-media="([^"]+)"', embed_page, 'media data'), media_id)
|
||||||
|
|
||||||
|
error = data.get('error')
|
||||||
|
if error:
|
||||||
|
raise ExtractorError('%s said: %s' % (self.IE_NAME, error), expected=True)
|
||||||
|
|
||||||
|
provider = data.get('provider')
|
||||||
|
if provider in self._PROVIDERS:
|
||||||
|
return self.url_result(data['url'], self._PROVIDERS[provider])
|
||||||
|
|
||||||
|
title = data['subtitle']
|
||||||
|
is_live = data.get('isLive')
|
||||||
|
height_re = r'-(\d+)p\.'
|
||||||
|
formats = []
|
||||||
|
|
||||||
|
m3u8_url = data.get('urlHlsAes128') or data.get('urlHls')
|
||||||
|
if m3u8_url:
|
||||||
|
formats.extend(self._extract_m3u8_formats(
|
||||||
|
m3u8_url, media_id, 'mp4', m3u8_id='hls', fatal=False))
|
||||||
|
|
||||||
|
fix_url = lambda x: x.replace('//rtbf-vod.', '//rtbf.') if '/geo/drm/' in x else x
|
||||||
|
http_url = data.get('url')
|
||||||
|
if formats and http_url and re.search(height_re, http_url):
|
||||||
|
http_url = fix_url(http_url)
|
||||||
|
for m3u8_f in formats[:]:
|
||||||
|
height = m3u8_f.get('height')
|
||||||
|
if not height:
|
||||||
|
continue
|
||||||
|
f = m3u8_f.copy()
|
||||||
|
del f['protocol']
|
||||||
|
f.update({
|
||||||
|
'format_id': m3u8_f['format_id'].replace('hls-', 'http-'),
|
||||||
|
'url': re.sub(height_re, '-%dp.' % height, http_url),
|
||||||
|
})
|
||||||
|
formats.append(f)
|
||||||
|
else:
|
||||||
|
sources = data.get('sources') or {}
|
||||||
|
for key, format_id in self._QUALITIES:
|
||||||
|
format_url = sources.get(key)
|
||||||
|
if not format_url:
|
||||||
|
continue
|
||||||
|
height = int_or_none(self._search_regex(
|
||||||
|
height_re, format_url, 'height', default=None))
|
||||||
|
formats.append({
|
||||||
|
'format_id': format_id,
|
||||||
|
'url': fix_url(format_url),
|
||||||
|
'height': height,
|
||||||
|
})
|
||||||
|
|
||||||
|
mpd_url = data.get('urlDash')
|
||||||
|
if mpd_url and (self.get_param('allow_unplayable_formats') or not data.get('drm')):
|
||||||
|
formats.extend(self._extract_mpd_formats(
|
||||||
|
mpd_url, media_id, mpd_id='dash', fatal=False))
|
||||||
|
|
||||||
|
audio_url = data.get('urlAudio')
|
||||||
|
if audio_url:
|
||||||
|
formats.append({
|
||||||
|
'format_id': 'audio',
|
||||||
|
'url': audio_url,
|
||||||
|
'vcodec': 'none',
|
||||||
|
})
|
||||||
|
|
||||||
|
subtitles = {}
|
||||||
|
for track in (data.get('tracks') or {}).values():
|
||||||
|
sub_url = track.get('url')
|
||||||
|
if not sub_url:
|
||||||
|
continue
|
||||||
|
subtitles.setdefault(track.get('lang') or 'fr', []).append({
|
||||||
|
'url': sub_url,
|
||||||
|
})
|
||||||
|
|
||||||
|
if not formats:
|
||||||
|
fmts, subs = self._get_formats_and_subtitles(url, media_id)
|
||||||
|
formats.extend(fmts)
|
||||||
|
self._merge_subtitles(subs, target=subtitles)
|
||||||
|
|
||||||
|
self._sort_formats(formats, ['res', 'proto'])
|
||||||
|
return {
|
||||||
|
'id': media_id,
|
||||||
|
'formats': formats,
|
||||||
|
'title': title,
|
||||||
|
'description': strip_or_none(data.get('description')),
|
||||||
|
'thumbnail': data.get('thumbnail'),
|
||||||
|
'duration': float_or_none(data.get('realDuration')),
|
||||||
|
'timestamp': int_or_none(data.get('liveFrom')),
|
||||||
|
'series': data.get('programLabel'),
|
||||||
|
'subtitles': subtitles,
|
||||||
|
'is_live': is_live,
|
||||||
|
}
|
@ -1,156 +0,0 @@
|
|||||||
import re
|
|
||||||
|
|
||||||
from .common import InfoExtractor
|
|
||||||
from ..utils import (
|
|
||||||
ExtractorError,
|
|
||||||
float_or_none,
|
|
||||||
int_or_none,
|
|
||||||
strip_or_none,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RTBFIE(InfoExtractor):
|
|
||||||
_VALID_URL = r'''(?x)
|
|
||||||
https?://(?:www\.)?rtbf\.be/
|
|
||||||
(?:
|
|
||||||
video/[^?]+\?.*\bid=|
|
|
||||||
ouftivi/(?:[^/]+/)*[^?]+\?.*\bvideoId=|
|
|
||||||
auvio/[^/]+\?.*\b(?P<live>l)?id=
|
|
||||||
)(?P<id>\d+)'''
|
|
||||||
_TESTS = [{
|
|
||||||
'url': 'https://www.rtbf.be/video/detail_les-diables-au-coeur-episode-2?id=1921274',
|
|
||||||
'md5': '8c876a1cceeb6cf31b476461ade72384',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '1921274',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Les Diables au coeur (épisode 2)',
|
|
||||||
'description': '(du 25/04/2014)',
|
|
||||||
'duration': 3099.54,
|
|
||||||
'upload_date': '20140425',
|
|
||||||
'timestamp': 1398456300,
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
# geo restricted
|
|
||||||
'url': 'http://www.rtbf.be/ouftivi/heros/detail_scooby-doo-mysteres-associes?id=1097&videoId=2057442',
|
|
||||||
'only_matching': True,
|
|
||||||
}, {
|
|
||||||
'url': 'http://www.rtbf.be/ouftivi/niouzz?videoId=2055858',
|
|
||||||
'only_matching': True,
|
|
||||||
}, {
|
|
||||||
'url': 'http://www.rtbf.be/auvio/detail_jeudi-en-prime-siegfried-bracke?id=2102996',
|
|
||||||
'only_matching': True,
|
|
||||||
}, {
|
|
||||||
# Live
|
|
||||||
'url': 'https://www.rtbf.be/auvio/direct_pure-fm?lid=134775',
|
|
||||||
'only_matching': True,
|
|
||||||
}, {
|
|
||||||
# Audio
|
|
||||||
'url': 'https://www.rtbf.be/auvio/detail_cinq-heures-cinema?id=2360811',
|
|
||||||
'only_matching': True,
|
|
||||||
}, {
|
|
||||||
# With Subtitle
|
|
||||||
'url': 'https://www.rtbf.be/auvio/detail_les-carnets-du-bourlingueur?id=2361588',
|
|
||||||
'only_matching': True,
|
|
||||||
}]
|
|
||||||
_IMAGE_HOST = 'http://ds1.ds.static.rtbf.be'
|
|
||||||
_PROVIDERS = {
|
|
||||||
'YOUTUBE': 'Youtube',
|
|
||||||
'DAILYMOTION': 'Dailymotion',
|
|
||||||
'VIMEO': 'Vimeo',
|
|
||||||
}
|
|
||||||
_QUALITIES = [
|
|
||||||
('mobile', 'SD'),
|
|
||||||
('web', 'MD'),
|
|
||||||
('high', 'HD'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
|
||||||
live, media_id = self._match_valid_url(url).groups()
|
|
||||||
embed_page = self._download_webpage(
|
|
||||||
'https://www.rtbf.be/auvio/embed/' + ('direct' if live else 'media'),
|
|
||||||
media_id, query={'id': media_id})
|
|
||||||
data = self._parse_json(self._html_search_regex(
|
|
||||||
r'data-media="([^"]+)"', embed_page, 'media data'), media_id)
|
|
||||||
|
|
||||||
error = data.get('error')
|
|
||||||
if error:
|
|
||||||
raise ExtractorError('%s said: %s' % (self.IE_NAME, error), expected=True)
|
|
||||||
|
|
||||||
provider = data.get('provider')
|
|
||||||
if provider in self._PROVIDERS:
|
|
||||||
return self.url_result(data['url'], self._PROVIDERS[provider])
|
|
||||||
|
|
||||||
title = data['title']
|
|
||||||
is_live = data.get('isLive')
|
|
||||||
height_re = r'-(\d+)p\.'
|
|
||||||
formats = []
|
|
||||||
|
|
||||||
m3u8_url = data.get('urlHlsAes128') or data.get('urlHls')
|
|
||||||
if m3u8_url:
|
|
||||||
formats.extend(self._extract_m3u8_formats(
|
|
||||||
m3u8_url, media_id, 'mp4', m3u8_id='hls', fatal=False))
|
|
||||||
|
|
||||||
fix_url = lambda x: x.replace('//rtbf-vod.', '//rtbf.') if '/geo/drm/' in x else x
|
|
||||||
http_url = data.get('url')
|
|
||||||
if formats and http_url and re.search(height_re, http_url):
|
|
||||||
http_url = fix_url(http_url)
|
|
||||||
for m3u8_f in formats[:]:
|
|
||||||
height = m3u8_f.get('height')
|
|
||||||
if not height:
|
|
||||||
continue
|
|
||||||
f = m3u8_f.copy()
|
|
||||||
del f['protocol']
|
|
||||||
f.update({
|
|
||||||
'format_id': m3u8_f['format_id'].replace('hls-', 'http-'),
|
|
||||||
'url': re.sub(height_re, '-%dp.' % height, http_url),
|
|
||||||
})
|
|
||||||
formats.append(f)
|
|
||||||
else:
|
|
||||||
sources = data.get('sources') or {}
|
|
||||||
for key, format_id in self._QUALITIES:
|
|
||||||
format_url = sources.get(key)
|
|
||||||
if not format_url:
|
|
||||||
continue
|
|
||||||
height = int_or_none(self._search_regex(
|
|
||||||
height_re, format_url, 'height', default=None))
|
|
||||||
formats.append({
|
|
||||||
'format_id': format_id,
|
|
||||||
'url': fix_url(format_url),
|
|
||||||
'height': height,
|
|
||||||
})
|
|
||||||
|
|
||||||
mpd_url = data.get('urlDash')
|
|
||||||
if mpd_url and (self.get_param('allow_unplayable_formats') or not data.get('drm')):
|
|
||||||
formats.extend(self._extract_mpd_formats(
|
|
||||||
mpd_url, media_id, mpd_id='dash', fatal=False))
|
|
||||||
|
|
||||||
audio_url = data.get('urlAudio')
|
|
||||||
if audio_url:
|
|
||||||
formats.append({
|
|
||||||
'format_id': 'audio',
|
|
||||||
'url': audio_url,
|
|
||||||
'vcodec': 'none',
|
|
||||||
})
|
|
||||||
self._sort_formats(formats)
|
|
||||||
|
|
||||||
subtitles = {}
|
|
||||||
for track in (data.get('tracks') or {}).values():
|
|
||||||
sub_url = track.get('url')
|
|
||||||
if not sub_url:
|
|
||||||
continue
|
|
||||||
subtitles.setdefault(track.get('lang') or 'fr', []).append({
|
|
||||||
'url': sub_url,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
'id': media_id,
|
|
||||||
'formats': formats,
|
|
||||||
'title': title,
|
|
||||||
'description': strip_or_none(data.get('description')),
|
|
||||||
'thumbnail': data.get('thumbnail'),
|
|
||||||
'duration': float_or_none(data.get('realDuration')),
|
|
||||||
'timestamp': int_or_none(data.get('liveFrom')),
|
|
||||||
'series': data.get('programLabel'),
|
|
||||||
'subtitles': subtitles,
|
|
||||||
'is_live': is_live,
|
|
||||||
}
|
|
@ -61,6 +61,18 @@ class VVVVIDIE(InfoExtractor):
|
|||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
# video_type == 'video/dash'
|
||||||
|
'url': 'https://www.vvvvid.it/show/683/made-in-abyss/1542/693786/nanachi',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '693786',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Nanachi',
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': True,
|
||||||
|
'format': 'mp4',
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.vvvvid.it/show/434/perche-dovrei-guardarlo-di-dario-moccia/437/489048',
|
'url': 'https://www.vvvvid.it/show/434/perche-dovrei-guardarlo-di-dario-moccia/437/489048',
|
||||||
'only_matching': True
|
'only_matching': True
|
||||||
@ -202,6 +214,9 @@ class VVVVIDIE(InfoExtractor):
|
|||||||
})
|
})
|
||||||
is_youtube = True
|
is_youtube = True
|
||||||
break
|
break
|
||||||
|
elif video_type == 'video/dash':
|
||||||
|
formats.extend(self._extract_m3u8_formats(
|
||||||
|
embed_code, video_id, 'mp4', m3u8_id='hls', fatal=False))
|
||||||
else:
|
else:
|
||||||
formats.extend(self._extract_wowza_formats(
|
formats.extend(self._extract_wowza_formats(
|
||||||
'http://sb.top-ix.org/videomg/_definst_/mp4:%s/playlist.m3u8' % embed_code, video_id))
|
'http://sb.top-ix.org/videomg/_definst_/mp4:%s/playlist.m3u8' % embed_code, video_id))
|
||||||
|
@ -20,12 +20,13 @@ from .postprocessor import (
|
|||||||
SponsorBlockPP,
|
SponsorBlockPP,
|
||||||
)
|
)
|
||||||
from .postprocessor.modify_chapters import DEFAULT_SPONSORBLOCK_CHAPTER_TITLE
|
from .postprocessor.modify_chapters import DEFAULT_SPONSORBLOCK_CHAPTER_TITLE
|
||||||
from .update import detect_variant
|
from .update import detect_variant, is_non_updateable
|
||||||
from .utils import (
|
from .utils import (
|
||||||
OUTTMPL_TYPES,
|
OUTTMPL_TYPES,
|
||||||
POSTPROCESS_WHEN,
|
POSTPROCESS_WHEN,
|
||||||
Config,
|
Config,
|
||||||
expand_path,
|
expand_path,
|
||||||
|
format_field,
|
||||||
get_executable_path,
|
get_executable_path,
|
||||||
join_nonempty,
|
join_nonempty,
|
||||||
remove_end,
|
remove_end,
|
||||||
@ -333,11 +334,13 @@ def create_parser():
|
|||||||
general.add_option(
|
general.add_option(
|
||||||
'-U', '--update',
|
'-U', '--update',
|
||||||
action='store_true', dest='update_self',
|
action='store_true', dest='update_self',
|
||||||
help='Update this program to latest version')
|
help=format_field(
|
||||||
|
is_non_updateable(), None, 'Check if updates are available. %s',
|
||||||
|
default='Update this program to the latest version'))
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'--no-update',
|
'--no-update',
|
||||||
action='store_false', dest='update_self',
|
action='store_false', dest='update_self',
|
||||||
help='Do not update (default)')
|
help='Do not check for updates (default)')
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'-i', '--ignore-errors',
|
'-i', '--ignore-errors',
|
||||||
action='store_true', dest='ignoreerrors',
|
action='store_true', dest='ignoreerrors',
|
||||||
|
@ -109,7 +109,8 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
return {p: p for p in programs}
|
return {p: p for p in programs}
|
||||||
|
|
||||||
if not os.path.exists(location):
|
if not os.path.exists(location):
|
||||||
self.report_warning(f'ffmpeg-location {location} does not exist! Continuing without ffmpeg')
|
self.report_warning(
|
||||||
|
f'ffmpeg-location {location} does not exist! Continuing without ffmpeg', only_once=True)
|
||||||
return {}
|
return {}
|
||||||
elif os.path.isdir(location):
|
elif os.path.isdir(location):
|
||||||
dirname, basename = location, None
|
dirname, basename = location, None
|
||||||
@ -171,9 +172,9 @@ class FFmpegPostProcessor(PostProcessor):
|
|||||||
return self.probe_basename
|
return self.probe_basename
|
||||||
|
|
||||||
def _get_version(self, kind):
|
def _get_version(self, kind):
|
||||||
executables = (kind, self._ffmpeg_to_avconv[kind])
|
executables = (kind, )
|
||||||
if not self._prefer_ffmpeg:
|
if not self._prefer_ffmpeg:
|
||||||
executables = reversed(executables)
|
executables = (kind, self._ffmpeg_to_avconv[kind])
|
||||||
basename, version, features = next(filter(
|
basename, version, features = next(filter(
|
||||||
lambda x: x[1], ((p, *self._get_ffmpeg_version(p)) for p in executables)), (None, None, {}))
|
lambda x: x[1], ((p, *self._get_ffmpeg_version(p)) for p in executables)), (None, None, {}))
|
||||||
if kind == 'ffmpeg':
|
if kind == 'ffmpeg':
|
||||||
|
@ -18,7 +18,7 @@ from .utils import (
|
|||||||
traverse_obj,
|
traverse_obj,
|
||||||
version_tuple,
|
version_tuple,
|
||||||
)
|
)
|
||||||
from .version import __version__
|
from .version import UPDATE_HINT, VARIANT, __version__
|
||||||
|
|
||||||
REPOSITORY = 'yt-dlp/yt-dlp'
|
REPOSITORY = 'yt-dlp/yt-dlp'
|
||||||
API_URL = f'https://api.github.com/repos/{REPOSITORY}/releases'
|
API_URL = f'https://api.github.com/repos/{REPOSITORY}/releases'
|
||||||
@ -47,7 +47,7 @@ def _get_variant_and_executable_path():
|
|||||||
|
|
||||||
|
|
||||||
def detect_variant():
|
def detect_variant():
|
||||||
return _get_variant_and_executable_path()[0]
|
return VARIANT or _get_variant_and_executable_path()[0]
|
||||||
|
|
||||||
|
|
||||||
_FILE_SUFFIXES = {
|
_FILE_SUFFIXES = {
|
||||||
@ -64,13 +64,16 @@ _NON_UPDATEABLE_REASONS = {
|
|||||||
**{variant: f'Auto-update is not supported for unpackaged {name} executable; Re-download the latest release'
|
**{variant: f'Auto-update is not supported for unpackaged {name} executable; Re-download the latest release'
|
||||||
for variant, name in {'win32_dir': 'Windows', 'darwin_dir': 'MacOS', 'linux_dir': 'Linux'}.items()},
|
for variant, name in {'win32_dir': 'Windows', 'darwin_dir': 'MacOS', 'linux_dir': 'Linux'}.items()},
|
||||||
'source': 'You cannot update when running from source code; Use git to pull the latest changes',
|
'source': 'You cannot update when running from source code; Use git to pull the latest changes',
|
||||||
'unknown': 'It looks like you installed yt-dlp with a package manager, pip or setup.py; Use that to update',
|
'unknown': 'You installed yt-dlp with a package manager or setup.py; Use that to update',
|
||||||
'other': 'It looks like you are using an unofficial build of yt-dlp; Build the executable again',
|
'other': 'You are using an unofficial build of yt-dlp; Build the executable again',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def is_non_updateable():
|
def is_non_updateable():
|
||||||
return _NON_UPDATEABLE_REASONS.get(detect_variant(), _NON_UPDATEABLE_REASONS['other'])
|
if UPDATE_HINT:
|
||||||
|
return UPDATE_HINT
|
||||||
|
return _NON_UPDATEABLE_REASONS.get(
|
||||||
|
detect_variant(), _NON_UPDATEABLE_REASONS['unknown' if VARIANT else 'other'])
|
||||||
|
|
||||||
|
|
||||||
def _sha256_file(path):
|
def _sha256_file(path):
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# Autogenerated by devscripts/update-version.py
|
# Autogenerated by devscripts/update-version.py
|
||||||
|
|
||||||
__version__ = '2022.07.18'
|
__version__ = '2022.08.08'
|
||||||
|
|
||||||
RELEASE_GIT_HEAD = '135f05ef6'
|
RELEASE_GIT_HEAD = '3157158f7'
|
||||||
|
|
||||||
|
VARIANT = None
|
||||||
|
|
||||||
|
UPDATE_HINT = None
|
||||||
|
Loading…
Reference in New Issue
Block a user