Compare commits

...

14 Commits

Author SHA1 Message Date
N/Ame
ddfd3e92e5
Merge ea7d7d85d3 into f351440f1d 2024-11-17 22:14:24 +01:00
grqx_wsl
ea7d7d85d3 request with impersonate=True 2024-11-01 11:15:54 +13:00
grqx_wsl
8e010ace41 make formats extraction non-fatal when geo-blocked or login required 2024-11-01 00:00:59 +13:00
grqx_wsl
0a05711805 float_or_none: use partial_application 2024-10-31 23:37:35 +13:00
grqx_wsl
6c6d75be16 Merge remote-tracking branch 'upstream/master' into ie/bahamut 2024-10-31 23:34:04 +13:00
grqx_wsl
50b2820684 Merge remote-tracking branch 'upstream/master' into ie/anigamer 2024-10-30 18:27:57 +13:00
grqx_wsl
ce031318fd [ie/anigamer] rename to bahamut 2024-10-30 18:11:38 +13:00
grqx_wsl
f8e15176cb add http headers at the root of the info_dict
simplify structure
2024-10-30 09:19:58 +13:00
grqx_wsl
2ad1cbf12d add http_headers for downloading 2024-10-29 13:14:30 +13:00
grqx_wsl
106f6c931b Merge remote-tracking branch 'upstream/master' into ie/anigamer 2024-10-28 13:28:21 +13:00
grqx_wsl
3b58fd1a20 add http_headers, extract all formats 2024-10-28 12:01:01 +13:00
grqx_wsl
99665e31b9 Merge remote-tracking branch 'upstream/master' into ie/anigamer 2024-10-28 11:28:14 +13:00
grqx_wsl
058ac436ba Use the same device_id in playlists 2024-10-23 18:32:11 +13:00
grqx_wsl
f87558f7a5 [ie/anigamer] add extractor 2024-10-23 10:40:48 +13:00
3 changed files with 115 additions and 0 deletions

View File

@ -1869,6 +1869,9 @@ The following extractors use this feature:
#### digitalconcerthall #### digitalconcerthall
* `prefer_combined_hls`: Prefer extracting combined/pre-merged video and audio HLS formats. This will exclude 4K/HEVC video and lossless/FLAC audio formats, which are only available as split video/audio HLS formats * `prefer_combined_hls`: Prefer extracting combined/pre-merged video and audio HLS formats. This will exclude 4K/HEVC video and lossless/FLAC audio formats, which are only available as split video/audio HLS formats
#### bahamut
* `device_id`: (optional) Device ID got from `https://ani.gamer.com.tw/ajax/getdeviceid.php` (bound to cookies and `User-Agent` HTTP header). The extractor will automatically fetch one if it is not present. E.g. `"bahamut:device_id=1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab"`
**Note**: These options may be changed/removed in the future without concern for backward compatibility **Note**: These options may be changed/removed in the future without concern for backward compatibility
<!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE --> <!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE -->

View File

@ -196,6 +196,7 @@ from .awaan import (
) )
from .axs import AxsIE from .axs import AxsIE
from .azmedien import AZMedienIE from .azmedien import AZMedienIE
from .bahamut import BahamutIE
from .baidu import BaiduVideoIE from .baidu import BaiduVideoIE
from .banbye import ( from .banbye import (
BanByeChannelIE, BanByeChannelIE,

111
yt_dlp/extractor/bahamut.py Normal file
View File

@ -0,0 +1,111 @@
from .common import InfoExtractor
from ..utils import (
ExtractorError,
float_or_none,
smuggle_url,
unified_timestamp,
unsmuggle_url,
)
from ..utils.traversal import traverse_obj
class BahamutIE(InfoExtractor):
_VALID_URL = r'https?://ani\.gamer\.com\.tw/animeVideo\.php\?sn=(?P<id>\d+)'
# see anime_player.js
RATING_TO_AGE_LIMIT = {
1: 0,
2: 6,
3: 12,
4: 15,
5: 18,
6: 18, # age-gated, needs login
}
def _real_extract(self, url):
url, unsmuggled_data = unsmuggle_url(url, {})
video_id = self._match_id(url)
device_id = (
self._configuration_arg('device_id', [None], casesense=True)[0]
or unsmuggled_data.get('device_id')
or self._download_json(
'https://ani.gamer.com.tw/ajax/getdeviceid.php', video_id,
'Downloading device ID', 'Failed to download device ID',
impersonate=True, headers=self.geo_verification_headers())['deviceid'])
# TODO: extract metadata from webpage
metadata = {}
if api_result := self._download_json(
'https://api.gamer.com.tw/anime/v1/video.php', video_id,
'Downloading video info', 'Failed to download video info',
impersonate=True, query={'videoSn': video_id}).get('data'):
metadata.update(traverse_obj(api_result, ('anime', {
'description': 'content',
'thumbnail': 'cover',
'tags': 'tags',
'creators': ('director', {lambda x: [x]}),
'title': 'title',
})))
playlist_id = traverse_obj(api_result, ('video', 'animeSn')) or ''
if self._yes_playlist(playlist_id, video_id) and unsmuggled_data.get('extract_playlist') is not False:
return self.playlist_result(
(self.url_result(
# it may be better to use self.cache for storing device_id
smuggle_url(f'https://ani.gamer.com.tw/animeVideo.php?sn={ep["videoSn"]}', {
'extract_playlist': False,
'device_id': device_id,
}), ie=BahamutIE,
video_id=ep['videoSn'], thumbnail=ep.get('cover')) for ep in traverse_obj(
api_result,
# This (the first ellipsis) extracts episodes of all languages,
# maybe just extract episodes of the current language?
('anime', 'episodes', ..., ...))),
playlist_id=playlist_id, **metadata)
# video-specific metadata, extract after returning the playlist result
metadata.update(traverse_obj(api_result, ('video', {
'thumbnail': 'cover',
'title': 'title',
'timestamp': ('upTime', {unified_timestamp}),
'duration': ('duration', {float_or_none(scale=60)}),
'age_limit': ('rating', {lambda x: self.RATING_TO_AGE_LIMIT.get(x)}),
})))
m3u8_info, urlh = self._download_json_handle(
'https://ani.gamer.com.tw/ajax/m3u8.php', video_id,
note='Downloading m3u8 URL', errnote='Failed to download m3u8 URL', query={
'sn': video_id,
'device': device_id,
}, impersonate=True, headers=self.geo_verification_headers(), expected_status=400)
formats_fatal = True
if urlh.status == 400:
# TODO: handle more error codes, search for /case \d+{4}:/g in anime_player.js
error_code = traverse_obj(m3u8_info, ('error', 'code'))
if error_code == 1011:
self.raise_geo_restricted(metadata_available=True)
formats_fatal = False
elif error_code == 1007:
if unsmuggled_data.pop('device_id', None) is not None:
return self.url_result(
smuggle_url(f'https://ani.gamer.com.tw/animeVideo.php?sn={video_id}',
unsmuggled_data), ie=BahamutIE, video_id=video_id)
raise ExtractorError('Invalid device id!')
elif error_code == 1017:
self.raise_login_required(metadata_available=True)
formats_fatal = False
else:
raise ExtractorError(
traverse_obj(m3u8_info, ('error', 'message')) or 'Failed to download m3u8 URL')
return {
**metadata,
'id': video_id,
'formats': self._extract_m3u8_formats(
m3u8_info.get('src'), video_id, ext='mp4', fatal=formats_fatal, headers={
'Origin': 'https://ani.gamer.com.tw',
**self.geo_verification_headers(),
}),
'http_headers': {'Origin': 'https://ani.gamer.com.tw'},
}