From 20f5c7b7f8c74f89b611d21be7d0af15ad33a059 Mon Sep 17 00:00:00 2001 From: rimu <3310831+rimu@users.noreply.github.com> Date: Sat, 6 Jan 2024 11:01:44 +1300 Subject: [PATCH] notifications --- app/activitypub/util.py | 30 ++++++++++++++++++++++++++++-- app/community/routes.py | 3 ++- app/post/routes.py | 23 ++++++++++++++++------- app/static/scss/_typography.scss | 4 ++++ app/static/structure.css | 5 +++++ app/static/styles.css | 5 +++++ app/templates/base.html | 11 +++++++++-- app/user/routes.py | 7 ++++--- 8 files changed, 73 insertions(+), 15 deletions(-) diff --git a/app/activitypub/util.py b/app/activitypub/util.py index 31aee555..cf54bbb3 100644 --- a/app/activitypub/util.py +++ b/app/activitypub/util.py @@ -4,7 +4,7 @@ import os from datetime import timedelta from random import randint from typing import Union, Tuple -from flask import current_app, request, g +from flask import current_app, request, g, url_for from sqlalchemy import text from app import db, cache, constants, celery from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow, \ @@ -20,7 +20,8 @@ from PIL import Image, ImageOps from io import BytesIO from app.utils import get_request, allowlist_html, html_to_markdown, get_setting, ap_datetime, markdown_to_html, \ - is_image_url, domain_from_url, gibberish, ensure_directory_exists, markdown_to_text, head_request, post_ranking + is_image_url, domain_from_url, gibberish, ensure_directory_exists, markdown_to_text, head_request, post_ranking, \ + shorten_string def public_key(): @@ -466,6 +467,7 @@ def post_json_to_model(post_json, user, community) -> Post: notify = Notification(title='Suspicious content', url=post.ap_id, user_id=community_member.user_id, author_id=user.id) db.session.add(notify) already_notified.add(community_member.user_id) + if domain.notify_admins: for admin in Site.admins(): if admin.id not in already_notified: @@ -911,12 +913,36 @@ def create_post_reply(activity_log: ActivityPubLog, community: Community, in_rep if post_id is not None: post = Post.query.get(post_id) if post.comments_enabled: + anchor = None + if not parent_comment_id: + notification_target = post + else: + notification_target = PostReply.query.get(parent_comment_id) + + if notification_target.author.has_blocked_user(post_reply.user_id): + activity_log.exception_message = 'Replier blocked, reply discarded' + activity_log.result = 'ignored' + return None + db.session.add(post_reply) post.reply_count += 1 community.post_reply_count += 1 community.last_active = post.last_active = utcnow() activity_log.result = 'success' db.session.commit() + + # send notification to the post/comment being replied to + if notification_target.notify_author and post_reply.user_id != notification_target.user_id and notification_target.author.ap_id is None: + if isinstance(notification_target, PostReply): + anchor = f"comment_{post_reply.id}" + notification = Notification(title='Reply from ' + post_reply.author.display_name(), + user_id=notification_target.user_id, + author_id=post_reply.user_id, + url=url_for('activitypub.post_ap', post_id=post.id, _anchor=anchor)) + db.session.add(notification) + notification_target.author.unread_notifications += 1 + db.session.commit() + if user.reputation > 100: vote = PostReplyVote(user_id=1, author_id=post_reply.user_id, post_reply_id=post_reply.id, diff --git a/app/community/routes.py b/app/community/routes.py index 6606ce76..4d242209 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -433,10 +433,11 @@ def community_report(community_id: int): # todo: find all instance admin(s). for now just load User.id == 1 admins = [User.query.get_or_404(1)] for admin in admins: - notification = Notification(user_id=admin.id, title=_('A post has been reported'), + notification = Notification(user_id=admin.id, title=_('A community has been reported'), url=community.local_url(), author_id=current_user.id) db.session.add(notification) + admin.unread_notifications += 1 db.session.commit() # todo: federate report to originating instance diff --git a/app/post/routes.py b/app/post/routes.py index c8485b31..4cacaeb6 100644 --- a/app/post/routes.py +++ b/app/post/routes.py @@ -54,14 +54,19 @@ def show_post(post_id: int): resp.set_cookie('sesion', '17489047567495', expires=datetime(year=2099, month=12, day=30)) return resp + if post.author.has_blocked_user(current_user.id): + flash(_('You cannot reply to %(name)s', name=post.author.display_name())) + return redirect(url_for('activitypub.post_ap', post_id=post_id)) + reply = PostReply(user_id=current_user.id, post_id=post.id, community_id=community.id, body=form.body.data, body_html=markdown_to_html(form.body.data), body_html_safe=True, from_bot=current_user.bot, up_votes=1, nsfw=post.nsfw, nsfl=post.nsfl, notify_author=form.notify_author.data) - if post.notify_author and current_user.id != post.user_id: # todo: check if replier is blocked - notification = Notification(title=_('Reply: ') + shorten_string(form.body.data, 42), user_id=post.user_id, + if post.notify_author and current_user.id != post.user_id: + notification = Notification(title=_('Reply from %(name)s ', name=current_user.display_name()), user_id=post.user_id, author_id=current_user.id, url=url_for('activitypub.post_ap', post_id=post.id)) db.session.add(notification) + post.author.unread_notifications += 1 post.last_active = community.last_active = utcnow() post.reply_count += 1 community.post_reply_count += 1 @@ -363,6 +368,11 @@ def add_reply(post_id: int, comment_id: int): in_reply_to = PostReply.query.get_or_404(comment_id) mods = post.community.moderators() is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods) + + if in_reply_to.author.has_blocked_user(current_user.id): + flash(_('You cannot reply to %(name)s', name=in_reply_to.author.display_name())) + return redirect(url_for('activitypub.post_ap', post_id=post_id)) + form = NewReplyForm() if form.validate_on_submit(): current_user.last_seen = utcnow() @@ -374,22 +384,21 @@ def add_reply(post_id: int, comment_id: int): notify_author=form.notify_author.data) db.session.add(reply) if in_reply_to.notify_author and current_user.id != in_reply_to.user_id and in_reply_to.author.ap_id is None: # todo: check if replier is blocked - notification = Notification(title=_('Reply: ') + shorten_string(form.body.data, 42), user_id=in_reply_to.user_id, + notification = Notification(title=_('Reply from %(name)s', name=current_user.display_name()), user_id=in_reply_to.user_id, author_id=current_user.id, url=url_for('activitypub.post_ap', post_id=post.id)) db.session.add(notification) + in_reply_to.author.unread_notifications += 1 db.session.commit() reply.ap_id = reply.profile_id() db.session.commit() if current_user.reputation > 100: - reply_vote = PostReplyVote(user_id=1, author_id=current_user.id, post_reply_id=reply.id, - effect=1.0) + reply_vote = PostReplyVote(user_id=1, author_id=current_user.id, post_reply_id=reply.id, effect=1.0) reply.up_votes += 1 reply.score += 1 reply.ranking += 1 db.session.add(reply_vote) elif current_user.reputation < -100: - reply_vote = PostReplyVote(user_id=1, author_id=current_user.id, post_reply_id=reply.id, - effect=-1.0) + reply_vote = PostReplyVote(user_id=1, author_id=current_user.id, post_reply_id=reply.id, effect=-1.0) reply.score -= 1 reply.ranking -= 1 db.session.add(reply_vote) diff --git a/app/static/scss/_typography.scss b/app/static/scss/_typography.scss index f98f2916..e10639e2 100644 --- a/app/static/scss/_typography.scss +++ b/app/static/scss/_typography.scss @@ -198,6 +198,10 @@ content: "\e967"; } +.fe-bell { + position: relative; + top: 1px; +} .fe-bell::before { content: "\e91e"; } diff --git a/app/static/structure.css b/app/static/structure.css index b25ef176..794a9148 100644 --- a/app/static/structure.css +++ b/app/static/structure.css @@ -225,6 +225,11 @@ nav, etc which are used site-wide */ content: "\e967"; } +.fe-bell { + position: relative; + top: 1px; +} + .fe-bell::before { content: "\e91e"; } diff --git a/app/static/styles.css b/app/static/styles.css index d5a1402e..8e143bac 100644 --- a/app/static/styles.css +++ b/app/static/styles.css @@ -224,6 +224,11 @@ content: "\e967"; } +.fe-bell { + position: relative; + top: 1px; +} + .fe-bell::before { content: "\e91e"; } diff --git a/app/templates/base.html b/app/templates/base.html index 1356a380..894c9089 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -96,8 +96,15 @@