diff options
author | Jesús <heckyel@hyperbola.info> | 2020-12-15 21:52:04 -0500 |
---|---|---|
committer | Jesús <heckyel@hyperbola.info> | 2020-12-15 21:52:04 -0500 |
commit | b9a3082e7c654d97cecc5410c086e13a7b046909 (patch) | |
tree | dc093ccb2246e7df0beaca5deb8b7467620b74a2 /youtube/channel.py | |
parent | f4b36a220d085080a881dbe2f63e51b2fb28a003 (diff) | |
download | yt-local-b9a3082e7c654d97cecc5410c086e13a7b046909.tar.lz yt-local-b9a3082e7c654d97cecc5410c086e13a7b046909.tar.xz yt-local-b9a3082e7c654d97cecc5410c086e13a7b046909.zip |
pep8
Diffstat (limited to 'youtube/channel.py')
-rw-r--r-- | youtube/channel.py | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/youtube/channel.py b/youtube/channel.py index e9cc87b..6f40965 100644 --- a/youtube/channel.py +++ b/youtube/channel.py @@ -51,7 +51,7 @@ def channel_ctoken_v3(channel_id, page, sort, tab, view=1): proto.string(1, proto.unpadded_b64encode(proto.uint(1,offset))) )) - tab = proto.string(2, tab ) + tab = proto.string(2, tab) sort = proto.uint(3, int(sort)) shelf_view = proto.uint(4, 0) @@ -60,11 +60,12 @@ def channel_ctoken_v3(channel_id, page, sort, tab, view=1): proto.percent_b64encode(tab + sort + shelf_view + view + page_token) ) - channel_id = proto.string(2, channel_id ) + channel_id = proto.string(2, channel_id) pointless_nest = proto.string(80226972, channel_id + continuation_info) return base64.urlsafe_b64encode(pointless_nest).decode('ascii') + def channel_ctoken_v2(channel_id, page, sort, tab, view=1): # see https://github.com/iv-org/invidious/issues/1319#issuecomment-671732646 # page > 1 doesn't work when sorting by oldest @@ -74,41 +75,44 @@ def channel_ctoken_v2(channel_id, page, sort, tab, view=1): 2: 17254859483345278706, 1: 16570086088270825023, }[int(sort)] - page_token = proto.string(61, proto.unpadded_b64encode(proto.string(1, - proto.uint(1, schema_number) + proto.string(2, - proto.string(1, proto.unpadded_b64encode(proto.uint(1,offset))) - ) - ))) + page_token = proto.string(61, proto.unpadded_b64encode( + proto.string(1, proto.uint(1, schema_number) + proto.string( + 2, + proto.string(1, proto.unpadded_b64encode(proto.uint(1, offset))) + )))) - tab = proto.string(2, tab ) + 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)) - continuation_info = proto.string(3, + continuation_info = proto.string( + 3, proto.percent_b64encode(tab + sort + shelf_view + view + page_token) ) - channel_id = proto.string(2, channel_id ) + channel_id = proto.string(2, channel_id) pointless_nest = proto.string(80226972, channel_id + continuation_info) return base64.urlsafe_b64encode(pointless_nest).decode('ascii') + def channel_ctoken_v1(channel_id, page, sort, tab, view=1): - tab = proto.string(2, tab ) + tab = proto.string(2, tab) sort = proto.uint(3, int(sort)) - page = proto.string(15, str(page) ) + page = proto.string(15, str(page)) # example with shelves in videos tab: https://www.youtube.com/channel/UCNL1ZadSjHpjm4q9j2sVtOA/videos shelf_view = proto.uint(4, 0) view = proto.uint(6, int(view)) continuation_info = proto.string(3, proto.percent_b64encode(tab + view + sort + shelf_view + page + proto.uint(23, 0)) ) - channel_id = proto.string(2, channel_id ) + channel_id = proto.string(2, channel_id) pointless_nest = proto.string(80226972, channel_id + continuation_info) return base64.urlsafe_b64encode(pointless_nest).decode('ascii') + def get_channel_tab(channel_id, page="1", sort=3, tab='videos', view=1, print_status=True): message = 'Got channel tab' if print_status else None @@ -118,18 +122,21 @@ def get_channel_tab(channel_id, page="1", sort=3, tab='videos', view=1, print_st url = ('https://www.youtube.com/channel/' + channel_id + '/' + tab + '?action_continuation=1&continuation=' + ctoken + '&pbj=1') - content = util.fetch_url(url, headers_desktop + real_cookie, + content = util.fetch_url( + url, headers_desktop + real_cookie, debug_name='channel_tab', report_text=message) else: ctoken = channel_ctoken_v3(channel_id, page, sort, tab, view) ctoken = ctoken.replace('=', '%3D') url = 'https://www.youtube.com/browse_ajax?ctoken=' + ctoken - content = util.fetch_url(url, + content = util.fetch_url( + url, headers_desktop + generic_cookie, debug_name='channel_tab', report_text=message) return content + # cache entries expire after 30 minutes @cachetools.func.ttl_cache(maxsize=128, ttl=30*60) def get_number_of_videos_channel(channel_id): @@ -157,22 +164,28 @@ def get_number_of_videos_channel(channel_id): else: return 0 + channel_id_re = re.compile(r'videos\.xml\?channel_id=([a-zA-Z0-9_-]{24})"') + + @cachetools.func.lru_cache(maxsize=128) def get_channel_id(base_url): # method that gives the smallest possible response at ~4 kb # needs to be as fast as possible base_url = base_url.replace('https://www', 'https://m') # avoid redirect - response = util.fetch_url(base_url + '/about?pbj=1', headers_mobile, + response = util.fetch_url( + base_url + '/about?pbj=1', headers_mobile, debug_name='get_channel_id', report_text='Got channel id').decode('utf-8') match = channel_id_re.search(response) if match: return match.group(1) return None + def get_number_of_videos_general(base_url): return get_number_of_videos_channel(get_channel_id(base_url)) + def get_channel_search_json(channel_id, query, page): params = proto.string(2, 'search') + proto.string(15, str(page)) params = proto.percent_b64encode(params) @@ -192,15 +205,14 @@ def post_process_channel_info(info): util.add_extra_html_info(item) - - - playlist_sort_codes = {'2': "da", '3': "dd", '4': "lad"} # youtube.com/[channel_id]/[tab] # youtube.com/user/[username]/[tab] # youtube.com/c/[custom]/[tab] # youtube.com/[custom]/[tab] + + def get_channel_page_general_url(base_url, tab, request, channel_id=None): page_number = int(request.args.get('page', 1)) @@ -236,10 +248,9 @@ def get_channel_page_general_url(base_url, tab, request, channel_id=None): else: flask.abort(404, 'Unknown channel tab: ' + tab) - info = yt_data_extract.extract_channel_info(json.loads(polymer_json), tab) 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']) post_process_channel_info(info) if tab == 'videos': @@ -254,28 +265,32 @@ def get_channel_page_general_url(base_url, tab, request, channel_id=None): info['page_number'] = page_number info['subscribed'] = subscriptions.is_subscribed(info['channel_id']) - return flask.render_template('channel.html', - parameters_dictionary = request.args, + return flask.render_template( + 'channel.html', + parameters_dictionary=request.args, **info ) + @yt_app.route('/channel/<channel_id>/') @yt_app.route('/channel/<channel_id>/<tab>') def get_channel_page(channel_id, tab='videos'): return get_channel_page_general_url('https://www.youtube.com/channel/' + channel_id, tab, request, channel_id) + @yt_app.route('/user/<username>/') @yt_app.route('/user/<username>/<tab>') def get_user_page(username, tab='videos'): return get_channel_page_general_url('https://www.youtube.com/user/' + username, tab, request) + @yt_app.route('/c/<custom>/') @yt_app.route('/c/<custom>/<tab>') def get_custom_c_page(custom, tab='videos'): return get_channel_page_general_url('https://www.youtube.com/c/' + custom, tab, request) + @yt_app.route('/<custom>') @yt_app.route('/<custom>/<tab>') def get_toplevel_custom_page(custom, tab='videos'): return get_channel_page_general_url('https://www.youtube.com/' + custom, tab, request) - |