/remove_header', methods=['GET', 'POST'])
@login_required
def remove_header(community_id):
community = Community.query.get_or_404(community_id)
if community.image_id:
community.image.delete_from_disk()
if community.image_id:
file = File.query.get(community.image_id)
file.delete_from_disk()
community.image_id = None
db.session.delete(file)
db.session.commit()
cache.delete_memoized(Community.header_image, community)
return ' ' + _('Banner removed!') + '
'
@bp.route('/community//delete', methods=['GET', 'POST'])
@login_required
def community_delete(community_id: int):
if current_user.banned:
return show_ban_message()
community = Community.query.get_or_404(community_id)
if community.is_owner() or current_user.is_admin():
form = DeleteCommunityForm()
if form.validate_on_submit():
if community.is_local():
community.banned = True
# todo: federate deletion out to all instances. At end of federation process, delete_dependencies() and delete community
community.delete_dependencies()
db.session.delete(community)
db.session.commit()
add_to_modlog('delete_community', community_id=community.id, link_text=community.display_name(),
link=community.link())
flash(_('Community deleted'))
return redirect('/communities')
return render_template('community/community_delete.html', title=_('Delete community'), form=form,
community=community, moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site)
else:
abort(401)
@bp.route('/community//moderators', methods=['GET', 'POST'])
@login_required
def community_mod_list(community_id: int):
if current_user.banned:
return show_ban_message()
community = Community.query.get_or_404(community_id)
if community.is_owner() or current_user.is_admin() or community.is_moderator(current_user):
moderators = User.query.filter(User.banned == False).join(CommunityMember, CommunityMember.user_id == User.id).\
filter(CommunityMember.community_id == community_id, or_(CommunityMember.is_moderator == True, CommunityMember.is_owner == True)).all()
return render_template('community/community_mod_list.html', title=_('Moderators for %(community)s', community=community.display_name()),
moderators=moderators, community=community, current="moderators",
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site
)
else:
abort(401)
@bp.route('/community//moderators/add/', methods=['GET', 'POST'])
@login_required
def community_add_moderator(community_id: int, user_id: int):
if current_user.banned:
return show_ban_message()
community = Community.query.get_or_404(community_id)
new_moderator = User.query.get_or_404(user_id)
if community.is_owner() or current_user.is_admin() and not new_moderator.banned:
existing_member = CommunityMember.query.filter(CommunityMember.user_id == new_moderator.id,
CommunityMember.community_id == community_id).first()
if existing_member:
existing_member.is_moderator = True
else:
new_member = CommunityMember(community_id=community_id, user_id=new_moderator.id, is_moderator=True)
db.session.add(new_member)
db.session.commit()
flash(_('Moderator added'))
# Notify new mod
if new_moderator.is_local():
notify = Notification(title=_('You are now a moderator of %(name)s', name=community.display_name()),
url='/c/' + community.name, user_id=new_moderator.id,
author_id=current_user.id)
new_moderator.unread_notifications += 1
db.session.add(notify)
db.session.commit()
else:
# for remote users, send a chat message to let them know
existing_conversation = Conversation.find_existing_conversation(recipient=new_moderator,
sender=current_user)
if not existing_conversation:
existing_conversation = Conversation(user_id=current_user.id)
existing_conversation.members.append(new_moderator)
existing_conversation.members.append(current_user)
db.session.add(existing_conversation)
db.session.commit()
server = current_app.config['SERVER_NAME']
send_message(f"Hi there. I've added you as a moderator to the community !{community.name}@{server}.",
existing_conversation.id)
add_to_modlog('add_mod', community_id=community_id, link_text=new_moderator.display_name(),
link=new_moderator.link())
# Flush cache
cache.delete_memoized(moderating_communities, new_moderator.id)
cache.delete_memoized(joined_communities, new_moderator.id)
cache.delete_memoized(community_moderators, community_id)
return redirect(url_for('community.community_mod_list', community_id=community.id))
@bp.route('/community//moderators/find', methods=['GET', 'POST'])
@login_required
def community_find_moderator(community_id: int):
if current_user.banned:
return show_ban_message()
community = Community.query.get_or_404(community_id)
if community.is_owner() or current_user.is_admin():
form = AddModeratorForm()
potential_moderators = None
if form.validate_on_submit():
potential_moderators = find_local_users(form.user_name.data)
return render_template('community/community_find_moderator.html', title=_('Add moderator to %(community)s',
community=community.display_name()),
community=community, form=form, potential_moderators=potential_moderators,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site
)
else:
abort(401)
@bp.route('/community//moderators/remove/', methods=['GET', 'POST'])
@login_required
def community_remove_moderator(community_id: int, user_id: int):
if current_user.banned:
return show_ban_message()
community = Community.query.get_or_404(community_id)
if community.is_owner() or current_user.is_admin() or user_id == current_user.id:
existing_member = CommunityMember.query.filter(CommunityMember.user_id == user_id,
CommunityMember.community_id == community_id).first()
if existing_member:
existing_member.is_moderator = False
db.session.commit()
flash(_('Moderator removed'))
removed_mod = User.query.get(existing_member.user_id)
add_to_modlog('remove_mod', community_id=community_id, link_text=removed_mod.display_name(),
link=removed_mod.link())
# Flush cache
cache.delete_memoized(moderating_communities, user_id)
cache.delete_memoized(joined_communities, user_id)
cache.delete_memoized(community_moderators, community_id)
return redirect(url_for('community.community_mod_list', community_id=community.id))
else:
abort(401)
@bp.route('/community//block_instance', methods=['GET', 'POST'])
@login_required
def community_block_instance(community_id: int):
community = Community.query.get_or_404(community_id)
existing = InstanceBlock.query.filter_by(user_id=current_user.id, instance_id=community.instance_id).first()
if not existing:
db.session.add(InstanceBlock(user_id=current_user.id, instance_id=community.instance_id))
db.session.commit()
flash(_('Content from %(name)s will be hidden.', name=community.instance.domain))
return redirect(community.local_url())
@bp.route('/community///ban_user_community', methods=['GET', 'POST'])
@login_required
def community_ban_user(community_id: int, user_id: int):
community = Community.query.get_or_404(community_id)
user = User.query.get_or_404(user_id)
existing = CommunityBan.query.filter_by(community_id=community.id, user_id=user.id).first()
form = BanUserCommunityForm()
if form.validate_on_submit():
# Both CommunityBan and CommunityMember need to be updated. CommunityBan is under the control of moderators while
# CommunityMember can be cleared by the user by leaving the group and rejoining. CommunityMember.is_banned stops
# posts from the community from showing up in the banned person's home feed.
if not existing:
new_ban = CommunityBan(community_id=community_id, user_id=user.id, banned_by=current_user.id,
reason=form.reason.data)
if form.ban_until.data is not None and form.ban_until.data > utcnow().date():
new_ban.ban_until = form.ban_until.data
db.session.add(new_ban)
db.session.commit()
community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first()
if community_membership_record:
community_membership_record.is_banned = True
db.session.commit()
flash(_('%(name)s has been banned.', name=user.display_name()))
if form.delete_posts.data:
posts = Post.query.filter(Post.user_id == user.id, Post.community_id == community.id).all()
for post in posts:
delete_post_from_community(post.id)
if posts:
flash(_('Posts by %(name)s have been deleted.', name=user.display_name()))
if form.delete_post_replies.data:
post_replies = PostReply.query.filter(PostReply.user_id == user.id, Post.community_id == community.id).all()
for post_reply in post_replies:
delete_post_reply_from_community(post_reply.id)
if post_replies:
flash(_('Comments by %(name)s have been deleted.', name=user.display_name()))
# todo: federate ban to post author instance
# Notify banned person
if user.is_local():
cache.delete_memoized(communities_banned_from, user.id)
cache.delete_memoized(joined_communities, user.id)
cache.delete_memoized(moderating_communities, user.id)
notify = Notification(title=shorten_string('You have been banned from ' + community.title),
url=f'/notifications', user_id=user.id,
author_id=1)
db.session.add(notify)
user.unread_notifications += 1
db.session.commit()
else:
...
# todo: send chatmessage to remote user and federate it
# Remove their notification subscription, if any
db.session.query(NotificationSubscription).filter(NotificationSubscription.entity_id == community.id,
NotificationSubscription.user_id == user.id,
NotificationSubscription.type == NOTIF_COMMUNITY).delete()
add_to_modlog('ban_user', community_id=community.id, link_text=user.display_name(), link=user.link())
return redirect(community.local_url())
else:
return render_template('community/community_ban_user.html', title=_('Ban from community'), form=form, community=community,
user=user,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
@bp.route('/community///unban_user_community', methods=['GET', 'POST'])
@login_required
def community_unban_user(community_id: int, user_id: int):
community = Community.query.get_or_404(community_id)
user = User.query.get_or_404(user_id)
existing_ban = CommunityBan.query.filter_by(community_id=community.id, user_id=user.id).first()
if existing_ban:
db.session.delete(existing_ban)
db.session.commit()
community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first()
if community_membership_record:
community_membership_record.is_banned = False
db.session.commit()
flash(_('%(name)s has been unbanned.', name=user.display_name()))
# todo: federate ban to post author instance
# notify banned person
if user.is_local():
cache.delete_memoized(communities_banned_from, user.id)
cache.delete_memoized(joined_communities, user.id)
cache.delete_memoized(moderating_communities, user.id)
notify = Notification(title=shorten_string('You have been un-banned from ' + community.title),
url=f'/notifications', user_id=user.id,
author_id=1)
db.session.add(notify)
user.unread_notifications += 1
db.session.commit()
else:
...
# todo: send chatmessage to remote user and federate it
add_to_modlog('unban_user', community_id=community.id, link_text=user.display_name(), link=user.link())
return redirect(url_for('community.community_moderate_subscribers', actor=community.link()))
@bp.route('//notification', methods=['GET', 'POST'])
@login_required
def community_notification(community_id: int):
# Toggle whether the current user is subscribed to notifications about this community's posts or not
community = Community.query.get_or_404(community_id)
existing_notification = NotificationSubscription.query.filter(NotificationSubscription.entity_id == community.id,
NotificationSubscription.user_id == current_user.id,
NotificationSubscription.type == NOTIF_COMMUNITY).first()
if existing_notification:
db.session.delete(existing_notification)
db.session.commit()
else: # no subscription yet, so make one
if community.id not in communities_banned_from(current_user.id):
new_notification = NotificationSubscription(name=shorten_string(_('New posts in %(community_name)s', community_name=community.title)),
user_id=current_user.id, entity_id=community.id,
type=NOTIF_COMMUNITY)
db.session.add(new_notification)
db.session.commit()
member_info = CommunityMember.query.filter(CommunityMember.community_id == community.id,
CommunityMember.user_id == current_user.id).first()
# existing community members get their notification flag toggled
if member_info and not member_info.is_banned:
member_info.notify_new_posts = not member_info.notify_new_posts
db.session.commit()
else: # people who are not yet members become members, with notify on.
if community.id not in communities_banned_from(current_user.id):
new_member = CommunityMember(community_id=community.id, user_id=current_user.id, notify_new_posts=True)
db.session.add(new_member)
db.session.commit()
return render_template('community/_notification_toggle.html', community=community)
@bp.route('//moderate', methods=['GET'])
@login_required
def community_moderate(actor):
if current_user.banned:
return show_ban_message()
community = actor_to_community(actor)
if community is not None:
if community.is_moderator() or current_user.is_admin():
page = request.args.get('page', 1, type=int)
search = request.args.get('search', '')
local_remote = request.args.get('local_remote', '')
reports = Report.query.filter_by(status=0, in_community_id=community.id)
if local_remote == 'local':
reports = reports.filter(Report.source_instance_id == 1)
if local_remote == 'remote':
reports = reports.filter(Report.source_instance_id != 1)
reports = reports.filter(Report.status >= 0).order_by(desc(Report.created_at)).paginate(page=page, per_page=1000, error_out=False)
next_url = url_for('community.community_moderate', page=reports.next_num) if reports.has_next else None
prev_url = url_for('community.community_moderate', page=reports.prev_num) if reports.has_prev and page != 1 else None
return render_template('community/community_moderate.html', title=_('Moderation of %(community)s', community=community.display_name()),
community=community, reports=reports, current='reports',
next_url=next_url, prev_url=prev_url,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//moderate/subscribers', methods=['GET'])
@login_required
def community_moderate_subscribers(actor):
community = actor_to_community(actor)
if community is not None:
if community.is_moderator() or current_user.is_admin():
page = request.args.get('page', 1, type=int)
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
subscribers = User.query.join(CommunityMember, CommunityMember.user_id == User.id).filter(CommunityMember.community_id == community.id)
subscribers = subscribers.filter(CommunityMember.is_banned == False)
# Pagination
subscribers = subscribers.paginate(page=page, per_page=100 if not low_bandwidth else 50, error_out=False)
next_url = url_for('community.community_moderate_subscribers', actor=actor, page=subscribers.next_num) if subscribers.has_next else None
prev_url = url_for('community.community_moderate_subscribers', actor=actor, page=subscribers.prev_num) if subscribers.has_prev and page != 1 else None
banned_people = User.query.join(CommunityBan, CommunityBan.user_id == User.id).filter(CommunityBan.community_id == community.id).all()
return render_template('community/community_moderate_subscribers.html', title=_('Moderation of %(community)s', community=community.display_name()),
community=community, current='subscribers', subscribers=subscribers, banned_people=banned_people,
next_url=next_url, prev_url=prev_url, low_bandwidth=low_bandwidth,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//moderate/wiki', methods=['GET'])
@login_required
def community_wiki_list(actor):
community = actor_to_community(actor)
if community is not None:
if community.is_moderator() or current_user.is_admin():
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
pages = CommunityWikiPage.query.filter(CommunityWikiPage.community_id == community.id).order_by(CommunityWikiPage.title).all()
return render_template('community/community_wiki_list.html', title=_('Community Wiki'), community=community,
pages=pages, low_bandwidth=low_bandwidth, current='wiki',
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//moderate/wiki/add', methods=['GET', 'POST'])
@login_required
def community_wiki_add(actor):
community = actor_to_community(actor)
if community is not None:
if community.is_moderator() or current_user.is_admin():
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
form = EditCommunityWikiPageForm()
if form.validate_on_submit():
new_page = CommunityWikiPage(community_id=community.id, slug=form.slug.data, title=form.title.data,
body=form.body.data, who_can_edit=form.who_can_edit.data)
new_page.body_html = markdown_to_html(new_page.body)
db.session.add(new_page)
db.session.commit()
initial_revision = CommunityWikiPageRevision(wiki_page_id=new_page.id, user_id=current_user.id,
community_id=community.id, title=form.title.data,
body=form.body.data, body_html=new_page.body_html)
db.session.add(initial_revision)
db.session.commit()
flash(_('Saved'))
return redirect(url_for('community.community_wiki_list', actor=community.link()))
return render_template('community/community_wiki_edit.html', title=_('Add wiki page'), community=community,
form=form, low_bandwidth=low_bandwidth, current='wiki',
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//wiki/', methods=['GET', 'POST'])
def community_wiki_view(actor, slug):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.filter_by(slug=slug, community_id=community.id).first()
if page is None:
abort(404)
else:
# Breadcrumbs
breadcrumbs = []
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Home')
breadcrumb.url = '/'
breadcrumbs.append(breadcrumb)
if community.topic_id:
topics = []
previous_topic = Topic.query.get(community.topic_id)
topics.append(previous_topic)
while previous_topic.parent_id:
topic = Topic.query.get(previous_topic.parent_id)
topics.append(topic)
previous_topic = topic
topics = list(reversed(topics))
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Topics')
breadcrumb.url = '/topics'
breadcrumbs.append(breadcrumb)
existing_url = '/topic'
for topic in topics:
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = topic.name
breadcrumb.url = f"{existing_url}/{topic.machine_name}"
breadcrumbs.append(breadcrumb)
existing_url = breadcrumb.url
else:
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Communities')
breadcrumb.url = '/communities'
breadcrumbs.append(breadcrumb)
return render_template('community/community_wiki_page_view.html', title=page.title, page=page,
community=community, breadcrumbs=breadcrumbs, is_moderator=community.is_moderator(),
is_owner=community.is_owner(),
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[
randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
@bp.route('//wiki//', methods=['GET', 'POST'])
@login_required
def community_wiki_view_revision(actor, slug, revision_id):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.filter_by(slug=slug, community_id=community.id).first()
revision: CommunityWikiPageRevision = CommunityWikiPageRevision.query.get_or_404(revision_id)
if page is None or revision is None:
abort(404)
else:
# Breadcrumbs
breadcrumbs = []
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Home')
breadcrumb.url = '/'
breadcrumbs.append(breadcrumb)
if community.topic_id:
topics = []
previous_topic = Topic.query.get(community.topic_id)
topics.append(previous_topic)
while previous_topic.parent_id:
topic = Topic.query.get(previous_topic.parent_id)
topics.append(topic)
previous_topic = topic
topics = list(reversed(topics))
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Topics')
breadcrumb.url = '/topics'
breadcrumbs.append(breadcrumb)
existing_url = '/topic'
for topic in topics:
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = topic.name
breadcrumb.url = f"{existing_url}/{topic.machine_name}"
breadcrumbs.append(breadcrumb)
existing_url = breadcrumb.url
else:
breadcrumb = namedtuple("Breadcrumb", ['text', 'url'])
breadcrumb.text = _('Communities')
breadcrumb.url = '/communities'
breadcrumbs.append(breadcrumb)
return render_template('community/community_wiki_revision_view.html', title=page.title, page=page,
community=community, breadcrumbs=breadcrumbs, is_moderator=community.is_moderator(),
is_owner=community.is_owner(), revision=revision,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[
randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
@bp.route('//wiki///revert', methods=['GET'])
@login_required
def community_wiki_revert_revision(actor, slug, revision_id):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.filter_by(slug=slug, community_id=community.id).first()
revision: CommunityWikiPageRevision = CommunityWikiPageRevision.query.get_or_404(revision_id)
if page is None or revision is None:
abort(404)
else:
if page.can_edit(current_user, community):
page.body = revision.body
page.body_html = revision.body_html
page.edited_at = utcnow()
new_revision = CommunityWikiPageRevision(wiki_page_id=page.id, user_id=current_user.id,
community_id=community.id, title=revision.title,
body=revision.body, body_html=revision.body_html)
db.session.add(new_revision)
db.session.commit()
flash(_('Reverted to old version of the page.'))
return redirect(url_for('community.community_wiki_revisions', actor=community.link(), page_id=page.id))
else:
abort(401)
@bp.route('//moderate/wiki//edit', methods=['GET', 'POST'])
@login_required
def community_wiki_edit(actor, page_id):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.get_or_404(page_id)
if page.can_edit(current_user, community):
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
form = EditCommunityWikiPageForm()
if form.validate_on_submit():
page.title = form.title.data
page.slug = form.slug.data
page.body = form.body.data
page.body_html = markdown_to_html(page.body)
page.who_can_edit = form.who_can_edit.data
page.edited_at = utcnow()
new_revision = CommunityWikiPageRevision(wiki_page_id=page.id, user_id=current_user.id,
community_id=community.id, title=form.title.data,
body=form.body.data, body_html=page.body_html)
db.session.add(new_revision)
db.session.commit()
flash(_('Saved'))
if request.args.get('return') == 'list':
return redirect(url_for('community.community_wiki_list', actor=community.link()))
elif request.args.get('return') == 'page':
return redirect(url_for('community.community_wiki_view', actor=community.link(), slug=page.slug))
else:
form.title.data = page.title
form.slug.data = page.slug
form.body.data = page.body
form.who_can_edit.data = page.who_can_edit
return render_template('community/community_wiki_edit.html', title=_('Edit wiki page'), community=community,
form=form, low_bandwidth=low_bandwidth,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//moderate/wiki//revisions', methods=['GET', 'POST'])
@login_required
def community_wiki_revisions(actor, page_id):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.get_or_404(page_id)
if page.can_edit(current_user, community):
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
revisions = CommunityWikiPageRevision.query.filter_by(wiki_page_id=page.id).\
order_by(desc(CommunityWikiPageRevision.edited_at)).all()
most_recent_revision = revisions[0].id
return render_template('community/community_wiki_revisions.html', title=_('%(title)s revisions', title=page.title),
community=community, page=page, revisions=revisions, most_recent_revision=most_recent_revision,
low_bandwidth=low_bandwidth,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('//moderate/wiki//delete', methods=['GET'])
@login_required
def community_wiki_delete(actor, page_id):
community = actor_to_community(actor)
if community is not None:
page: CommunityWikiPage = CommunityWikiPage.query.get_or_404(page_id)
if page.can_edit(current_user, community):
db.session.delete(page)
db.session.commit()
flash(_('Page deleted'))
return redirect(url_for('community.community_wiki_list', actor=community.link()))
else:
abort(404)
@bp.route('//moderate/modlog', methods=['GET'])
@login_required
def community_modlog(actor):
community = actor_to_community(actor)
if community is not None:
if community.is_moderator() or current_user.is_admin():
page = request.args.get('page', 1, type=int)
low_bandwidth = request.cookies.get('low_bandwidth', '0') == '1'
modlog_entries = ModLog.query.filter(ModLog.community_id == community.id).order_by(desc(ModLog.created_at))
# Pagination
modlog_entries = modlog_entries.paginate(page=page, per_page=100 if not low_bandwidth else 50, error_out=False)
next_url = url_for('community.community_modlog', actor=actor,
page=modlog_entries.next_num) if modlog_entries.has_next else None
prev_url = url_for('community.community_modlog', actor=actor,
page=modlog_entries.prev_num) if modlog_entries.has_prev and page != 1 else None
return render_template('community/community_modlog.html',
title=_('Mod Log of %(community)s', community=community.display_name()),
community=community, current='modlog', modlog_entries=modlog_entries,
next_url=next_url, prev_url=prev_url, low_bandwidth=low_bandwidth,
moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()),
menu_topics=menu_topics(), site=g.site,
inoculation=inoculation[randint(0, len(inoculation) - 1)] if g.site.show_inoculation_block else None
)
else:
abort(401)
else:
abort(404)
@bp.route('/community//moderate_report//escalate', methods=['GET', 'POST'])
@login_required
def community_moderate_report_escalate(community_id, report_id):
community = Community.query.get_or_404(community_id)
if community.is_moderator() or current_user.is_admin():
report = Report.query.filter_by(in_community_id=community.id, id=report_id, status=REPORT_STATE_NEW).first()
if report:
form = EscalateReportForm()
if form.validate_on_submit():
notify = Notification(title='Escalated report', url='/admin/reports', user_id=1,
author_id=current_user.id)
db.session.add(notify)
report.description = form.reason.data
report.status = REPORT_STATE_ESCALATED
db.session.commit()
flash(_('Admin has been notified about this report.'))
# todo: remove unread notifications about this report
# todo: append to mod log
return redirect(url_for('community.community_moderate', actor=community.link()))
else:
form.reason.data = report.description
return render_template('community/community_moderate_report_escalate.html', form=form)
else:
abort(401)
@bp.route('/community//moderate_report//resolve', methods=['GET', 'POST'])
@login_required
def community_moderate_report_resolve(community_id, report_id):
community = Community.query.get_or_404(community_id)
if community.is_moderator() or current_user.is_admin():
report = Report.query.filter_by(in_community_id=community.id, id=report_id).first()
if report:
form = ResolveReportForm()
if form.validate_on_submit():
report.status = REPORT_STATE_RESOLVED
# Reset the 'reports' counter on the comment, post or user
if report.suspect_post_reply_id:
post_reply = PostReply.query.get(report.suspect_post_reply_id)
post_reply.reports = 0
elif report.suspect_post_id:
post = Post.query.get(report.suspect_post_id)
post.reports = 0
elif report.suspect_user_id:
user = User.query.get(report.suspect_user_id)
user.reports = 0
db.session.commit()
# todo: remove unread notifications about this report
# todo: append to mod log
if form.also_resolve_others.data:
if report.suspect_post_reply_id:
db.session.execute(text('UPDATE "report" SET status = :new_status WHERE suspect_post_reply_id = :suspect_post_reply_id'),
{'new_status': REPORT_STATE_RESOLVED,
'suspect_post_reply_id': report.suspect_post_reply_id})
# todo: remove unread notifications about these reports
elif report.suspect_post_id:
db.session.execute(text('UPDATE "report" SET status = :new_status WHERE suspect_post_id = :suspect_post_id'),
{'new_status': REPORT_STATE_RESOLVED,
'suspect_post_id': report.suspect_post_id})
# todo: remove unread notifications about these reports
db.session.commit()
flash(_('Report resolved.'))
return redirect(url_for('community.community_moderate', actor=community.link()))
else:
return render_template('community/community_moderate_report_resolve.html', form=form)
@bp.route('/community//moderate_report//ignore', methods=['GET', 'POST'])
@login_required
def community_moderate_report_ignore(community_id, report_id):
community = Community.query.get_or_404(community_id)
if community.is_moderator() or current_user.is_admin():
report = Report.query.filter_by(in_community_id=community.id, id=report_id).first()
if report:
# Set the 'reports' counter on the comment, post or user to -1 to ignore all future reports
if report.suspect_post_reply_id:
post_reply = PostReply.query.get(report.suspect_post_reply_id)
post_reply.reports = -1
elif report.suspect_post_id:
post = Post.query.get(report.suspect_post_id)
post.reports = -1
elif report.suspect_user_id:
user = User.query.get(report.suspect_user_id)
user.reports = -1
db.session.commit()
# todo: append to mod log
if report.suspect_post_reply_id:
db.session.execute(text('UPDATE "report" SET status = :new_status WHERE suspect_post_reply_id = :suspect_post_reply_id'),
{'new_status': REPORT_STATE_DISCARDED,
'suspect_post_reply_id': report.suspect_post_reply_id})
# todo: remove unread notifications about these reports
elif report.suspect_post_id:
db.session.execute(text('UPDATE "report" SET status = :new_status WHERE suspect_post_id = :suspect_post_id'),
{'new_status': REPORT_STATE_DISCARDED,
'suspect_post_id': report.suspect_post_id})
# todo: remove unread notifications about these reports
db.session.commit()
flash(_('Report ignored.'))
return redirect(url_for('community.community_moderate', actor=community.link()))
else:
abort(404)
@bp.route('/lookup//')
def lookup(community, domain):
if domain == current_app.config['SERVER_NAME']:
return redirect('/c/' + community)
exists = Community.query.filter_by(name=community, ap_domain=domain).first()
if exists:
return redirect('/c/' + community + '@' + domain)
else:
address = '!' + community + '@' + domain
if current_user.is_authenticated:
new_community = None
new_community = search_for_community(address)
if new_community is None:
if g.site.enable_nsfw:
flash(_('Community not found.'), 'warning')
else:
flash(_('Community not found. If you are searching for a nsfw community it is blocked by this instance.'), 'warning')
else:
if new_community.banned:
flash(_('That community is banned from %(site)s.', site=g.site.name), 'warning')
return render_template('community/lookup_remote.html',
title=_('Search result for remote community'), new_community=new_community,
subscribed=community_membership(current_user, new_community) >= SUBSCRIPTION_MEMBER)
else:
# send them back where they came from
flash('Searching for remote communities requires login', 'error')
referrer = request.headers.get('Referer', None)
if referrer is not None:
return redirect(referrer)
else:
return redirect('/')
def upvote_own_post(post):
post.score = 1
post.up_votes = 1
post.ranking = post_ranking(post.score, utcnow())
vote = PostVote(user_id=current_user.id, post_id=post.id, author_id=current_user.id, effect=1)
db.session.add(vote)
db.session.commit()
cache.delete_memoized(recently_upvoted_posts, current_user.id)