From 5408c4b0608b8578c5a0121ce0a48b2f10fb9fc6 Mon Sep 17 00:00:00 2001 From: rimu <3310831+rimu@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:06:24 +1300 Subject: [PATCH] instance blocking --- app/community/routes.py | 6 +++++- app/domain/routes.py | 8 ++++++-- app/main/routes.py | 6 +++++- app/post/routes.py | 7 +++++-- app/post/util.py | 12 +++++++++++- app/topic/routes.py | 5 ++++- app/utils.py | 8 +++++++- 7 files changed, 43 insertions(+), 9 deletions(-) diff --git a/app/community/routes.py b/app/community/routes.py index 9b9477d8..f9b58408 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -23,7 +23,7 @@ from app.community import bp from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \ shorten_string, gibberish, community_membership, ap_datetime, \ request_etag_matches, return_304, instance_banned, can_create_post, can_upvote, can_downvote, user_filters_posts, \ - joined_communities, moderating_communities, blocked_domains, mimetype_from_url + joined_communities, moderating_communities, blocked_domains, mimetype_from_url, blocked_instances from feedgen.feed import FeedGenerator from datetime import timezone, timedelta @@ -152,9 +152,13 @@ def show_community(community: Community): posts = posts.filter(Post.nsfw == False) content_filters = user_filters_posts(current_user.id) + # filter domains and instances domains_ids = blocked_domains(current_user.id) if domains_ids: posts = posts.filter(or_(Post.domain_id.not_in(domains_ids), Post.domain_id == None)) + instance_ids = blocked_instances(current_user.id) + if instance_ids: + posts = posts.filter(or_(Post.instance_id.not_in(instance_ids), Post.instance_id == None)) if sort == '' or sort == 'hot': posts = posts.order_by(desc(Post.ranking)).order_by(desc(Post.posted_at)) diff --git a/app/domain/routes.py b/app/domain/routes.py index 84d5c055..2cd68e3e 100644 --- a/app/domain/routes.py +++ b/app/domain/routes.py @@ -9,8 +9,8 @@ from app.inoculation import inoculation from app.models import Post, Domain, Community, DomainBlock from app.domain import bp from app.utils import render_template, permission_required, joined_communities, moderating_communities, \ - user_filters_posts, blocked_domains -from sqlalchemy import desc + user_filters_posts, blocked_domains, blocked_instances +from sqlalchemy import desc, or_ @bp.route('/d/', methods=['GET']) @@ -31,6 +31,10 @@ def show_domain(domain_id): else: posts = Post.query.join(Community).filter(Post.domain_id == domain.id, Community.banned == False).order_by(desc(Post.posted_at)) + instance_ids = blocked_instances(current_user.id) + if instance_ids: + posts = posts.filter(or_(Post.instance_id.not_in(instance_ids), Post.instance_id == None)) + if current_user.is_authenticated: content_filters = user_filters_posts(current_user.id) else: diff --git a/app/main/routes.py b/app/main/routes.py index 9a2b3550..b2d292a0 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -23,7 +23,8 @@ from sqlalchemy import select, desc, text from sqlalchemy_searchable import search from app.utils import render_template, get_setting, gibberish, request_etag_matches, return_304, blocked_domains, \ ap_datetime, ip_address, retrieve_block_list, shorten_string, markdown_to_text, user_filters_home, \ - joined_communities, moderating_communities, parse_page, theme_list, get_request, markdown_to_html, allowlist_html + joined_communities, moderating_communities, parse_page, theme_list, get_request, markdown_to_html, allowlist_html, \ + blocked_instances from app.models import Community, CommunityMember, Post, Site, User, utcnow, Domain, Topic, File, Instance, \ InstanceRole, Notification from PIL import Image @@ -103,6 +104,9 @@ def home_page(type, sort): domains_ids = blocked_domains(current_user.id) if domains_ids: posts = posts.filter(or_(Post.domain_id.not_in(domains_ids), Post.domain_id == None)) + instance_ids = blocked_instances(current_user.id) + if instance_ids: + posts = posts.filter(or_(Post.instance_id.not_in(instance_ids), Post.instance_id == None)) content_filters = user_filters_home(current_user.id) # Sorting diff --git a/app/post/routes.py b/app/post/routes.py index e418eb60..0c5ed613 100644 --- a/app/post/routes.py +++ b/app/post/routes.py @@ -7,7 +7,7 @@ from flask_login import login_user, logout_user, current_user, login_required from flask_babel import _ from sqlalchemy import or_, desc -from app import db, constants +from app import db, constants, cache from app.activitypub.signature import HttpSignature, post_request from app.activitypub.util import default_context from app.community.util import save_post, send_to_remote_instance @@ -22,7 +22,8 @@ from app.post import bp 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, \ request_etag_matches, ip_address, user_ip_banned, instance_banned, can_downvote, can_upvote, post_ranking, \ - reply_already_exists, reply_is_just_link_to_gif_reaction, confidence, moderating_communities, joined_communities + reply_already_exists, reply_is_just_link_to_gif_reaction, confidence, moderating_communities, joined_communities, \ + blocked_instances, blocked_domains def show_post(post_id: int): @@ -848,6 +849,7 @@ def post_block_domain(post_id: int): if not existing: db.session.add(DomainBlock(user_id=current_user.id, domain_id=post.domain_id)) db.session.commit() + cache.delete_memoized(blocked_domains, current_user.id) flash(_('Posts linking to %(name)s will be hidden.', name=post.domain.name)) return redirect(post.community.local_url()) @@ -860,6 +862,7 @@ def post_block_instance(post_id: int): if not existing: db.session.add(InstanceBlock(user_id=current_user.id, instance_id=post.instance_id)) db.session.commit() + cache.delete_memoized(blocked_instances, current_user.id) flash(_('Content from %(name)s will be hidden.', name=post.instance.domain)) return redirect(post.community.local_url()) diff --git a/app/post/util.py b/app/post/util.py index 1773c83b..948e3f1f 100644 --- a/app/post/util.py +++ b/app/post/util.py @@ -1,14 +1,20 @@ from typing import List -from sqlalchemy import desc, text +from flask_login import current_user +from sqlalchemy import desc, text, or_ from app import db from app.models import PostReply +from app.utils import blocked_instances # replies to a post, in a tree, sorted by a variety of methods def post_replies(post_id: int, sort_by: str, show_first: int = 0) -> List[PostReply]: comments = PostReply.query.filter_by(post_id=post_id) + if current_user.is_authenticated: + instance_ids = blocked_instances(current_user.id) + if instance_ids: + comments = comments.filter(or_(PostReply.instance_id.not_in(instance_ids), PostReply.instance_id == None)) if sort_by == 'hot': comments = comments.order_by(desc(PostReply.ranking)) elif sort_by == 'top': @@ -36,6 +42,10 @@ def get_comment_branch(post_id: int, comment_id: int, sort_by: str) -> List[Post return [] comments = PostReply.query.filter(PostReply.post_id == post_id) + if current_user.is_authenticated: + instance_ids = blocked_instances(current_user.id) + if instance_ids: + comments = comments.filter(or_(PostReply.instance_id.not_in(instance_ids), PostReply.instance_id == None)) if sort_by == 'hot': comments = comments.order_by(desc(PostReply.ranking)) elif sort_by == 'top': diff --git a/app/topic/routes.py b/app/topic/routes.py index db3ea61d..906ec7ee 100644 --- a/app/topic/routes.py +++ b/app/topic/routes.py @@ -16,7 +16,7 @@ from app.topic import bp from app import db, celery, cache from app.topic.forms import ChooseTopicsForm from app.utils import render_template, user_filters_posts, moderating_communities, joined_communities, \ - community_membership, blocked_domains, validation_required, mimetype_from_url + community_membership, blocked_domains, validation_required, mimetype_from_url, blocked_instances @bp.route('/topic/', methods=['GET']) @@ -65,6 +65,9 @@ def show_topic(topic_path): domains_ids = blocked_domains(current_user.id) if domains_ids: posts = posts.filter(or_(Post.domain_id.not_in(domains_ids), Post.domain_id == None)) + instance_ids = blocked_instances(current_user.id) + if instance_ids: + posts = posts.filter(or_(Post.instance_id.not_in(instance_ids), Post.instance_id == None)) # sorting if sort == '' or sort == 'hot': diff --git a/app/utils.py b/app/utils.py index 93cf3559..88b2ad6f 100644 --- a/app/utils.py +++ b/app/utils.py @@ -26,7 +26,7 @@ import re from app.email import send_welcome_email from app.models import Settings, Domain, Instance, BannedInstances, User, Community, DomainBlock, ActivityPubLog, IpBan, \ - Site, Post, PostReply, utcnow, Filter, CommunityMember + Site, Post, PostReply, utcnow, Filter, CommunityMember, InstanceBlock # Flask's render_template function, with support for themes added @@ -313,6 +313,12 @@ def blocked_domains(user_id) -> List[int]: return [block.domain_id for block in blocks] +@cache.memoize(timeout=86400) +def blocked_instances(user_id) -> List[int]: + blocks = InstanceBlock.query.filter_by(user_id=user_id) + return [block.instance_id for block in blocks] + + def retrieve_block_list(): try: response = requests.get('https://raw.githubusercontent.com/rimu/no-qanon/master/domains.txt', timeout=1)