mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-02 16:21:32 -08:00
refactor community subscription to use new subscription system #20
This commit is contained in:
parent
95172af37c
commit
708edd51b6
6 changed files with 64 additions and 25 deletions
|
@ -167,7 +167,7 @@ def domain_blocks():
|
|||
|
||||
|
||||
@bp.route('/api/v3/site')
|
||||
#@cache.cached(timeout=600)
|
||||
@cache.cached(timeout=600)
|
||||
def lemmy_site():
|
||||
return jsonify(lemmy_site_data())
|
||||
|
||||
|
|
|
@ -1535,25 +1535,27 @@ def create_post(activity_log: ActivityPubLog, community: Community, request_json
|
|||
|
||||
|
||||
def notify_about_post(post: Post):
|
||||
# todo: eventually this function could trigger a lot of DB activity. This function will need to be a celery task.
|
||||
|
||||
# Send notifications based on subscriptions to the author
|
||||
notifications_sent_to = set()
|
||||
for notify_id in post.author.notification_subscribers():
|
||||
new_notification = Notification(title=shorten_string(post.title, 50), url=f"/post/{post.id}",
|
||||
user_id=notify_id, author_id=post.user_id)
|
||||
db.session.add(new_notification)
|
||||
user = User.query.get(notify_id)
|
||||
user.unread_notifications += 1
|
||||
db.session.commit()
|
||||
notifications_sent_to.add(notify_id)
|
||||
if notify_id != post.user_id:
|
||||
new_notification = Notification(title=shorten_string(post.title, 50), url=f"/post/{post.id}",
|
||||
user_id=notify_id, author_id=post.user_id)
|
||||
db.session.add(new_notification)
|
||||
user = User.query.get(notify_id)
|
||||
user.unread_notifications += 1
|
||||
db.session.commit()
|
||||
notifications_sent_to.add(notify_id)
|
||||
|
||||
# Send notifications based on subscriptions to the community
|
||||
people_to_notify = CommunityMember.query.filter_by(community_id=post.community_id, notify_new_posts=True, is_banned=False)
|
||||
for person in people_to_notify:
|
||||
if person.user_id != post.user_id and person.user_id not in notifications_sent_to:
|
||||
new_notification = Notification(title=shorten_string(post.title, 50), url=f"/post/{post.id}", user_id=person.user_id, author_id=post.user_id)
|
||||
for notify_id in post.community.notification_subscribers():
|
||||
if notify_id != post.user_id and notify_id not in notifications_sent_to:
|
||||
new_notification = Notification(title=shorten_string(post.title, 50), url=f"/post/{post.id}",
|
||||
user_id=notify_id, author_id=post.user_id)
|
||||
db.session.add(new_notification)
|
||||
user = User.query.get(person.user_id) # todo: make this more efficient by doing a join with CommunityMember at the start of the function
|
||||
user = User.query.get(notify_id)
|
||||
user.unread_notifications += 1
|
||||
db.session.commit()
|
||||
|
||||
|
|
15
app/cli.py
15
app/cli.py
|
@ -16,9 +16,10 @@ import os
|
|||
|
||||
from app.activitypub.signature import RsaKeys
|
||||
from app.auth.util import random_token
|
||||
from app.constants import NOTIF_COMMUNITY
|
||||
from app.email import send_verification_email, send_email
|
||||
from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission, Domain, ActivityPubLog, \
|
||||
utcnow, Site, Instance, File, Notification, Post, CommunityMember
|
||||
utcnow, Site, Instance, File, Notification, Post, CommunityMember, NotificationSubscription
|
||||
from app.utils import file_get_contents, retrieve_block_list, blocked_domains, retrieve_peertube_block_list
|
||||
|
||||
|
||||
|
@ -305,6 +306,18 @@ def register(app):
|
|||
db.session.query(ActivityPubLog).filter(ActivityPubLog.created_at < utcnow() - timedelta(days=3)).delete()
|
||||
db.session.commit()
|
||||
|
||||
@app.cli.command("migrate_community_notifs")
|
||||
def migrate_community_notifs():
|
||||
with app.app_context():
|
||||
member_infos = CommunityMember.query.filter(CommunityMember.notify_new_posts == True,
|
||||
CommunityMember.is_banned == False).all()
|
||||
for member_info in member_infos:
|
||||
new_notification = NotificationSubscription(user_id=member_info.user_id, entity_id=member_info.community_id,
|
||||
type=NOTIF_COMMUNITY)
|
||||
db.session.add(new_notification)
|
||||
db.session.commit()
|
||||
print('Done')
|
||||
|
||||
|
||||
def parse_communities(interests_source, segment):
|
||||
lines = interests_source.split("\n")
|
||||
|
|
|
@ -21,10 +21,11 @@ from app.community.util import search_for_community, community_url_exists, actor
|
|||
delete_post_from_community, delete_post_reply_from_community
|
||||
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \
|
||||
SUBSCRIPTION_PENDING, SUBSCRIPTION_MODERATOR, REPORT_STATE_NEW, REPORT_STATE_ESCALATED, REPORT_STATE_RESOLVED, \
|
||||
REPORT_STATE_DISCARDED, POST_TYPE_VIDEO
|
||||
REPORT_STATE_DISCARDED, POST_TYPE_VIDEO, NOTIF_COMMUNITY
|
||||
from app.inoculation import inoculation
|
||||
from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \
|
||||
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog, Topic, Conversation, PostReply
|
||||
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog, Topic, Conversation, PostReply, \
|
||||
NotificationSubscription
|
||||
from app.community import bp
|
||||
from app.user.utils import search_for_user
|
||||
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
|
||||
|
@ -1092,7 +1093,7 @@ def community_ban_user(community_id: int, user_id: int):
|
|||
|
||||
# todo: federate ban to post author instance
|
||||
|
||||
# notify banned person
|
||||
# Notify banned person
|
||||
if user.is_local():
|
||||
cache.delete_memoized(communities_banned_from, user.id)
|
||||
cache.delete_memoized(joined_communities, user.id)
|
||||
|
@ -1107,6 +1108,11 @@ def community_ban_user(community_id: int, user_id: int):
|
|||
...
|
||||
# todo: send chatmessage to remote user and federate it
|
||||
|
||||
# Remove their notification subscription, if any
|
||||
db.session.query(NotificationSubscription).filter(NotificationSubscription.entity_id == community.id,
|
||||
NotificationSubscription.user_id == user.id,
|
||||
NotificationSubscription.type == NOTIF_COMMUNITY).delete()
|
||||
|
||||
return redirect(community.local_url())
|
||||
else:
|
||||
return render_template('community/community_ban_user.html', title=_('Ban from community'), form=form, community=community,
|
||||
|
@ -1157,7 +1163,20 @@ def community_unban_user(community_id: int, user_id: int):
|
|||
@bp.route('/<int:community_id>/notification', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def community_notification(community_id: int):
|
||||
# Toggle whether the current user is subscribed to notifications about this community's posts or not
|
||||
community = Community.query.get_or_404(community_id)
|
||||
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == community.id,
|
||||
NotificationSubscription.user_id == current_user.id,
|
||||
NotificationSubscription.type == NOTIF_COMMUNITY).first()
|
||||
if existing_notification:
|
||||
db.session.delete(existing_notification)
|
||||
db.session.commit()
|
||||
else: # no subscription yet, so make one
|
||||
if not community.user_is_banned(current_user):
|
||||
new_notification = NotificationSubscription(user_id=current_user.id, entity_id=community.id, type=NOTIF_COMMUNITY)
|
||||
db.session.add(new_notification)
|
||||
db.session.commit()
|
||||
|
||||
member_info = CommunityMember.query.filter(CommunityMember.community_id == community.id,
|
||||
CommunityMember.user_id == current_user.id).first()
|
||||
# existing community members get their notification flag toggled
|
||||
|
|
|
@ -19,7 +19,7 @@ import jwt
|
|||
import os
|
||||
|
||||
from app.constants import SUBSCRIPTION_NONMEMBER, SUBSCRIPTION_MEMBER, SUBSCRIPTION_MODERATOR, SUBSCRIPTION_OWNER, \
|
||||
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING, NOTIF_USER
|
||||
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING, NOTIF_USER, NOTIF_COMMUNITY
|
||||
|
||||
|
||||
# datetime.utcnow() is depreciated in Python 3.12 so it will need to be swapped out eventually
|
||||
|
@ -503,12 +503,15 @@ class Community(db.Model):
|
|||
return f"https://{current_app.config['SERVER_NAME']}/c/{self.ap_id}"
|
||||
|
||||
def notify_new_posts(self, user_id: int) -> bool:
|
||||
member_info = CommunityMember.query.filter(CommunityMember.community_id == self.id,
|
||||
CommunityMember.is_banned == False,
|
||||
CommunityMember.user_id == user_id).first()
|
||||
if not member_info:
|
||||
return False
|
||||
return member_info.notify_new_posts
|
||||
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == self.id,
|
||||
NotificationSubscription.user_id == user_id,
|
||||
NotificationSubscription.type == NOTIF_COMMUNITY).first()
|
||||
return existing_notification is not None
|
||||
|
||||
# ids of all the users who want to be notified when there is a post in this community
|
||||
def notification_subscribers(self):
|
||||
return list(db.session.execute(text('SELECT user_id FROM "notification_subscription" WHERE entity_id = :community_id AND type = :type '),
|
||||
{'community_id': self.id, 'type': NOTIF_COMMUNITY}).scalars())
|
||||
|
||||
# instances that have users which are members of this community. (excluding the current instance)
|
||||
def following_instances(self, include_dormant=False) -> List[Instance]:
|
||||
|
@ -836,7 +839,6 @@ class User(UserMixin, db.Model):
|
|||
return
|
||||
return User.query.get(id)
|
||||
|
||||
|
||||
def delete_dependencies(self):
|
||||
if self.cover_id:
|
||||
file = File.query.get(self.cover_id)
|
||||
|
@ -850,6 +852,8 @@ class User(UserMixin, db.Model):
|
|||
db.session.delete(file)
|
||||
if self.waiting_for_approval():
|
||||
db.session.query(UserRegistration).filter(UserRegistration.user_id == self.id).delete()
|
||||
db.session.query(NotificationSubscription).filter(NotificationSubscription.user_id == self.id).delete()
|
||||
db.session.query(Notification).filter(Notification.user_id == self.id).delete()
|
||||
|
||||
def purge_content(self):
|
||||
files = File.query.join(Post).filter(Post.user_id == self.id).all()
|
||||
|
|
|
@ -223,6 +223,7 @@ def change_settings():
|
|||
@bp.route('/user/<int:user_id>/notification', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def user_notification(user_id: int):
|
||||
# Toggle whether the current user is subscribed to notifications about this user's posts or not
|
||||
user = User.query.get_or_404(user_id)
|
||||
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == user.id,
|
||||
NotificationSubscription.user_id == current_user.id,
|
||||
|
|
Loading…
Add table
Reference in a new issue