mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
parent
cede0163fd
commit
01d4b2678c
13 changed files with 177 additions and 52 deletions
|
@ -1364,17 +1364,10 @@ def create_post_reply(activity_log: ActivityPubLog, community: Community, in_rep
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
# send notification to the post/comment being replied to
|
# 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 parent_comment_id:
|
||||||
anchor = f"comment_{post_reply.id}"
|
notify_about_post_reply(parent_comment, post_reply)
|
||||||
notification = Notification(title=shorten_string(_('Reply from %(name)s on %(post_title)s',
|
else:
|
||||||
name=post_reply.author.display_name(),
|
notify_about_post_reply(None, post_reply)
|
||||||
post_title=post.title), 50),
|
|
||||||
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:
|
if user.reputation > 100:
|
||||||
post_reply.up_votes += 1
|
post_reply.up_votes += 1
|
||||||
|
@ -1555,6 +1548,35 @@ def notify_about_post(post: Post):
|
||||||
notifications_sent_to.add(notify_id)
|
notifications_sent_to.add(notify_id)
|
||||||
|
|
||||||
|
|
||||||
|
def notify_about_post_reply(parent_reply: Union[PostReply, None], new_reply: PostReply):
|
||||||
|
|
||||||
|
if parent_reply is None: # This happens when a new_reply is a top-level comment, not a comment on a comment
|
||||||
|
send_notifs_to = notification_subscribers(new_reply.post.id, NOTIF_POST)
|
||||||
|
for notify_id in send_notifs_to:
|
||||||
|
if new_reply.user_id != notify_id:
|
||||||
|
new_notification = Notification(title=shorten_string(_('Reply to %(post_title)s',
|
||||||
|
post_title=new_reply.post.title), 50),
|
||||||
|
url=f"/post/{new_reply.post.id}#comment_{new_reply.id}",
|
||||||
|
user_id=notify_id, author_id=new_reply.user_id)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
user = User.query.get(notify_id)
|
||||||
|
user.unread_notifications += 1
|
||||||
|
db.session.commit()
|
||||||
|
else:
|
||||||
|
# Send notifications based on subscriptions
|
||||||
|
send_notifs_to = set(notification_subscribers(parent_reply.id, NOTIF_REPLY))
|
||||||
|
for notify_id in send_notifs_to:
|
||||||
|
if new_reply.user_id != notify_id:
|
||||||
|
new_notification = Notification(title=shorten_string(_('Reply to comment on %(post_title)s',
|
||||||
|
post_title=parent_reply.post.title), 50),
|
||||||
|
url=f"/post/{parent_reply.post.id}#comment_{new_reply.id}",
|
||||||
|
user_id=notify_id, author_id=new_reply.user_id)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
user = User.query.get(notify_id)
|
||||||
|
user.unread_notifications += 1
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def update_post_reply_from_activity(reply: PostReply, request_json: dict):
|
def update_post_reply_from_activity(reply: PostReply, request_json: dict):
|
||||||
if 'source' in request_json['object'] and \
|
if 'source' in request_json['object'] and \
|
||||||
isinstance(request_json['object']['source'], dict) and \
|
isinstance(request_json['object']['source'], dict) and \
|
||||||
|
|
30
app/cli.py
30
app/cli.py
|
@ -16,11 +16,12 @@ import os
|
||||||
|
|
||||||
from app.activitypub.signature import RsaKeys
|
from app.activitypub.signature import RsaKeys
|
||||||
from app.auth.util import random_token
|
from app.auth.util import random_token
|
||||||
from app.constants import NOTIF_COMMUNITY
|
from app.constants import NOTIF_COMMUNITY, NOTIF_POST, NOTIF_REPLY
|
||||||
from app.email import send_verification_email, send_email
|
from app.email import send_verification_email, send_email
|
||||||
from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission, Domain, ActivityPubLog, \
|
from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission, Domain, ActivityPubLog, \
|
||||||
utcnow, Site, Instance, File, Notification, Post, CommunityMember, NotificationSubscription
|
utcnow, Site, Instance, File, Notification, Post, CommunityMember, NotificationSubscription, PostReply
|
||||||
from app.utils import file_get_contents, retrieve_block_list, blocked_domains, retrieve_peertube_block_list
|
from app.utils import file_get_contents, retrieve_block_list, blocked_domains, retrieve_peertube_block_list, \
|
||||||
|
shorten_string
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
|
@ -318,6 +319,29 @@ def register(app):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
print('Done')
|
print('Done')
|
||||||
|
|
||||||
|
@app.cli.command("migrate_post_notifs")
|
||||||
|
def migrate_post_notifs():
|
||||||
|
with app.app_context():
|
||||||
|
posts = Post.query.filter(Post.notify_author == True).all()
|
||||||
|
for post in posts:
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my post %(post_title)s',
|
||||||
|
post_title=post.title)),
|
||||||
|
user_id=post.user_id, entity_id=post.id,
|
||||||
|
type=NOTIF_POST)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
post_replies = PostReply.query.filter(PostReply.notify_author == True).all()
|
||||||
|
for reply in post_replies:
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my comment on %(post_title)s',
|
||||||
|
post_title=reply.post.title)),
|
||||||
|
user_id=post.user_id, entity_id=reply.id,
|
||||||
|
type=NOTIF_REPLY)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
print('Done')
|
||||||
|
|
||||||
|
|
||||||
def parse_communities(interests_source, segment):
|
def parse_communities(interests_source, segment):
|
||||||
lines = interests_source.split("\n")
|
lines = interests_source.split("\n")
|
||||||
|
|
|
@ -497,8 +497,8 @@ def add_discussion_post(actor):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
upvote_own_post(post)
|
upvote_own_post(post)
|
||||||
if not post.community.user_is_banned(current_user):
|
|
||||||
notify_about_post(post)
|
notify_about_post(post)
|
||||||
|
|
||||||
if not community.local_only:
|
if not community.local_only:
|
||||||
federate_post(community, post)
|
federate_post(community, post)
|
||||||
|
@ -1178,7 +1178,8 @@ def community_notification(community_id: int):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
else: # no subscription yet, so make one
|
else: # no subscription yet, so make one
|
||||||
if community.id not in communities_banned_from(current_user.id):
|
if community.id not in communities_banned_from(current_user.id):
|
||||||
new_notification = NotificationSubscription(name=community.title, user_id=current_user.id, entity_id=community.id,
|
new_notification = NotificationSubscription(name=shorten_string(_('New posts in %(community_name)s', community_name=community.title)),
|
||||||
|
user_id=current_user.id, entity_id=community.id,
|
||||||
type=NOTIF_COMMUNITY)
|
type=NOTIF_COMMUNITY)
|
||||||
db.session.add(new_notification)
|
db.session.add(new_notification)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
|
@ -11,9 +11,9 @@ from pillow_heif import register_heif_opener
|
||||||
from app import db, cache, celery
|
from app import db, cache, celery
|
||||||
from app.activitypub.signature import post_request
|
from app.activitypub.signature import post_request
|
||||||
from app.activitypub.util import find_actor_or_create, actor_json_to_model, post_json_to_model, default_context, ensure_domains_match
|
from app.activitypub.util import find_actor_or_create, actor_json_to_model, post_json_to_model, default_context, ensure_domains_match
|
||||||
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE, POST_TYPE_VIDEO
|
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE, POST_TYPE_VIDEO, NOTIF_POST
|
||||||
from app.models import Community, File, BannedInstances, PostReply, PostVote, Post, utcnow, CommunityMember, Site, \
|
from app.models import Community, File, BannedInstances, PostReply, PostVote, Post, utcnow, CommunityMember, Site, \
|
||||||
Instance, Notification, User, ActivityPubLog
|
Instance, Notification, User, ActivityPubLog, NotificationSubscription
|
||||||
from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, allowlist_html, \
|
from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, allowlist_html, \
|
||||||
is_image_url, ensure_directory_exists, inbox_domain, post_ranking, shorten_string, parse_page, \
|
is_image_url, ensure_directory_exists, inbox_domain, post_ranking, shorten_string, parse_page, \
|
||||||
remove_tracking_from_link, ap_datetime, instance_banned, blocked_phrases
|
remove_tracking_from_link, ap_datetime, instance_banned, blocked_phrases
|
||||||
|
@ -387,8 +387,24 @@ def save_post(form, post: Post, type: str):
|
||||||
return
|
return
|
||||||
|
|
||||||
db.session.add(post)
|
db.session.add(post)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# Notify author about replies
|
||||||
|
# Remove any subscription that currently exists
|
||||||
|
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == post.id,
|
||||||
|
NotificationSubscription.user_id == current_user.id,
|
||||||
|
NotificationSubscription.type == NOTIF_POST).first()
|
||||||
|
if existing_notification:
|
||||||
|
db.session.delete(existing_notification)
|
||||||
|
|
||||||
|
# Add subscription if necessary
|
||||||
|
if form.notify_author.data:
|
||||||
|
new_notification = NotificationSubscription(name=post.title, user_id=current_user.id, entity_id=post.id,
|
||||||
|
type=NOTIF_POST)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
|
||||||
g.site.last_active = utcnow()
|
g.site.last_active = utcnow()
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def delete_post_from_community(post_id):
|
def delete_post_from_community(post_id):
|
||||||
|
|
|
@ -19,7 +19,7 @@ import jwt
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from app.constants import SUBSCRIPTION_NONMEMBER, SUBSCRIPTION_MEMBER, SUBSCRIPTION_MODERATOR, SUBSCRIPTION_OWNER, \
|
from app.constants import SUBSCRIPTION_NONMEMBER, SUBSCRIPTION_MEMBER, SUBSCRIPTION_MODERATOR, SUBSCRIPTION_OWNER, \
|
||||||
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING, NOTIF_USER, NOTIF_COMMUNITY, NOTIF_TOPIC
|
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING, NOTIF_USER, NOTIF_COMMUNITY, NOTIF_TOPIC, NOTIF_POST, NOTIF_REPLY
|
||||||
|
|
||||||
|
|
||||||
# datetime.utcnow() is depreciated in Python 3.12 so it will need to be swapped out eventually
|
# datetime.utcnow() is depreciated in Python 3.12 so it will need to be swapped out eventually
|
||||||
|
@ -990,6 +990,12 @@ class Post(db.Model):
|
||||||
return name
|
return name
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def notify_new_replies(self, user_id: int) -> bool:
|
||||||
|
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == self.id,
|
||||||
|
NotificationSubscription.user_id == user_id,
|
||||||
|
NotificationSubscription.type == NOTIF_POST).first()
|
||||||
|
return existing_notification is not None
|
||||||
|
|
||||||
|
|
||||||
class PostReply(db.Model):
|
class PostReply(db.Model):
|
||||||
query_class = FullTextSearchQuery
|
query_class = FullTextSearchQuery
|
||||||
|
@ -1086,6 +1092,12 @@ class PostReply(db.Model):
|
||||||
return name
|
return name
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def notify_new_replies(self, user_id: int) -> bool:
|
||||||
|
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == self.id,
|
||||||
|
NotificationSubscription.user_id == user_id,
|
||||||
|
NotificationSubscription.type == NOTIF_REPLY).first()
|
||||||
|
return existing_notification is not None
|
||||||
|
|
||||||
|
|
||||||
class Domain(db.Model):
|
class Domain(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
|
@ -9,17 +9,18 @@ from sqlalchemy import or_, desc
|
||||||
|
|
||||||
from app import db, constants, cache
|
from app import db, constants, cache
|
||||||
from app.activitypub.signature import HttpSignature, post_request
|
from app.activitypub.signature import HttpSignature, post_request
|
||||||
from app.activitypub.util import default_context
|
from app.activitypub.util import default_context, notify_about_post_reply
|
||||||
from app.community.util import save_post, send_to_remote_instance
|
from app.community.util import save_post, send_to_remote_instance
|
||||||
from app.inoculation import inoculation
|
from app.inoculation import inoculation
|
||||||
from app.post.forms import NewReplyForm, ReportPostForm, MeaCulpaForm
|
from app.post.forms import NewReplyForm, ReportPostForm, MeaCulpaForm
|
||||||
from app.community.forms import CreateLinkForm, CreateImageForm, CreateDiscussionForm, CreateVideoForm
|
from app.community.forms import CreateLinkForm, CreateImageForm, CreateDiscussionForm, CreateVideoForm
|
||||||
from app.post.util import post_replies, get_comment_branch, post_reply_count
|
from app.post.util import post_replies, get_comment_branch, post_reply_count
|
||||||
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, SUBSCRIPTION_MODERATOR, POST_TYPE_LINK, POST_TYPE_IMAGE, \
|
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, SUBSCRIPTION_MODERATOR, POST_TYPE_LINK, \
|
||||||
POST_TYPE_ARTICLE, POST_TYPE_VIDEO
|
POST_TYPE_IMAGE, \
|
||||||
|
POST_TYPE_ARTICLE, POST_TYPE_VIDEO, NOTIF_REPLY, NOTIF_POST
|
||||||
from app.models import Post, PostReply, \
|
from app.models import Post, PostReply, \
|
||||||
PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community, \
|
PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community, \
|
||||||
Topic, User, Instance
|
Topic, User, Instance, NotificationSubscription
|
||||||
from app.post import bp
|
from app.post import bp
|
||||||
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
||||||
shorten_string, markdown_to_text, gibberish, ap_datetime, return_304, \
|
shorten_string, markdown_to_text, gibberish, ap_datetime, return_304, \
|
||||||
|
@ -98,14 +99,7 @@ def show_post(post_id: int):
|
||||||
body_html=markdown_to_html(form.body.data), body_html_safe=True,
|
body_html=markdown_to_html(form.body.data), body_html_safe=True,
|
||||||
from_bot=current_user.bot, nsfw=post.nsfw, nsfl=post.nsfl,
|
from_bot=current_user.bot, nsfw=post.nsfw, nsfl=post.nsfl,
|
||||||
notify_author=form.notify_author.data, instance_id=1)
|
notify_author=form.notify_author.data, instance_id=1)
|
||||||
if post.notify_author and current_user.id != post.user_id:
|
|
||||||
notification = Notification(title=shorten_string(_('Reply from %(name)s on %(post_title)s',
|
|
||||||
name=current_user.display_name(),
|
|
||||||
post_title=post.title), 50),
|
|
||||||
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.last_active = community.last_active = utcnow()
|
||||||
post.reply_count += 1
|
post.reply_count += 1
|
||||||
community.post_reply_count += 1
|
community.post_reply_count += 1
|
||||||
|
@ -113,6 +107,17 @@ def show_post(post_id: int):
|
||||||
db.session.add(reply)
|
db.session.add(reply)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
notify_about_post_reply(None, reply)
|
||||||
|
|
||||||
|
# Subscribe to own comment
|
||||||
|
if form.notify_author.data:
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my comment on %(post_title)s',
|
||||||
|
post_title=post.title), 50),
|
||||||
|
user_id=current_user.id, entity_id=reply.id,
|
||||||
|
type=NOTIF_REPLY)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
# upvote own reply
|
# upvote own reply
|
||||||
reply.score = 1
|
reply.score = 1
|
||||||
reply.up_votes = 1
|
reply.up_votes = 1
|
||||||
|
@ -622,16 +627,19 @@ def add_reply(post_id: int, comment_id: int):
|
||||||
if blocked_phrase in reply.body:
|
if blocked_phrase in reply.body:
|
||||||
abort(401)
|
abort(401)
|
||||||
db.session.add(reply)
|
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=shorten_string(_('Reply from %(name)s on %(post_title)s',
|
|
||||||
name=current_user.display_name(),
|
|
||||||
post_title=post.title), 50),
|
|
||||||
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()
|
db.session.commit()
|
||||||
|
|
||||||
|
# Notify subscribers
|
||||||
|
notify_about_post_reply(in_reply_to, reply)
|
||||||
|
|
||||||
|
# Subscribe to own comment
|
||||||
|
if form.notify_author.data:
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my comment on %(post_title)s',
|
||||||
|
post_title=post.title), 50),
|
||||||
|
user_id=current_user.id, entity_id=reply.id,
|
||||||
|
type=NOTIF_REPLY)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
|
||||||
# upvote own reply
|
# upvote own reply
|
||||||
reply.score = 1
|
reply.score = 1
|
||||||
reply.up_votes = 1
|
reply.up_votes = 1
|
||||||
|
@ -1663,20 +1671,43 @@ def post_reply_delete(post_id: int, comment_id: int):
|
||||||
@bp.route('/post/<int:post_id>/notification', methods=['GET', 'POST'])
|
@bp.route('/post/<int:post_id>/notification', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def post_notification(post_id: int):
|
def post_notification(post_id: int):
|
||||||
|
# Toggle whether the current user is subscribed to notifications about top-level replies to this post or not
|
||||||
post = Post.query.get_or_404(post_id)
|
post = Post.query.get_or_404(post_id)
|
||||||
if post.user_id == current_user.id:
|
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == post.id,
|
||||||
post.notify_author = not post.notify_author
|
NotificationSubscription.user_id == current_user.id,
|
||||||
|
NotificationSubscription.type == NOTIF_POST).first()
|
||||||
|
if existing_notification:
|
||||||
|
db.session.delete(existing_notification)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
else: # no subscription yet, so make one
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my post %(post_title)s',
|
||||||
|
post_title=post.title)),
|
||||||
|
user_id=current_user.id, entity_id=post.id,
|
||||||
|
type=NOTIF_POST)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
return render_template('post/_post_notification_toggle.html', post=post)
|
return render_template('post/_post_notification_toggle.html', post=post)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/post_reply/<int:post_reply_id>/notification', methods=['GET', 'POST'])
|
@bp.route('/post_reply/<int:post_reply_id>/notification', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def post_reply_notification(post_reply_id: int):
|
def post_reply_notification(post_reply_id: int):
|
||||||
|
# Toggle whether the current user is subscribed to notifications about replies to this reply or not
|
||||||
post_reply = PostReply.query.get_or_404(post_reply_id)
|
post_reply = PostReply.query.get_or_404(post_reply_id)
|
||||||
if post_reply.user_id == current_user.id:
|
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == post_reply.id,
|
||||||
post_reply.notify_author = not post_reply.notify_author
|
NotificationSubscription.user_id == current_user.id,
|
||||||
|
NotificationSubscription.type == NOTIF_REPLY).first()
|
||||||
|
if existing_notification:
|
||||||
|
db.session.delete(existing_notification)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
else: # no subscription yet, so make one
|
||||||
|
new_notification = NotificationSubscription(name=shorten_string(_('Replies to my comment on %(post_title)s',
|
||||||
|
post_title=post_reply.post.title)), user_id=current_user.id, entity_id=post_reply.id,
|
||||||
|
type=NOTIF_REPLY)
|
||||||
|
db.session.add(new_notification)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
return render_template('post/_reply_notification_toggle.html', comment={'comment': post_reply})
|
return render_template('post/_reply_notification_toggle.html', comment={'comment': post_reply})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -699,6 +699,15 @@ div.navbar {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notif_toggle {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 30px;
|
||||||
|
width: 41px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
width: 96%;
|
width: 96%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,6 +290,15 @@ div.navbar {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notif_toggle {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 30px;
|
||||||
|
width: 41px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
width: 96%;
|
width: 96%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
{% include "post/_post_voting_buttons.html" %}
|
{% include "post/_post_voting_buttons.html" %}
|
||||||
</div>
|
</div>
|
||||||
<h1 class="mt-2 post_title">{{ post.title }}
|
<h1 class="mt-2 post_title">{{ post.title }}
|
||||||
{% if current_user.is_authenticated and post.user_id == current_user.id %}
|
{% if current_user.is_authenticated %}
|
||||||
{% include 'post/_post_notification_toggle.html' %}
|
{% include 'post/_post_notification_toggle.html' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if post.nsfw %}<span class="warning_badge nsfw" title="{{ _('Not safe for work') }}">nsfw</span>{% endif %}
|
{% if post.nsfw %}<span class="warning_badge nsfw" title="{{ _('Not safe for work') }}">nsfw</span>{% endif %}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<a href="{{ url_for('post.post_notification', post_id=post.id) }}" rel="nofollow"
|
<a href="{{ url_for('post.post_notification', post_id=post.id) }}" rel="nofollow" aria-live="assertive"
|
||||||
class="small fe {{ 'fe-bell' if post.notify_author else 'fe-no-bell' }} no-underline"
|
aria-label="{{ 'Notify about replies to this post.' if post.notify_new_replies(current_user.id) else 'Do not notify about new replies to this post.' }}"
|
||||||
|
class="small fe {{ 'fe-bell' if post.notify_new_replies(current_user.id) else 'fe-no-bell' }} no-underline"
|
||||||
hx-post="{{ url_for('post.post_notification', post_id=post.id) }}" hx-trigger="click throttle:1s" hx-swap="outerHTML"
|
hx-post="{{ url_for('post.post_notification', post_id=post.id) }}" hx-trigger="click throttle:1s" hx-swap="outerHTML"
|
||||||
title="{{ _('Notify about replies') }}" aria-label="{{ _('Notify about replies') }}"></a>
|
title="{{ _('Notify about replies') }}" aria-label="{{ _('Notify about replies') }}"></a>
|
|
@ -1,4 +1,4 @@
|
||||||
<a href="{{ url_for('post.post_reply_notification', post_reply_id=comment['comment'].id) }}" rel="nofollow"
|
<a href="{{ url_for('post.post_reply_notification', post_reply_id=comment['comment'].id) }}" rel="nofollow"
|
||||||
class="notif_toggle fe {{ 'fe-bell' if comment['comment'].notify_author else 'fe-no-bell' }}"
|
class="notif_toggle fe {{ 'fe-bell' if comment['comment'].notify_new_replies(current_user.id) else 'fe-no-bell' }}"
|
||||||
hx-post="{{ url_for('post.post_reply_notification', post_reply_id=comment['comment'].id) }}" hx-trigger="click throttle:1s" hx-swap="outerHTML"
|
hx-post="{{ url_for('post.post_reply_notification', post_reply_id=comment['comment'].id) }}" hx-trigger="click throttle:1s" hx-swap="outerHTML"
|
||||||
title="{{ _('Notify about replies') }}" aria-label="{{ _('Notify about replies') }}"></a>
|
title="{{ _('Notify about replies') }}" aria-label="{{ _('Notify about replies') }}"></a>
|
|
@ -128,7 +128,7 @@
|
||||||
<a href='#'><span class="fe fe-collapse"></span></a>
|
<a href='#'><span class="fe fe-collapse"></span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if current_user.is_authenticated and current_user.verified and current_user.id == comment['comment'].author.id %}
|
{% if current_user.is_authenticated and current_user.verified %}
|
||||||
{% include "post/_reply_notification_toggle.html" %}
|
{% include "post/_reply_notification_toggle.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url_for('post.post_reply_options', post_id=post.id, comment_id=comment['comment'].id) }}" class="comment_actions_link" rel="nofollow noindex" aria-label="{{ _('Comment options') }}"><span class="fe fe-options" title="Options"> </span></a>
|
<a href="{{ url_for('post.post_reply_options', post_id=post.id, comment_id=comment['comment'].id) }}" class="comment_actions_link" rel="nofollow noindex" aria-label="{{ _('Comment options') }}"><span class="fe fe-options" title="Options"> </span></a>
|
||||||
|
|
|
@ -710,9 +710,9 @@ def finalize_user_setup(user, application_required=False):
|
||||||
send_welcome_email(user, application_required)
|
send_welcome_email(user, application_required)
|
||||||
|
|
||||||
|
|
||||||
def notification_subscribers(entity_id, entity_type) -> List[int]:
|
def notification_subscribers(entity_id: int, entity_type: int) -> List[int]:
|
||||||
return list(db.session.execute(text('SELECT user_id FROM "notification_subscription" WHERE entity_id = :community_id AND type = :type '),
|
return list(db.session.execute(text('SELECT user_id FROM "notification_subscription" WHERE entity_id = :entity_id AND type = :type '),
|
||||||
{'community_id': entity_id, 'type': entity_type}).scalars())
|
{'entity_id': entity_id, 'type': entity_type}).scalars())
|
||||||
|
|
||||||
|
|
||||||
# topics, in a tree
|
# topics, in a tree
|
||||||
|
|
Loading…
Reference in a new issue