[youtube_live_chat] Fix download with cookies (#437)

Closes #417 

Authored by: siikamiika
This commit is contained in:
siikamiika 2021-06-24 18:56:32 +03:00 committed by GitHub
parent 2b18a8c590
commit d534c4520b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -59,6 +59,17 @@ def parse_actions_replay(live_chat_continuation):
self._append_fragment(ctx, processed_fragment) self._append_fragment(ctx, processed_fragment)
return continuation_id, offset return continuation_id, offset
def try_refresh_replay_beginning(live_chat_continuation):
# choose the second option that contains the unfiltered live chat replay
refresh_continuation_id = try_get(
live_chat_continuation,
lambda x: x['header']['liveChatHeaderRenderer']['viewSelector']['sortFilterSubMenuRenderer']['subMenuItems'][1]['continuation']['reloadContinuationData']['continuation'], str)
if refresh_continuation_id:
# no data yet but required to call _append_fragment
self._append_fragment(ctx, b'')
return refresh_continuation_id, 0
return parse_actions_replay(live_chat_continuation)
live_offset = 0 live_offset = 0
def parse_actions_live(live_chat_continuation): def parse_actions_live(live_chat_continuation):
@ -90,23 +101,29 @@ def parse_actions_live(live_chat_continuation):
self._append_fragment(ctx, processed_fragment) self._append_fragment(ctx, processed_fragment)
return continuation_id, live_offset return continuation_id, live_offset
if info_dict['protocol'] == 'youtube_live_chat_replay': def download_and_parse_fragment(url, frag_index, request_data=None, headers=None):
parse_actions = parse_actions_replay
elif info_dict['protocol'] == 'youtube_live_chat':
parse_actions = parse_actions_live
def download_and_parse_fragment(url, frag_index, request_data, headers):
count = 0 count = 0
while count <= fragment_retries: while count <= fragment_retries:
try: try:
success, raw_fragment = dl_fragment(url, request_data, headers) success, raw_fragment = dl_fragment(url, request_data, headers)
if not success: if not success:
return False, None, None return False, None, None
data = json.loads(raw_fragment) try:
data = ie._extract_yt_initial_data(video_id, raw_fragment.decode('utf-8', 'replace'))
except RegexNotFoundError:
data = None
if not data:
data = json.loads(raw_fragment)
live_chat_continuation = try_get( live_chat_continuation = try_get(
data, data,
lambda x: x['continuationContents']['liveChatContinuation'], dict) or {} lambda x: x['continuationContents']['liveChatContinuation'], dict) or {}
continuation_id, offset = parse_actions(live_chat_continuation) if info_dict['protocol'] == 'youtube_live_chat_replay':
if frag_index == 1:
continuation_id, offset = try_refresh_replay_beginning(live_chat_continuation)
else:
continuation_id, offset = parse_actions_replay(live_chat_continuation)
elif info_dict['protocol'] == 'youtube_live_chat':
continuation_id, offset = parse_actions_live(live_chat_continuation)
return True, continuation_id, offset return True, continuation_id, offset
except compat_urllib_error.HTTPError as err: except compat_urllib_error.HTTPError as err:
count += 1 count += 1
@ -142,8 +159,10 @@ def download_and_parse_fragment(url, frag_index, request_data, headers):
visitor_data = try_get(innertube_context, lambda x: x['client']['visitorData'], str) visitor_data = try_get(innertube_context, lambda x: x['client']['visitorData'], str)
if info_dict['protocol'] == 'youtube_live_chat_replay': if info_dict['protocol'] == 'youtube_live_chat_replay':
url = 'https://www.youtube.com/youtubei/v1/live_chat/get_live_chat_replay?key=' + api_key url = 'https://www.youtube.com/youtubei/v1/live_chat/get_live_chat_replay?key=' + api_key
chat_page_url = 'https://www.youtube.com/live_chat_replay?continuation=' + continuation_id
elif info_dict['protocol'] == 'youtube_live_chat': elif info_dict['protocol'] == 'youtube_live_chat':
url = 'https://www.youtube.com/youtubei/v1/live_chat/get_live_chat?key=' + api_key url = 'https://www.youtube.com/youtubei/v1/live_chat/get_live_chat?key=' + api_key
chat_page_url = 'https://www.youtube.com/live_chat?continuation=' + continuation_id
frag_index = offset = 0 frag_index = offset = 0
while continuation_id is not None: while continuation_id is not None:
@ -154,11 +173,13 @@ def download_and_parse_fragment(url, frag_index, request_data, headers):
} }
if frag_index > 1: if frag_index > 1:
request_data['currentPlayerState'] = {'playerOffsetMs': str(max(offset - 5000, 0))} request_data['currentPlayerState'] = {'playerOffsetMs': str(max(offset - 5000, 0))}
headers = ie._generate_api_headers(ytcfg, visitor_data=visitor_data) headers = ie._generate_api_headers(ytcfg, visitor_data=visitor_data)
headers.update({'content-type': 'application/json'}) headers.update({'content-type': 'application/json'})
fragment_request_data = json.dumps(request_data, ensure_ascii=False).encode('utf-8') + b'\n' fragment_request_data = json.dumps(request_data, ensure_ascii=False).encode('utf-8') + b'\n'
success, continuation_id, offset = download_and_parse_fragment( success, continuation_id, offset = download_and_parse_fragment(
url, frag_index, fragment_request_data, headers) url, frag_index, fragment_request_data, headers)
else:
success, continuation_id, offset = download_and_parse_fragment(chat_page_url, frag_index)
if not success: if not success:
return False return False
if test: if test: