pyfedi/app/community/routes.py

136 lines
5.8 KiB
Python
Raw Normal View History

from datetime import date, datetime, timedelta
2023-09-05 20:25:02 +12:00
from flask import render_template, redirect, url_for, flash, request, make_response, session, Markup, current_app, abort
from flask_login import login_user, logout_user, current_user
from flask_babel import _
from app import db
2023-09-03 16:30:20 +12:00
from app.activitypub.signature import RsaKeys
from app.community.forms import SearchRemoteCommunity, AddLocalCommunity
2023-09-05 20:25:02 +12:00
from app.community.util import search_for_community, community_url_exists
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER
2023-09-03 16:30:20 +12:00
from app.models import User, Community, CommunityMember
from app.community import bp
2023-09-03 16:30:20 +12:00
from app.utils import get_setting
2023-09-05 20:25:02 +12:00
from sqlalchemy import or_
@bp.route('/add_local', methods=['GET', 'POST'])
def add_local():
form = AddLocalCommunity()
2023-09-03 16:30:20 +12:00
if get_setting('allow_nsfw', False) is False:
form.nsfw.render_kw = {'disabled': True}
2023-09-05 20:25:02 +12:00
if form.validate_on_submit() and not community_url_exists(form.url.data):
# todo: more intense data validation
if form.url.data.trim().lower().startswith('/c/'):
form.url.data = form.url.data[3:]
2023-09-03 16:30:20 +12:00
private_key, public_key = RsaKeys.generate_keypair()
community = Community(title=form.community_name.data, name=form.url.data, description=form.description.data,
rules=form.rules.data, nsfw=form.nsfw.data, private_key=private_key, public_key=public_key,
subscriptions_count=1)
db.session.add(community)
db.session.commit()
membership = CommunityMember(user_id=current_user.id, community_id=community.id, is_moderator=True,
is_owner=True)
db.session.add(membership)
db.session.commit()
flash(_('Your new community has been created.'))
return redirect('/c/' + community.name)
return render_template('community/add_local.html', title=_('Create community'), form=form)
@bp.route('/add_remote', methods=['GET', 'POST'])
def add_remote():
form = SearchRemoteCommunity()
new_community = None
if form.validate_on_submit():
address = form.address.data.strip()
if address.startswith('!') and '@' in address:
new_community = search_for_community(address)
elif address.startswith('@') and '@' in address[1:]:
# todo: the user is searching for a person instead
...
elif '@' in address:
new_community = search_for_community('!' + address)
else:
message = Markup('Type address in the format !community@server.name. Search on <a href="https://lemmyverse.net/communities">Lemmyverse.net</a> to find some.')
flash(message, 'error')
return render_template('community/add_remote.html',
title=_('Add remote community'), form=form, new_community=new_community,
subscribed=current_user.subscribed(new_community) >= SUBSCRIPTION_MEMBER)
# @bp.route('/c/<actor>', methods=['GET']) - defined in activitypub/routes.py, which calls this function for user requests. A bit weird.
def show_community(community: Community):
2023-09-05 20:25:02 +12:00
mods = CommunityMember.query.filter((CommunityMember.community_id == community.id) &
(or_(
CommunityMember.is_owner,
CommunityMember.is_moderator
))
).all()
is_moderator = any(mod.user_id == current_user.id for mod in mods)
is_owner = any(mod.user_id == current_user.id and mod.is_owner == True for mod in mods)
if community.private_mods:
mod_list = []
else:
mod_user_ids = [mod.user_id for mod in mods]
mod_list = User.query.filter(User.id.in_(mod_user_ids)).all()
return render_template('community/community.html', community=community, title=community.title,
is_moderator=is_moderator, is_owner=is_owner, mods=mod_list)
@bp.route('/<actor>/subscribe', methods=['GET'])
def subscribe(actor):
actor = actor.strip()
if '@' in actor:
community = Community.query.filter_by(banned=False, ap_id=actor).first()
else:
community = Community.query.filter_by(name=actor, banned=False, ap_id=None).first()
if community is not None:
if not current_user.subscribed(community):
membership = CommunityMember(user_id=current_user.id, community_id=community.id)
db.session.add(membership)
db.session.commit()
flash('You have subscribed to ' + community.title)
referrer = request.headers.get('Referer', None)
if referrer is not None:
return redirect(referrer)
else:
return redirect('/c/' + actor)
else:
abort(404)
@bp.route('/<actor>/unsubscribe', methods=['GET'])
def unsubscribe(actor):
actor = actor.strip()
if '@' in actor:
community = Community.query.filter_by(banned=False, ap_id=actor).first()
else:
community = Community.query.filter_by(name=actor, banned=False, ap_id=None).first()
if community is not None:
subscription = current_user.subscribed(community)
if subscription:
if subscription != SUBSCRIPTION_OWNER:
db.session.query(CommunityMember).filter_by(user_id=current_user.id, community_id=community.id).delete()
db.session.commit()
flash('You are unsubscribed from ' + community.title)
else:
# todo: community deletion
flash('You need to make someone else the owner before unsubscribing.', 'warning')
# send them back where they came from
referrer = request.headers.get('Referer', None)
if referrer is not None:
return redirect(referrer)
else:
return redirect('/c/' + actor)
else:
abort(404)