From 45b68c6a7f880cae60ba50a5a28e9394f857c2a3 Mon Sep 17 00:00:00 2001 From: freamon Date: Mon, 7 Oct 2024 13:57:19 +0000 Subject: [PATCH] API: process /community/block endpoint --- app/api/alpha/routes.py | 15 +++++++++-- app/api/alpha/utils/__init__.py | 2 +- app/api/alpha/utils/community.py | 24 ++++++++++++++++- app/api/alpha/utils/post.py | 5 +++- app/api/alpha/utils/site.py | 7 +++-- app/api/alpha/views.py | 14 ++++++++-- app/shared/community.py | 46 ++++++++++++++++++++++++++------ 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/app/api/alpha/routes.py b/app/api/alpha/routes.py index fe7f9e2c..02b9f7d0 100644 --- a/app/api/alpha/routes.py +++ b/app/api/alpha/routes.py @@ -2,7 +2,7 @@ from app.api.alpha import bp from app.api.alpha.utils import get_site, \ get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, \ get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe, \ - get_community_list, get_community, post_community_follow, \ + get_community_list, get_community, post_community_follow, post_community_block, \ get_user, post_user_block from app.shared.auth import log_user_in @@ -58,6 +58,18 @@ def post_alpha_community_follow(): return jsonify({"error": str(ex)}), 400 +@bp.route('/api/alpha/community/block', methods=['POST']) +def post_alpha_community_block(): + if not current_app.debug: + return jsonify({'error': 'alpha api routes only available in debug mode'}) + try: + auth = request.headers.get('Authorization') + data = request.get_json(force=True) or {} + return jsonify(post_community_block(auth, data)) + except Exception as ex: + return jsonify({"error": str(ex)}), 400 + + # Post @bp.route('/api/alpha/post/list', methods=['GET']) def get_alpha_post_list(): @@ -226,7 +238,6 @@ def alpha_miscellaneous(): @bp.route('/api/alpha/community', methods=['POST']) @bp.route('/api/alpha/community', methods=['PUT']) @bp.route('/api/alpha/community/hide', methods=['PUT']) -@bp.route('/api/alpha/community/block', methods=['POST']) @bp.route('/api/alpha/community/delete', methods=['POST']) @bp.route('/api/alpha/community/remove', methods=['POST']) @bp.route('/api/alpha/community/transfer', methods=['POST']) diff --git a/app/api/alpha/utils/__init__.py b/app/api/alpha/utils/__init__.py index da561671..7c22f790 100644 --- a/app/api/alpha/utils/__init__.py +++ b/app/api/alpha/utils/__init__.py @@ -1,7 +1,7 @@ from app.api.alpha.utils.site import get_site from app.api.alpha.utils.post import get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe from app.api.alpha.utils.reply import get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe -from app.api.alpha.utils.community import get_community, get_community_list, post_community_follow +from app.api.alpha.utils.community import get_community, get_community_list, post_community_follow, post_community_block from app.api.alpha.utils.user import get_user, post_user_block diff --git a/app/api/alpha/utils/community.py b/app/api/alpha/utils/community.py index b8463f3d..b573af73 100644 --- a/app/api/alpha/utils/community.py +++ b/app/api/alpha/utils/community.py @@ -3,7 +3,7 @@ from app.api.alpha.views import community_view from app.api.alpha.utils.validators import required, integer_expected, boolean_expected from app.utils import authorise_api_user from app.models import Community, CommunityMember -from app.shared.community import join_community, leave_community +from app.shared.community import join_community, leave_community, block_community, unblock_community from app.utils import communities_banned_from @@ -103,3 +103,25 @@ def post_community_follow(auth, data): return community_json except: raise + + +def post_community_block(auth, data): + try: + required(['community_id', 'block'], data) + integer_expected(['community_id'], data) + boolean_expected(['block'], data) + except: + raise + + community_id = data['community_id'] + block = data['block'] + + try: + if block == True: + user_id = block_community(community_id, SRC_API, auth) + else: + user_id = unblock_community(community_id, SRC_API, auth) + community_json = community_view(community=community_id, variant=5, user_id=user_id) + return community_json + except: + raise diff --git a/app/api/alpha/utils/post.py b/app/api/alpha/utils/post.py index 2bdf4dc4..a6c7e0a5 100644 --- a/app/api/alpha/utils/post.py +++ b/app/api/alpha/utils/post.py @@ -3,7 +3,7 @@ from app.api.alpha.views import post_view from app.api.alpha.utils.validators import required, integer_expected, boolean_expected from app.models import Post, Community, CommunityMember, utcnow from app.shared.post import vote_for_post, bookmark_the_post, remove_the_bookmark_from_post, toggle_post_notification -from app.utils import authorise_api_user, blocked_users +from app.utils import authorise_api_user, blocked_users, blocked_communities from datetime import timedelta from sqlalchemy import desc @@ -32,6 +32,9 @@ def cached_post_list(type, sort, user_id, community_id, community_name, person_i blocked_person_ids = blocked_users(user_id) if blocked_person_ids: posts = posts.filter(Post.user_id.not_in(blocked_person_ids)) + blocked_community_ids = blocked_communities(user_id) + if blocked_community_ids: + posts = posts.filter(Post.community_id.not_in(blocked_community_ids)) if sort == "Hot": posts = posts.order_by(desc(Post.ranking)).order_by(desc(Post.posted_at)) diff --git a/app/api/alpha/utils/site.py b/app/api/alpha/utils/site.py index 93864464..0bc56c75 100644 --- a/app/api/alpha/utils/site.py +++ b/app/api/alpha/utils/site.py @@ -1,5 +1,5 @@ from app import db -from app.api.alpha.views import user_view +from app.api.alpha.views import user_view, community_view from app.utils import authorise_api_user from app.models import Language @@ -70,7 +70,7 @@ def get_site(auth): }, #"moderates": [], #"follows": [], - "community_blocks": [], # TODO + "community_blocks": [], "instance_blocks": [], # TODO "person_blocks": [], "discussion_languages": [] # TODO @@ -87,6 +87,9 @@ def get_site(auth): blocked_ids = db.session.execute(text('SELECT blocked_id FROM "user_block" WHERE blocker_id = :blocker_id'), {"blocker_id": user.id}).scalars() for blocked_id in blocked_ids: my_user['person_blocks'].append({'person': user_view(user, variant=1, stub=True), 'target': user_view(blocked_id, variant=1, stub=True)}) + blocked_ids = db.session.execute(text('SELECT community_id FROM "community_block" WHERE user_id = :user_id'), {"user_id": user.id}).scalars() + for blocked_id in blocked_ids: + my_user['community_blocks'].append({'person': user_view(user, variant=1, stub=True), 'community': community_view(blocked_id, variant=1, stub=True)}) data = { "version": "1.0.0", "site": site diff --git a/app/api/alpha/views.py b/app/api/alpha/views.py index b1b0dce0..4e2ea483 100644 --- a/app/api/alpha/views.py +++ b/app/api/alpha/views.py @@ -3,6 +3,7 @@ from __future__ import annotations from app import cache, db from app.constants import * from app.models import Community, CommunityMember, Post, PostReply, PostVote, User +from app.utils import blocked_communities from sqlalchemy import text @@ -211,10 +212,11 @@ def community_view(community: Community | int | str, variant, stub=False, user_i counts.update({'published': community.created_at.isoformat() + 'Z'}) if user_id: followed = db.session.execute(text('SELECT user_id FROM "community_member" WHERE community_id = :community_id and user_id = :user_id'), {"community_id": community.id, "user_id": user_id}).scalar() + blocked = True if community.id in blocked_communities(user_id) else False else: - followed = False + followed = blocked = False subscribe_type = 'Subscribed' if followed else 'NotSubscribed' - v2 = {'community': community_view(community=community, variant=1, stub=stub), 'subscribed': subscribe_type, 'blocked': False, 'counts': counts} + v2 = {'community': community_view(community=community, variant=1, stub=stub), 'subscribed': subscribe_type, 'blocked': blocked, 'counts': counts} return v2 # Variant 3 - models/community/get_community_response.dart - /community api endpoint @@ -232,6 +234,14 @@ def community_view(community: Community | int | str, variant, stub=False, user_i 'discussion_languages': []} return v4 + # Variant 5 - models/community/block_community_response.dart - /community/block api endpoint + if variant == 5: + block = db.session.execute(text('SELECT user_id FROM "community_block" WHERE user_id = :user_id and community_id = :community_id'), {'user_id': user_id, 'community_id': community.id}).scalar() + blocked = True if block else False + v5 = {'community_view': community_view(community=community, variant=2, stub=False, user_id=user_id), + 'blocked': blocked} + return v5 + # would be better to incrementally add to a post_reply.path field @cache.memoize(timeout=86400) diff --git a/app/shared/community.py b/app/shared/community.py index 4f3bd6b1..4b79b84e 100644 --- a/app/shared/community.py +++ b/app/shared/community.py @@ -1,8 +1,8 @@ from app import db, cache from app.activitypub.signature import post_request from app.constants import * -from app.models import Community, CommunityBan, CommunityJoinRequest, CommunityMember -from app.utils import authorise_api_user, community_membership, joined_communities, gibberish +from app.models import Community, CommunityBan, CommunityBlock, CommunityJoinRequest, CommunityMember +from app.utils import authorise_api_user, blocked_communities, community_membership, joined_communities, gibberish from flask import abort, current_app, flash from flask_babel import _ @@ -181,13 +181,43 @@ def leave_community(community_id: int, src, auth=None): return +def block_community(community_id, src, auth=None): + if src == SRC_API: + try: + user_id = authorise_api_user(auth) + except: + raise + else: + user_id = current_user.id + + existing = CommunityBlock.query.filter_by(user_id=user_id, community_id=community_id).first() + if not existing: + db.session.add(CommunityBlock(user_id=user_id, community_id=community_id)) + db.session.commit() + cache.delete_memoized(blocked_communities, user_id) + + if src == SRC_API: + return user_id + else: + return # let calling function handle confirmation flash message and redirect +def unblock_community(community_id, src, auth=None): + if src == SRC_API: + try: + user_id = authorise_api_user(auth) + except: + raise + else: + user_id = current_user.id + existing_block = CommunityBlock.query.filter_by(user_id=user_id, community_id=community_id).first() + if existing_block: + db.session.delete(existing_block) + db.session.commit() + cache.delete_memoized(blocked_communities, user_id) - - - - - - + if src == SRC_API: + return user_id + else: + return # let calling function handle confirmation flash message and redirect