diff --git a/app/activitypub/util.py b/app/activitypub/util.py index e87401eb..ecf3ff76 100644 --- a/app/activitypub/util.py +++ b/app/activitypub/util.py @@ -1317,11 +1317,7 @@ def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json, reas community.post_count -= 1 to_delete.author.post_count -= 1 if to_delete.url and to_delete.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(to_delete.cross_posts)).all() - to_delete.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and to_delete.id in ocp.cross_posts: - ocp.cross_posts.remove(to_delete.id) + to_delete.calculate_cross_posts(delete_only=True) db.session.commit() if to_delete.author.id != deletor.id: add_to_modlog_activitypub('delete_post', deletor, community_id=community.id, @@ -1359,17 +1355,7 @@ def restore_post_or_comment(restorer, to_restore, store_ap_json, request_json, r community.post_count += 1 to_restore.author.post_count += 1 if to_restore.url: - new_cross_posts = Post.query.filter(Post.id != to_restore.id, Post.url == to_restore.url, Post.deleted == False, - Post.posted_at > utcnow() - timedelta(days=6)).all() - for ncp in new_cross_posts: - if ncp.cross_posts is None: - ncp.cross_posts = [to_restore.id] - else: - ncp.cross_posts.append(to_restore.id) - if to_restore.cross_posts is None: - to_restore.cross_posts = [ncp.id] - else: - to_restore.cross_posts.append(ncp.id) + to_restore.calculate_cross_posts() db.session.commit() if to_restore.author.id != restorer.id: add_to_modlog_activitypub('restore_post', restorer, community_id=community.id, @@ -1410,11 +1396,7 @@ def site_ban_remove_data(blocker_id, blocked): post.deleted_by = blocker_id post.community.post_count -= 1 if post.url and post.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and post.id in ocp.cross_posts: - ocp.cross_posts.remove(post.id) + post.calculate_cross_posts(delete_only=True) blocked.post_count = 0 db.session.commit() @@ -1451,11 +1433,7 @@ def community_ban_remove_data(blocker_id, community_id, blocked): post.deleted_by = blocker_id post.community.post_count -= 1 if post.url and post.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and post.id in ocp.cross_posts: - ocp.cross_posts.remove(post.id) + post.calculate_cross_posts(delete_only=True) blocked.post_count -= 1 db.session.commit() @@ -1860,34 +1838,14 @@ def update_post_from_activity(post: Post, request_json: dict): # Fix-up cross posts (Posts which link to the same url as other posts) if post.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and post.id in ocp.cross_posts: - ocp.cross_posts.remove(post.id) - - new_cross_posts = Post.query.filter(Post.id != post.id, Post.url == new_url, Post.deleted == False, - Post.posted_at > utcnow() - timedelta(days=6)).all() - for ncp in new_cross_posts: - if ncp.cross_posts is None: - ncp.cross_posts = [post.id] - else: - ncp.cross_posts.append(post.id) - if post.cross_posts is None: - post.cross_posts = [ncp.id] - else: - post.cross_posts.append(ncp.id) + post.calculate_cross_posts(url_changed=True) else: post.type = POST_TYPE_ARTICLE post.url = '' post.image_id = None if post.cross_posts is not None: # unlikely, but not impossible - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and post.id in ocp.cross_posts: - ocp.cross_posts.remove(post.id) + post.calculate_cross_posts(delete_only=True) db.session.commit() if old_db_entry_to_delete: diff --git a/app/community/util.py b/app/community/util.py index 560529d1..789f2ad5 100644 --- a/app/community/util.py +++ b/app/community/util.py @@ -199,18 +199,7 @@ def retrieve_mods_and_backfill(community_id: int): post.ap_announce_id = activity['id'] post.ranking = post.post_ranking(post.score, post.posted_at) if post.url: - other_posts = Post.query.filter(Post.id != post.id, Post.url == post.url, Post.deleted == False, - Post.posted_at > post.posted_at - timedelta(days=3), - Post.posted_at < post.posted_at + timedelta(days=3)).all() - for op in other_posts: - if op.cross_posts is None: - op.cross_posts = [post.id] - else: - op.cross_posts.append(post.id) - if post.cross_posts is None: - post.cross_posts = [op.id] - else: - post.cross_posts.append(op.id) + post.calculate_cross_posts(backfilled=True) db.session.commit() else: activity_log.exception_message = 'Could not find or create actor' diff --git a/app/models.py b/app/models.py index 43953841..03a29d01 100644 --- a/app/models.py +++ b/app/models.py @@ -1383,18 +1383,7 @@ class Post(db.Model): # Update list of cross posts if post.url: - other_posts = Post.query.filter(Post.id != post.id, Post.url == post.url, Post.deleted == False, - Post.posted_at > post.posted_at - timedelta(days=6)).all() - for op in other_posts: - if op.cross_posts is None: - op.cross_posts = [post.id] - else: - op.cross_posts.append(post.id) - if post.cross_posts is None: - post.cross_posts = [op.id] - else: - post.cross_posts.append(op.id) - db.session.commit() + post.calculate_cross_posts() if post.community_id not in communities_banned_from(user.id): notify_about_post(post) @@ -1420,6 +1409,39 @@ class Post(db.Model): td = date - self.epoch return td.days * 86400 + td.seconds + (float(td.microseconds) / 1000000) + def calculate_cross_posts(self, delete_only=False, url_changed=False, backfilled=False): + if not self.url and not delete_only: + return + + if self.cross_posts and (url_changed or delete_only): + old_cross_posts = Post.query.filter(Post.id.in_(self.cross_posts)).all() + self.cross_posts.clear() + for ocp in old_cross_posts: + if ocp.cross_posts is not None: + ocp.cross_posts.remove(self.id) + + if delete_only: + db.session.commit() + return + + if not backfilled: + new_cross_posts = Post.query.filter(Post.id != self.id, Post.url == self.url, Post.deleted == False, + Post.posted_at > self.posted_at - timedelta(days=6)) + else: + new_cross_posts = Post.query.filter(Post.id != self.id, Post.url == self.url, Post.deleted == False, + Post.posted_at > self.posted_at - timedelta(days=3), + Post.posted_at < self.posted_at + timedelta(days=3)) + for op in new_cross_posts: + if op.cross_posts is None: + op.cross_posts = [self.id] + else: + op.cross_posts.append(self.id) + if self.cross_posts is None: + self.cross_posts = [op.id] + else: + self.cross_posts.append(op.id) + db.session.commit() + def delete_dependencies(self): db.session.query(PostBookmark).filter(PostBookmark.post_id == self.id).delete() db.session.query(PollChoiceVote).filter(PollChoiceVote.post_id == self.id).delete() diff --git a/app/post/routes.py b/app/post/routes.py index 15a0b801..33588d32 100644 --- a/app/post/routes.py +++ b/app/post/routes.py @@ -783,24 +783,7 @@ def post_edit(post_id: int): post.edited_at = utcnow() if post.url != old_url: - if post.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None: - ocp.cross_posts.remove(post.id) - - new_cross_posts = Post.query.filter(Post.id != post.id, Post.url == post.url, Post.deleted == False, - Post.posted_at > post.edited_at - timedelta(days=6)).all() - for ncp in new_cross_posts: - if ncp.cross_posts is None: - ncp.cross_posts = [post.id] - else: - ncp.cross_posts.append(post.id) - if post.cross_posts is None: - post.cross_posts = [ncp.id] - else: - post.cross_posts.append(ncp.id) + post.calculate_cross_posts(url_changed=True) db.session.commit() @@ -1054,12 +1037,7 @@ def post_delete(post_id: int): def post_delete_post(community: Community, post: Post, user_id: int, federate_all_communities=True): user: User = User.query.get(user_id) if post.url: - if post.cross_posts is not None: - old_cross_posts = Post.query.filter(Post.id.in_(post.cross_posts)).all() - post.cross_posts.clear() - for ocp in old_cross_posts: - if ocp.cross_posts is not None and post.id in ocp.cross_posts: - ocp.cross_posts.remove(post.id) + post.calculate_cross_posts(delete_only=True) post.deleted = True post.deleted_by = user_id post.author.post_count -= 1