From f00a9b27225335a923cfe5a2938f864b2f80b097 Mon Sep 17 00:00:00 2001 From: Alan Roberts Date: Thu, 12 Sep 2024 14:45:38 -0400 Subject: [PATCH] initial pass at the subscribe step --- app/admin/routes.py | 24 +++++++++++++++---- app/community/routes.py | 53 +++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/app/admin/routes.py b/app/admin/routes.py index fb3b1788..c75ec433 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -14,12 +14,13 @@ from PIL import Image from app import db, celery, cache from app.activitypub.routes import process_inbox_request, process_delete_request from app.activitypub.signature import post_request, default_context -from app.activitypub.util import instance_allowed, instance_blocked +from app.activitypub.util import instance_allowed, instance_blocked, extract_domain_and_actor from app.admin.forms import FederationForm, SiteMiscForm, SiteProfileForm, EditCommunityForm, EditUserForm, \ EditTopicForm, SendNewsletterForm, AddUserForm, PreLoadCommunitiesForm from app.admin.util import unsubscribe_from_everything_then_delete, unsubscribe_from_community, send_newsletter, \ topics_for_form -from app.community.util import save_icon_file, save_banner_file +from app.community.util import save_icon_file, save_banner_file, search_for_community +from app.community.routes import do_subscribe from app.constants import REPORT_STATE_NEW, REPORT_STATE_ESCALATED from app.email import send_welcome_email from app.models import AllowedInstances, BannedInstances, ActivityPubLog, utcnow, Site, Community, CommunityMember, \ @@ -269,10 +270,23 @@ def admin_federation(): # sort the list based on the users_active_week key parsed_communities_sorted = sorted(cnotbanned, key=lambda c: c['counts']['users_active_week'], reverse=True) - # testing - print the top 20 in the list to a flash - top_20 = [] + # get the community urls to join + community_urls_to_join = [] for i in range(communities_to_add): - top_20.append(parsed_communities_sorted[i]['url']) + community_urls_to_join.append(parsed_communities_sorted[i]['url']) + + # loop through the list and send off the follow requests + pre_load_messages = [] + for c in community_urls_to_join: + # get the relevant url bits + server, community = extract_domain_and_actor(c) + # find the community + new_community = search_for_community('!' + community + '@' + server) + # subscribe to the community + # since this is using the alt_user_name, capture the messages + # returned by do_subscibe as well + message = do_subscribe(new_community.ap_id, main_user_name=False) + flash(_(f'top_20 == {top_20}')) # flash(_(f'leng_before == {leng_before}, leng_middle == {leng_middle}, leng_after == {leng_after}')) diff --git a/app/community/routes.py b/app/community/routes.py index 465b9880..d34dc10c 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -390,8 +390,14 @@ def show_community_rss(actor): @login_required @validation_required def subscribe(actor): + do_subscribe(actor) + +# this is separated out from the route, so it can be used by the +# admin.admin_federation.preload_form as well +def do_subscribe(actor, main_user_name=True): remote = False actor = actor.strip() + pre_load_message = {} if '@' in actor: community = Community.query.filter_by(banned=False, ap_id=actor).first() remote = True @@ -399,12 +405,19 @@ def subscribe(actor): community = Community.query.filter_by(name=actor, banned=False, ap_id=None).first() if community is not None: + pre_load_message['community'] = community.ap_id if community.id in communities_banned_from(current_user.id): - abort(401) + if main_user_name: + abort(401) + else: + pre_load_message['user_banned'] = True if community_membership(current_user, community) != SUBSCRIPTION_MEMBER and community_membership(current_user, community) != SUBSCRIPTION_PENDING: banned = CommunityBan.query.filter_by(user_id=current_user.id, community_id=community.id).first() if banned: - flash(_('You cannot join this community')) + if main_user_name: + flash(_('You cannot join this community')) + else: + pre_load_message['community_banned_by_local_instance'] = True success = True if remote: # send ActivityPub message to remote community, asking to follow. Accept message will be sent to our shared inbox @@ -413,7 +426,7 @@ def subscribe(actor): db.session.commit() if community.instance.online(): follow = { - "actor": current_user.public_url(), + "actor": current_user.public_url(main_user_name=main_user_name), "to": [community.public_url()], "object": community.public_url(), "type": "Follow", @@ -423,24 +436,44 @@ def subscribe(actor): current_user.public_url() + '#main-key', timeout=10) if success is False or isinstance(success, str): if 'is not in allowlist' in success: - flash(_('%(name)s does not allow us to join their communities.', name=community.instance.domain), 'error') + msg_to_user = f'{community.instance.domain} does not allow us to join their communities.' + if main_user_name: + flash(_(msg_to_user), 'error') + else: + pre_load_message['status'] = msg_to_user else: - flash(_("There was a problem while trying to communicate with remote server. If other people have already joined this community it won't matter."), 'error') + msg_to_user = "There was a problem while trying to communicate with remote server. If other people have already joined this community it won't matter." + if main_user_name: + flash(_(msg_to_user), 'error') + else: + pre_load_message['status'] = msg_to_user + # for local communities, joining is instant member = CommunityMember(user_id=current_user.id, community_id=community.id) db.session.add(member) db.session.commit() if success is True: - flash('You joined ' + community.title) + if main_user_name: + flash('You joined ' + community.title) + else: + pre_load_message['status'] = 'joined' referrer = request.headers.get('Referer', None) cache.delete_memoized(community_membership, current_user, community) cache.delete_memoized(joined_communities, current_user.id) - if referrer is not None: - return redirect(referrer) + if main_user_name: + if referrer is not None: + return redirect(referrer) + else: + return redirect('/c/' + actor) else: - return redirect('/c/' + actor) + return pre_load_message else: - abort(404) + if main_user_name: + abort(404) + else: + pre_load_message['community'] = actor + pre_load_message['status'] = 'community not found' + return pre_load_message @bp.route('//unsubscribe', methods=['GET'])