Compare commits

...

3 Commits

Author SHA1 Message Date
bashonly
820c6e2445 [ie/mitele] Remove extractor (#14348)
Closes #13535
Authored by: bashonly
2025-09-16 23:03:09 +00:00
thegymguy
677997d84e [ie/xhamster] Fix extractor (#14345)
Fix a1c98226a4

Closes #14145
Authored by: arand, thegymguy

Co-authored-by: arand <183498+arand@users.noreply.github.com>
2025-09-16 22:19:08 +00:00
sepro
b81e9272dc [ie/vk] Support vksport URLs (#14341)
Closes #14175
Authored by: seproDev
2025-09-16 19:43:00 +02:00
5 changed files with 42 additions and 118 deletions

View File

@@ -1136,7 +1136,6 @@ from .mit import (
OCWMITIE,
TechTVMITIE,
)
from .mitele import MiTeleIE
from .mixch import (
MixchArchiveIE,
MixchIE,

View File

@@ -1,102 +0,0 @@
from .telecinco import TelecincoBaseIE
from ..utils import (
int_or_none,
parse_iso8601,
)
class MiTeleIE(TelecincoBaseIE):
IE_DESC = 'mitele.es'
_VALID_URL = r'https?://(?:www\.)?mitele\.es/(?:[^/]+/)+(?P<id>[^/]+)/player'
_TESTS = [{
'url': 'http://www.mitele.es/programas-tv/diario-de/57b0dfb9c715da65618b4afa/player',
'info_dict': {
'id': 'FhYW1iNTE6J6H7NkQRIEzfne6t2quqPg',
'ext': 'mp4',
'title': 'Diario de La redacción Programa 144',
'description': 'md5:07c35a7b11abb05876a6a79185b58d27',
'series': 'Diario de',
'season': 'Season 14',
'season_number': 14,
'episode': 'Tor, la web invisible',
'episode_number': 3,
'thumbnail': r're:(?i)^https?://.*\.jpg$',
'duration': 2913,
'age_limit': 16,
'timestamp': 1471209401,
'upload_date': '20160814',
},
'skip': 'HTTP Error 404 Not Found',
}, {
# no explicit title
'url': 'http://www.mitele.es/programas-tv/cuarto-milenio/57b0de3dc915da14058b4876/player',
'info_dict': {
'id': 'oyNG1iNTE6TAPP-JmCjbwfwJqqMMX3Vq',
'ext': 'mp4',
'title': 'Cuarto Milenio Temporada 6 Programa 226',
'description': 'md5:5ff132013f0cd968ffbf1f5f3538a65f',
'series': 'Cuarto Milenio',
'season': 'Season 6',
'season_number': 6,
'episode': 'Episode 24',
'episode_number': 24,
'thumbnail': r're:(?i)^https?://.*\.jpg$',
'duration': 7313,
'age_limit': 12,
'timestamp': 1471209021,
'upload_date': '20160814',
},
'params': {
'skip_download': True,
},
'skip': 'HTTP Error 404 Not Found',
}, {
'url': 'https://www.mitele.es/programas-tv/horizonte/temporada-5/programa-171-40_013480051/player/',
'info_dict': {
'id': '7adbe22e-cd41-4787-afa4-36f3da7c2c6f',
'ext': 'mp4',
'title': 'Horizonte Temporada 5 Programa 171',
'description': 'md5:97f1fb712c5ac27e5693a8b3c5c0c6e3',
'episode': 'Las Zonas de Bajas Emisiones, a debate',
'episode_number': 171,
'season': 'Season 5',
'season_number': 5,
'series': 'Horizonte',
'duration': 7012,
'upload_date': '20240927',
'timestamp': 1727416450,
'thumbnail': 'https://album.mediaset.es/eimg/2024/09/27/horizonte-171_9f02.jpg',
'age_limit': 12,
},
'params': {'geo_bypass_country': 'ES'},
}, {
'url': 'http://www.mitele.es/series-online/la-que-se-avecina/57aac5c1c915da951a8b45ed/player',
'only_matching': True,
}, {
'url': 'https://www.mitele.es/programas-tv/diario-de/la-redaccion/programa-144-40_1006364575251/player/',
'only_matching': True,
}]
def _real_extract(self, url):
display_id = self._match_id(url)
webpage = self._download_webpage(url, display_id)
pre_player = self._search_json(
r'window\.\$REACTBASE_STATE\.prePlayer_mtweb\s*=',
webpage, 'Pre Player', display_id)['prePlayer']
title = pre_player['title']
video_info = self._parse_content(pre_player['video'], url)
content = pre_player.get('content') or {}
info = content.get('info') or {}
video_info.update({
'title': title,
'description': info.get('synopsis'),
'series': content.get('title'),
'season_number': int_or_none(info.get('season_number')),
'episode': content.get('subtitle'),
'episode_number': int_or_none(info.get('episode_number')),
'duration': int_or_none(info.get('duration')),
'age_limit': int_or_none(info.get('rating')),
'timestamp': parse_iso8601(pre_player.get('publishedTime')),
})
return video_info

View File

@@ -65,6 +65,7 @@ class KnownDRMIE(UnsupportedInfoExtractor):
r'play\.rtl\.hr',
r'rtlmost\.hu',
r'plus\.rtl\.de(?!/podcast/)',
r'mediasetinfinity\.es',
)
_TESTS = [{
@@ -222,6 +223,9 @@ class KnownDRMIE(UnsupportedInfoExtractor):
}, {
'url': 'https://plus.rtl.de/video-tv/',
'only_matching': True,
}, {
'url': 'https://www.mediasetinfinity.es/',
'only_matching': True,
}]
def _real_extract(self, url):

View File

@@ -96,12 +96,12 @@ class VKIE(VKBaseIE):
https?://
(?:
(?:
(?:(?:m|new)\.)?vk(?:(?:video)?\.ru|\.com)/video_|
(?:(?:m|new|vksport)\.)?vk(?:(?:video)?\.ru|\.com)/video_|
(?:www\.)?daxab\.com/
)
ext\.php\?(?P<embed_query>.*?\boid=(?P<oid>-?\d+).*?\bid=(?P<id>\d+).*)|
(?:
(?:(?:m|new)\.)?vk(?:(?:video)?\.ru|\.com)/(?:.+?\?.*?z=)?(?:video|clip)|
(?:(?:m|new|vksport)\.)?vk(?:(?:video)?\.ru|\.com)/(?:.+?\?.*?z=)?(?:video|clip)|
(?:www\.)?daxab\.com/embed/
)
(?P<videoid>-?\d+_\d+)(?:.*\blist=(?P<list_id>([\da-f]+)|(ln-[\da-zA-Z]+)))?
@@ -359,6 +359,10 @@ class VKIE(VKBaseIE):
'url': 'https://vk.ru/video-220754053_456242564',
'only_matching': True,
},
{
'url': 'https://vksport.vkvideo.ru/video-124096712_456240773',
'only_matching': True,
},
]
def _real_extract(self, url):

View File

@@ -1,4 +1,5 @@
import base64
import codecs
import itertools
import re
@@ -11,13 +12,13 @@ from ..utils import (
extract_attributes,
float_or_none,
int_or_none,
join_nonempty,
parse_duration,
str_or_none,
try_call,
try_get,
unified_strdate,
url_or_none,
urljoin,
)
@@ -142,6 +143,27 @@ class XHamsterIE(InfoExtractor):
'only_matching': True,
}]
_XOR_KEY = b'xh7999'
def _decipher_format_url(self, format_url, format_id):
cipher_type, _, ciphertext = try_call(
lambda: base64.b64decode(format_url).decode().partition('_')) or [None] * 3
if not cipher_type or not ciphertext:
self.report_warning(f'Skipping format "{format_id}": failed to decipher URL')
return None
if cipher_type == 'xor':
return bytes(
a ^ b for a, b in
zip(ciphertext.encode(), itertools.cycle(self._XOR_KEY))).decode()
if cipher_type == 'rot13':
return codecs.decode(ciphertext, cipher_type)
self.report_warning(f'Skipping format "{format_id}": unsupported cipher type "{cipher_type}"')
return None
def _real_extract(self, url):
mobj = self._match_valid_url(url)
video_id = mobj.group('id') or mobj.group('id_2')
@@ -212,7 +234,7 @@ class XHamsterIE(InfoExtractor):
hls_url = hls_sources.get(hls_format_key)
if not hls_url:
continue
hls_url = urljoin(url, hls_url)
hls_url = self._decipher_format_url(hls_url, f'hls-{hls_format_key}')
if not hls_url or hls_url in format_urls:
continue
format_urls.add(hls_url)
@@ -221,7 +243,7 @@ class XHamsterIE(InfoExtractor):
m3u8_id='hls', fatal=False))
standard_sources = xplayer_sources.get('standard')
if isinstance(standard_sources, dict):
for format_id, formats_list in standard_sources.items():
for identifier, formats_list in standard_sources.items():
if not isinstance(formats_list, list):
continue
for standard_format in formats_list:
@@ -231,12 +253,11 @@ class XHamsterIE(InfoExtractor):
standard_url = standard_format.get(standard_format_key)
if not standard_url:
continue
decoded = try_call(lambda: base64.b64decode(standard_url))
if decoded and decoded[:4] == b'xor_':
standard_url = bytes(
a ^ b for a, b in
zip(decoded[4:], itertools.cycle(b'xh7999'))).decode()
standard_url = urljoin(url, standard_url)
quality = (str_or_none(standard_format.get('quality'))
or str_or_none(standard_format.get('label'))
or '')
format_id = join_nonempty(identifier, quality)
standard_url = self._decipher_format_url(standard_url, format_id)
if not standard_url or standard_url in format_urls:
continue
format_urls.add(standard_url)
@@ -246,11 +267,9 @@ class XHamsterIE(InfoExtractor):
standard_url, video_id, 'mp4', entry_protocol='m3u8_native',
m3u8_id='hls', fatal=False))
continue
quality = (str_or_none(standard_format.get('quality'))
or str_or_none(standard_format.get('label'))
or '')
formats.append({
'format_id': f'{format_id}-{quality}',
'format_id': format_id,
'url': standard_url,
'ext': ext,
'height': get_height(quality),