aboutsummaryrefslogtreecommitdiffstats
path: root/youtube
diff options
context:
space:
mode:
Diffstat (limited to 'youtube')
-rw-r--r--youtube/comments.css7
-rw-r--r--youtube/comments.py27
-rw-r--r--youtube/post_comment.py41
-rw-r--r--youtube/youtube.py20
4 files changed, 88 insertions, 7 deletions
diff --git a/youtube/comments.css b/youtube/comments.css
index 5fd9063..baa8ac7 100644
--- a/youtube/comments.css
+++ b/youtube/comments.css
@@ -113,10 +113,13 @@
white-space: nowrap;
}
-.comment .replies{
- grid-column:2 / span 2;
+.comment .bottom-row{
+ grid-column:2 / span 3;
grid-row:4;
justify-self:start;
+ display: grid;
+ grid-auto-flow: column;
+ grid-column-gap: 10px;
}
.more-comments{
diff --git a/youtube/comments.py b/youtube/comments.py
index 58a03ac..1d96545 100644
--- a/youtube/comments.py
+++ b/youtube/comments.py
@@ -26,10 +26,14 @@ $avatar
<address>
<a class="author" href="$author_url" title="$author">$author</a>
</address>
- <span class="text">$text</span>
<time datetime="$datetime">$published</time>
+ <span class="text">$text</span>
+
<span class="likes">$likes</span>
+ <div class="bottom-row">
$replies
+$action_buttons
+ </div>
</div>
</div>
@@ -162,6 +166,8 @@ def parse_comments_ajax(content, replies=False):
comment = {
'author': comment_raw['author']['runs'][0]['text'],
'author_url': comment_raw['author_endpoint']['url'],
+ 'author_channel_id': '',
+ 'author_id': '',
'author_avatar': comment_raw['author_thumbnail']['url'],
'likes': comment_raw['like_count'],
'published': comment_raw['published_time']['runs'][0]['text'],
@@ -207,6 +213,7 @@ def parse_comments_polymer(content, replies=False):
video_title = comment_raw['commentTargetTitle']['runs'][0]['text']
parent_id = comment_raw['comment']['commentRenderer']['commentId']
+ # TODO: move this stuff into the comments_html function
if 'replies' in comment_raw:
#reply_ctoken = comment_raw['replies']['commentRepliesRenderer']['continuations'][0]['nextContinuationData']['continuation']
#comment_id, video_id = get_ids(reply_ctoken)
@@ -226,12 +233,16 @@ def parse_comments_polymer(content, replies=False):
comment = {
'author': common.get_plain_text(comment_raw['authorText']),
'author_url': comment_raw['authorEndpoint']['commandMetadata']['webCommandMetadata']['url'],
+ 'author_channel_id': comment_raw['authorEndpoint']['browseEndpoint']['browseId'],
+ 'author_id': comment_raw['authorId'],
'author_avatar': comment_raw['authorThumbnail']['thumbnails'][0]['url'],
'likes': comment_raw['likeCount'],
'published': common.get_plain_text(comment_raw['publishedTimeText']),
'text': comment_raw['contentText'].get('runs', ''),
'view_replies_text': view_replies_text,
'replies_url': replies_url,
+ 'video_id': video_id,
+ 'comment_id': comment_raw['commentId'],
}
comments.append(comment)
except Exception as e:
@@ -256,6 +267,16 @@ def get_comments_html(comments):
)
else:
avatar = ''
+ if comment['author_channel_id'] in accounts.accounts:
+ delete_url = (URL_ORIGIN + '/delete_comment?video_id='
+ + comment['video_id']
+ + '&channel_id='+ comment['author_channel_id']
+ + '&author_id=' + comment['author_id']
+ + '&comment_id=' + comment['comment_id'])
+
+ action_buttons = '''<a href="''' + delete_url + '''" target="_blank">Delete</a>'''
+ else:
+ action_buttons = ''
html_result += comment_template.substitute(
author=comment['author'],
author_url = URL_ORIGIN + comment['author_url'],
@@ -264,8 +285,8 @@ def get_comments_html(comments):
published = comment['published'],
text = format_text_runs(comment['text']),
datetime = '', #TODO
- replies=replies,
- #replies='',
+ replies = replies,
+ action_buttons = action_buttons,
)
return html_result
diff --git a/youtube/post_comment.py b/youtube/post_comment.py
index 45e9f4b..587a258 100644
--- a/youtube/post_comment.py
+++ b/youtube/post_comment.py
@@ -70,7 +70,7 @@ def _post_comment_reply(text, video_id, parent_comment_id, session_token, cookie
'''with open('debug/post_comment_response', 'wb') as f:
f.write(content)'''
-def delete_comment(video_id, comment_id, author_id, session_token, cookiejar):
+def _delete_comment(video_id, comment_id, author_id, session_token, cookiejar):
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': '*/*',
@@ -91,7 +91,9 @@ def delete_comment(video_id, comment_id, author_id, session_token, cookiejar):
data = urllib.parse.urlencode(data_dict).encode()
content = common.fetch_url("https://m.youtube.com/service_ajax?name=performCommentActionEndpoint", headers=headers, data=data, cookiejar_send=cookiejar)
-
+ code = json.loads(content)['code']
+ print("Comment deletion code: " + code)
+ return code
xsrf_token_regex = re.compile(r'''XSRF_TOKEN"\s*:\s*"([\w-]*(?:=|%3D){0,2})"''')
def get_session_token(video_id, cookiejar):
@@ -107,6 +109,12 @@ def get_session_token(video_id, cookiejar):
else:
raise Exception("Couldn't find xsrf_token")
+def delete_comment(parameters, fields):
+ video_id = fields['video_id'][0]
+ cookiejar = accounts.account_cookiejar(fields['channel_id'][0])
+ token = get_session_token(video_id, cookiejar)
+ return _delete_comment(video_id, fields['comment_id'][0], fields['author_id'][0], token, cookiejar)
+
def post_comment(parameters, fields):
channel_id = fields['channel_id'][0]
cookiejar = accounts.account_cookiejar(channel_id)
@@ -144,6 +152,35 @@ def post_comment(parameters, fields):
return response'''
return code
+def get_delete_comment_page(query_string):
+ parameters = urllib.parse.parse_qs(query_string)
+
+ style = '''
+ main{
+ display: grid;
+ grid-template-columns: minmax(0px, 3fr) 640px 40px 500px minmax(0px,2fr);
+ align-content: start;
+ }
+ main > div, main > form{
+ margin-top:20px;
+ grid-column:2;
+ }
+ '''
+
+ page = '''
+ <div>Are you sure you want to delete this comment?</div>
+ <form action="" method="POST">'''
+ for parameter in ('video_id', 'channel_id', 'author_id', 'comment_id'):
+ page += '''\n <input type="hidden" name="''' + parameter + '''" value="''' + parameters[parameter][0] + '''">'''
+ page += '''
+ <input type="submit" value="Yes, delete it">
+ </form>'''
+ return common.yt_basic_template.substitute(
+ page_title = "Delete comment?",
+ style = style,
+ header = common.get_header(),
+ page = page,
+ )
def get_post_comment_page(query_string):
parameters = urllib.parse.parse_qs(query_string)
diff --git a/youtube/youtube.py b/youtube/youtube.py
index 8260faf..c4a0e5b 100644
--- a/youtube/youtube.py
+++ b/youtube/youtube.py
@@ -78,6 +78,18 @@ def youtube(env, start_response):
start_response('200 OK', (('Content-type','text/html'),) )
return accounts.get_account_login_page(query_string=query_string).encode()
+ elif path == "/delete_comment":
+ start_response('200 OK', (('Content-type','text/html'),) )
+ return post_comment.get_delete_comment_page(query_string).encode()
+
+ elif path == "/comment_delete_success":
+ start_response('200 OK', () )
+ return b'Successfully deleted comment'
+
+ elif path == "/comment_delete_fail":
+ start_response('200 OK', () )
+ return b'Failed to deleted comment'
+
else:
start_response('200 OK', (('Content-type','text/html'),) )
return channel.get_channel_page_general_url(path, query_string=query_string).encode()
@@ -116,6 +128,14 @@ def youtube(env, start_response):
start_response('303 See Other', (('Location', common.URL_ORIGIN + '/comments?ctoken=' + comments.make_comment_ctoken(video_id, sort=1)),) )
return ''
+ elif path == "/delete_comment":
+ parameters = urllib.parse.parse_qs(query_string)
+ code = post_comment.delete_comment(parameters, fields)
+ if code == "SUCCESS":
+ start_response('303 See Other', (('Location', common.URL_ORIGIN + '/comment_delete_success'),) )
+ else:
+ start_response('303 See Other', (('Location', common.URL_ORIGIN + '/comment_delete_fail'),) )
+
elif path == "/login":
if 'save' in fields and fields['save'][0] == "on":
save_account = True