From f322035d4ac6aa17386ac9dd05f9c7a8d6720e99 Mon Sep 17 00:00:00 2001 From: Jesus E Date: Sat, 17 Jun 2023 16:05:40 -0400 Subject: Add functional but preliminary channel tab support Add channel tabs to the channel template and script Update continuation token to request different tabs Add support for 'reelItemRenderer' format required to extract shorts --- youtube/channel.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'youtube/channel.py') diff --git a/youtube/channel.py b/youtube/channel.py index 4cf6cdf..5c757d3 100644 --- a/youtube/channel.py +++ b/youtube/channel.py @@ -32,16 +32,23 @@ real_cookie = (('Cookie', 'VISITOR_INFO1_LIVE=8XihrAcN1l4'),) generic_cookie = (('Cookie', 'VISITOR_INFO1_LIVE=ST1Ti53r4fU'),) # added an extra nesting under the 2nd base64 compared to v4 +# added tab support def channel_ctoken_v5(channel_id, page, sort, tab, view=1): new_sort = (2 if int(sort) == 1 else 1) offset = str(30*(int(page) - 1)) + if tab == 'videos': + tab = 15 + elif tab == 'shorts': + tab = 10 + elif tab == 'streams': + tab = 14 pointless_nest = proto.string(80226972, proto.string(2, channel_id) + proto.string(3, proto.percent_b64encode( proto.string(110, proto.string(3, - proto.string(15, + proto.string(tab, proto.string(1, proto.string(1, proto.unpadded_b64encode( @@ -167,7 +174,7 @@ def channel_ctoken_v2(channel_id, page, sort, tab, view=1): tab = proto.string(2, tab) sort = proto.uint(3, int(sort)) - # page = proto.string(15, str(page) ) + #page = proto.string(15, str(page)) shelf_view = proto.uint(4, 0) view = proto.uint(6, int(view)) @@ -202,7 +209,7 @@ def get_channel_tab(channel_id, page="1", sort=3, tab='videos', view=1, message = 'Got channel tab' if print_status else None if not ctoken: - if tab == 'videos': + if tab in ('videos', 'shorts', 'streams'): ctoken = channel_ctoken_v5(channel_id, page, sort, tab, view) else: ctoken = channel_ctoken_v3(channel_id, page, sort, tab, view) @@ -349,11 +356,11 @@ def post_process_channel_info(info): info['links'][i] = (text, util.prefix_url(url)) -def get_channel_first_page(base_url=None, channel_id=None): +def get_channel_first_page(base_url=None, channel_id=None, tab='videos'): if channel_id: base_url = 'https://www.youtube.com/channel/' + channel_id - return util.fetch_url(base_url + '/videos?pbj=1&view=0', headers_desktop, - debug_name='gen_channel_videos') + return util.fetch_url(base_url + '/' + tab + '?pbj=1&view=0', + headers_desktop, debug_name='gen_channel_' + tab) playlist_sort_codes = {'2': "da", '3': "dd", '4': "lad"} @@ -374,24 +381,25 @@ def get_channel_page_general_url(base_url, tab, request, channel_id=None): default_params = (page_number == 1 and sort == '3' and view == '1') continuation = bool(ctoken) # whether or not we're using a continuation - if tab == 'videos' and channel_id and not default_params: + if (tab in ('videos', 'shorts', 'streams') and channel_id and + not default_params): tasks = ( gevent.spawn(get_number_of_videos_channel, channel_id), gevent.spawn(get_channel_tab, channel_id, page_number, sort, - 'videos', view, ctoken) + tab, view, ctoken) ) gevent.joinall(tasks) util.check_gevent_exceptions(*tasks) number_of_videos, polymer_json = tasks[0].value, tasks[1].value continuation = True - elif tab == 'videos': + elif tab in ('videos', 'shorts', 'streams'): if channel_id: num_videos_call = (get_number_of_videos_channel, channel_id) else: num_videos_call = (get_number_of_videos_general, base_url) tasks = ( gevent.spawn(*num_videos_call), - gevent.spawn(get_channel_first_page, base_url=base_url), + gevent.spawn(get_channel_first_page, base_url=base_url, tab=tab), ) gevent.joinall(tasks) util.check_gevent_exceptions(*tasks) @@ -440,13 +448,13 @@ def get_channel_page_general_url(base_url, tab, request, channel_id=None): item.update(additional_info) if info['error'] is not None: - return flask.render_template('error.html', error_message=info['error']) + return flask.render_template('error.html', error_message = info['error']) - if tab == 'videos': + if tab in ('videos', 'shorts', 'streams'): info['number_of_videos'] = number_of_videos info['number_of_pages'] = math.ceil(number_of_videos/30) info['header_playlist_names'] = local_playlist.get_playlist_names() - if tab in ('videos', 'playlists'): + if tab in ('videos', 'shorts', 'streams', 'playlists'): info['current_sort'] = sort elif tab == 'search': info['search_box_value'] = query @@ -457,9 +465,8 @@ def get_channel_page_general_url(base_url, tab, request, channel_id=None): post_process_channel_info(info) - return flask.render_template( - 'channel.html', - parameters_dictionary=request.args, + return flask.render_template('channel.html', + parameters_dictionary = request.args, **info ) -- cgit v1.2.3