aboutsummaryrefslogtreecommitdiffstats
path: root/youtube/comments.py
diff options
context:
space:
mode:
Diffstat (limited to 'youtube/comments.py')
-rw-r--r--youtube/comments.py78
1 files changed, 43 insertions, 35 deletions
diff --git a/youtube/comments.py b/youtube/comments.py
index d47c826..1ff1a21 100644
--- a/youtube/comments.py
+++ b/youtube/comments.py
@@ -8,9 +8,6 @@ import settings
import json
import base64
-import urllib
-import re
-import traceback
import flask
from flask import request
@@ -34,7 +31,7 @@ def make_comment_ctoken(video_id, sort=0, offset=0, lc='', secret_key=''):
secret_key = proto.as_bytes(secret_key)
- page_info = proto.string(4,video_id) + proto.uint(6, sort)
+ page_info = proto.string(4, video_id) + proto.uint(6, sort)
offset_information = proto.nested(4, page_info) + proto.uint(5, offset)
if secret_key:
offset_information = proto.string(1, secret_key) + offset_information
@@ -47,25 +44,23 @@ def make_comment_ctoken(video_id, sort=0, offset=0, lc='', secret_key=''):
return base64.urlsafe_b64encode(result).decode('ascii')
-mobile_headers = {
- 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1',
- 'Accept': '*/*',
- 'Accept-Language': 'en-US,en;q=0.5',
- 'X-YouTube-Client-Name': '2',
- 'X-YouTube-Client-Version': '2.20180823',
-}
-
-
def request_comments(ctoken, replies=False):
- base_url = 'https://m.youtube.com/watch_comment?'
- if replies:
- base_url += 'action_get_comment_replies=1&ctoken='
- else:
- base_url += 'action_get_comments=1&ctoken='
- url = base_url + ctoken.replace("=", "%3D") + "&pbj=1"
+ url = 'https://m.youtube.com/youtubei/v1/next'
+ url += '?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'
+ data = json.dumps({
+ 'context': {
+ 'client': {
+ 'hl': 'en',
+ 'gl': 'US',
+ 'clientName': 'MWEB',
+ 'clientVersion': '2.20210804.02.00',
+ },
+ },
+ 'continuation': ctoken.replace('=', '%3D'),
+ })
content = util.fetch_url(
- url, headers=mobile_headers,
+ url, headers=util.mobile_xhr_headers + util.json_header, data=data,
report_text='Retrieved comments', debug_name='request_comments')
content = content.decode('utf-8')
@@ -83,7 +78,7 @@ def single_comment_ctoken(video_id, comment_id):
def post_process_comments_info(comments_info):
for comment in comments_info['comments']:
- comment['author'] = strip_non_ascii(comment['author'])
+ comment['author'] = strip_non_ascii(comment['author']) if comment.get('author') else ""
comment['author_url'] = concat_or_none(
'/', comment['author_url'])
comment['author_avatar'] = concat_or_none(
@@ -102,7 +97,7 @@ def post_process_comments_info(comments_info):
ctoken = comment['reply_ctoken']
ctoken, err = proto.set_protobuf_value(
ctoken,
- 'base64p', 6, 3, 9, value=250)
+ 'base64p', 6, 3, 9, value=200)
if err:
print('Error setting ctoken value:')
print(err)
@@ -118,10 +113,11 @@ def post_process_comments_info(comments_info):
else:
comment['view_replies_text'] = str(reply_count) + ' replies'
- if comment['like_count'] == 1:
+ if comment['approx_like_count'] == '1':
comment['likes_text'] = '1 like'
else:
- comment['likes_text'] = str(comment['like_count']) + ' likes'
+ comment['likes_text'] = (str(comment['approx_like_count'])
+ + ' likes')
comments_info['include_avatars'] = settings.enable_comment_avatars
if comments_info['ctoken']:
@@ -131,7 +127,7 @@ def post_process_comments_info(comments_info):
# change max_replies field to 250 in ctoken
new_ctoken, err = proto.set_protobuf_value(
ctoken,
- 'base64p', 6, 3, 9, value=250)
+ 'base64p', 6, 3, 9, value=200)
if err:
print('Error setting ctoken value:')
print(err)
@@ -142,7 +138,10 @@ def post_process_comments_info(comments_info):
comments_info['more_comments_url'] = concat_or_none(
util.URL_ORIGIN, '/comments?ctoken=', ctoken, replies_param)
- comments_info['page_number'] = page_number = str(int(comments_info['offset']/20) + 1)
+ if comments_info['offset'] is None:
+ comments_info['page_number'] = None
+ else:
+ comments_info['page_number'] = int(comments_info['offset']/20) + 1
if not comments_info['is_replies']:
comments_info['sort_text'] = 'top' if comments_info['sort'] == 0 else 'newest'
@@ -151,7 +150,7 @@ def post_process_comments_info(comments_info):
util.URL_ORIGIN, '/watch?v=', comments_info['video_id'])
comments_info['video_thumbnail'] = concat_or_none(
settings.img_prefix, 'https://i.ytimg.com/vi/',
- comments_info['video_id'], '/mqdefault.jpg'
+ comments_info['video_id'], '/hqdefault.jpg'
)
@@ -174,10 +173,9 @@ def video_comments(video_id, sort=0, offset=0, lc='', secret_key=''):
('Direct link', this_sort_url)
]
+ ctoken = make_comment_ctoken(video_id, sort, offset, lc)
comments_info.update(yt_data_extract.extract_comments_info(
- request_comments(
- make_comment_ctoken(video_id, sort, offset, lc, secret_key)
- )
+ request_comments(ctoken), ctoken=ctoken
))
post_process_comments_info(comments_info)
@@ -186,15 +184,15 @@ def video_comments(video_id, sort=0, offset=0, lc='', secret_key=''):
return {}
except util.FetchError as e:
if e.code == '429' and settings.route_tor:
- comments_info['error'] = 'Error: Youtube blocked the request because the Tor exit node is overutilized.'
+ comments_info['error'] = 'Error: YouTube blocked the request because the Tor exit node is overutilized.'
if e.error_message:
comments_info['error'] += '\n\n' + e.error_message
comments_info['error'] += '\n\nExit node IP address: %s' % e.ip
else:
- comments_info['error'] = traceback.format_exc()
+ comments_info['error'] = 'YouTube blocked the request. Error: %s' % str(e)
except Exception as e:
- comments_info['error'] = traceback.format_exc()
+ comments_info['error'] = 'YouTube blocked the request. Error: %s' % str(e)
if comments_info.get('error'):
print('Error retrieving comments for ' + str(video_id) + ':\n' +
@@ -208,11 +206,21 @@ def get_comments_page():
ctoken = request.args.get('ctoken', '')
replies = request.args.get('replies', '0') == '1'
- comments_info = yt_data_extract.extract_comments_info(request_comments(ctoken, replies))
+ comments_info = yt_data_extract.extract_comments_info(
+ request_comments(ctoken, replies), ctoken=ctoken
+ )
post_process_comments_info(comments_info)
if not replies:
- other_sort_url = util.URL_ORIGIN + '/comments?ctoken=' + make_comment_ctoken(comments_info['video_id'], sort=1 - comments_info['sort'])
+ if comments_info['sort'] is None or comments_info['video_id'] is None:
+ other_sort_url = None
+ else:
+ other_sort_url = (
+ util.URL_ORIGIN
+ + '/comments?ctoken='
+ + make_comment_ctoken(comments_info['video_id'],
+ sort=1-comments_info['sort'])
+ )
other_sort_text = 'Sort by ' + ('newest' if comments_info['sort'] == 0 else 'top')
comments_info['comment_links'] = [(other_sort_text, other_sort_url)]