mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 11:26:56 -08:00
API: post reports (creation)
This commit is contained in:
parent
dc5c0fd7b4
commit
eb7af155ee
7 changed files with 143 additions and 8 deletions
|
@ -1,7 +1,7 @@
|
|||
from app.api.alpha import bp
|
||||
from app.api.alpha.utils import get_site, post_site_block, \
|
||||
get_search, \
|
||||
get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, post_post, put_post, post_post_delete, \
|
||||
get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, post_post, put_post, post_post_delete, post_post_report, \
|
||||
get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe, post_reply, put_reply, post_reply_delete, post_reply_report, \
|
||||
get_community_list, get_community, post_community_follow, post_community_block, \
|
||||
get_user, post_user_block
|
||||
|
@ -195,6 +195,18 @@ def post_alpha_post_delete():
|
|||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
@bp.route('/api/alpha/post/report', methods=['POST'])
|
||||
def post_alpha_post_report():
|
||||
if not enable_api():
|
||||
return jsonify({'error': 'alpha api is not enabled'})
|
||||
try:
|
||||
auth = request.headers.get('Authorization')
|
||||
data = request.get_json(force=True) or {}
|
||||
return jsonify(post_post_report(auth, data))
|
||||
except Exception as ex:
|
||||
return jsonify({"error": str(ex)}), 400
|
||||
|
||||
|
||||
# Reply
|
||||
@bp.route('/api/alpha/comment/list', methods=['GET'])
|
||||
def get_alpha_comment_list():
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from app.api.alpha.utils.site import get_site, post_site_block
|
||||
from app.api.alpha.utils.misc import get_search
|
||||
from app.api.alpha.utils.post import get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, post_post, put_post, post_post_delete
|
||||
from app.api.alpha.utils.post import get_post_list, get_post, post_post_like, put_post_save, put_post_subscribe, post_post, put_post, post_post_delete, post_post_report
|
||||
from app.api.alpha.utils.reply import get_reply_list, post_reply_like, put_reply_save, put_reply_subscribe, post_reply, put_reply, post_reply_delete, post_reply_report
|
||||
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
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from app import cache
|
||||
from app.api.alpha.views import post_view
|
||||
from app.api.alpha.views import post_view, post_report_view
|
||||
from app.api.alpha.utils.validators import required, integer_expected, boolean_expected, string_expected
|
||||
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE, POST_TYPE_VIDEO
|
||||
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, make_post, edit_post, delete_post, restore_post
|
||||
from app.shared.post import vote_for_post, bookmark_the_post, remove_the_bookmark_from_post, toggle_post_notification, make_post, edit_post, delete_post, restore_post, report_post
|
||||
from app.utils import authorise_api_user, blocked_users, blocked_communities, blocked_instances, community_ids_from_instances, is_image_url, is_video_url
|
||||
|
||||
from datetime import timedelta
|
||||
|
@ -222,3 +222,20 @@ def post_post_delete(auth, data):
|
|||
|
||||
post_json = post_view(post=post, variant=4, user_id=user_id)
|
||||
return post_json
|
||||
|
||||
|
||||
|
||||
def post_post_report(auth, data):
|
||||
required(['post_id', 'reason'], data)
|
||||
integer_expected(['post_id'], data)
|
||||
string_expected(['reason'], data)
|
||||
|
||||
post_id = data['post_id']
|
||||
reason = data['reason']
|
||||
input = {'reason': reason, 'description': '', 'report_remote': True}
|
||||
|
||||
user_id, report = report_post(post_id, input, SRC_API, auth)
|
||||
|
||||
post_json = post_report_view(report=report, post_id=post_id, user_id=user_id)
|
||||
return post_json
|
||||
|
||||
|
|
|
@ -373,6 +373,47 @@ def reply_report_view(report, reply_id, user_id):
|
|||
return v1
|
||||
|
||||
|
||||
def post_report_view(report, post_id, user_id):
|
||||
# views/post_report_view.dart - /post/report api endpoint
|
||||
post_json = post_view(post=post_id, variant=2, user_id=user_id)
|
||||
community_json = community_view(community=post_json['post']['community_id'], variant=1, stub=True)
|
||||
|
||||
banned = db.session.execute(text('SELECT user_id FROM "community_ban" WHERE user_id = :user_id and community_id = :community_id'), {'user_id': report.reporter_id, 'community_id': community_json['id']}).scalar()
|
||||
moderator = db.session.execute(text('SELECT is_moderator FROM "community_member" WHERE user_id = :user_id and community_id = :community_id'), {'user_id': report.reporter_id, 'community_id': community_json['id']}).scalar()
|
||||
admin = db.session.execute(text('SELECT user_id FROM "user_role" WHERE user_id = :user_id and role_id = 4'), {'user_id': report.reporter_id}).scalar()
|
||||
|
||||
creator_banned_from_community = True if banned else False
|
||||
creator_is_moderator = True if moderator else False
|
||||
creator_is_admin = True if admin else False
|
||||
|
||||
v1 = {
|
||||
'post_report_view': {
|
||||
'post_report': {
|
||||
'id': report.id,
|
||||
'creator_id': report.reporter_id,
|
||||
'post_id': report.suspect_post_id,
|
||||
'original_post_name': post_json['post']['title'],
|
||||
'original_post_body': '',
|
||||
'reason': report.reasons,
|
||||
'resolved': report.status == 3,
|
||||
'published': report.created_at.isoformat() + 'Z'
|
||||
},
|
||||
'post': post_json['post'],
|
||||
'community': community_json,
|
||||
'creator': user_view(user=user_id, variant=1, stub=True),
|
||||
'post_creator': user_view(user=report.suspect_user_id, variant=1, stub=True),
|
||||
'counts': post_json['counts'],
|
||||
'creator_banned_from_community': creator_banned_from_community,
|
||||
'creator_is_moderator': creator_is_moderator,
|
||||
'creator_is_admin': creator_is_admin,
|
||||
'creator_blocked': False,
|
||||
'subscribed': post_json['subscribed'],
|
||||
'saved': post_json['saved']
|
||||
}
|
||||
}
|
||||
return v1
|
||||
|
||||
|
||||
def search_view(type):
|
||||
v1 = {
|
||||
'type_': type,
|
||||
|
|
|
@ -2,7 +2,7 @@ from app import db, cache
|
|||
from app.activitypub.util import make_image_sizes
|
||||
from app.constants import *
|
||||
from app.community.util import tags_from_string_old, end_poll_date
|
||||
from app.models import File, Language, NotificationSubscription, Poll, PollChoice, Post, PostBookmark, PostVote, utcnow
|
||||
from app.models import File, Language, Notification, NotificationSubscription, Poll, PollChoice, Post, PostBookmark, PostVote, Report, Site, User, utcnow
|
||||
from app.shared.tasks import task_selector
|
||||
from app.utils import render_template, authorise_api_user, shorten_string, gibberish, ensure_directory_exists, \
|
||||
piefed_markdown_to_lemmy_markdown, markdown_to_html, remove_tracking_from_link, domain_from_url, \
|
||||
|
@ -473,3 +473,61 @@ def restore_post(post_id, src, auth):
|
|||
return user_id, post
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
def report_post(post_id, input, src, auth=None):
|
||||
if src == SRC_API:
|
||||
post = Post.query.filter_by(id=post_id).one()
|
||||
user_id = authorise_api_user(auth)
|
||||
reason = input['reason']
|
||||
description = input['description']
|
||||
report_remote = input['report_remote']
|
||||
else:
|
||||
post = Post.query.get_or_404(post_id)
|
||||
user_id = current_user.id
|
||||
reason = input.reasons_to_string(input.reasons.data)
|
||||
description = input.description.data
|
||||
report_remote = input.report_remote.data
|
||||
|
||||
if post.reports == -1: # When a mod decides to ignore future reports, post.reports is set to -1
|
||||
if src == SRC_API:
|
||||
raise Exception('already_reported')
|
||||
else:
|
||||
flash(_('Post has already been reported, thank you!'))
|
||||
return
|
||||
|
||||
report = Report(reasons=reason, description=description, type=1, reporter_id=user_id, suspect_post_id=post.id, suspect_community_id=post.community_id,
|
||||
suspect_user_id=post.user_id, in_community_id=post.community_id, source_instance_id=1)
|
||||
db.session.add(report)
|
||||
|
||||
# Notify moderators
|
||||
already_notified = set()
|
||||
for mod in post.community.moderators():
|
||||
moderator = User.query.get(mod.user_id)
|
||||
if moderator and moderator.is_local():
|
||||
notification = Notification(user_id=mod.user_id, title=_('A comment has been reported'),
|
||||
url=f"https://{current_app.config['SERVER_NAME']}/comment/{post.id}",
|
||||
author_id=user_id)
|
||||
db.session.add(notification)
|
||||
already_notified.add(mod.user_id)
|
||||
post.reports += 1
|
||||
# todo: only notify admins for certain types of report
|
||||
for admin in Site.admins():
|
||||
if admin.id not in already_notified:
|
||||
notify = Notification(title='Suspicious content', url='/admin/reports', user_id=admin.id, author_id=user_id)
|
||||
db.session.add(notify)
|
||||
admin.unread_notifications += 1
|
||||
db.session.commit()
|
||||
|
||||
# federate report to originating instance
|
||||
if not post.community.is_local() and report_remote:
|
||||
summary = reason
|
||||
if description:
|
||||
summary += ' - ' + description
|
||||
|
||||
task_selector('report_post', user_id=user_id, post_id=post_id, summary=summary)
|
||||
|
||||
if src == SRC_API:
|
||||
return user_id, report
|
||||
else:
|
||||
return
|
||||
|
|
|
@ -2,7 +2,7 @@ from app.shared.tasks.follows import join_community, leave_community
|
|||
from app.shared.tasks.likes import vote_for_post, vote_for_reply
|
||||
from app.shared.tasks.notes import make_reply, edit_reply
|
||||
from app.shared.tasks.deletes import delete_reply, restore_reply, delete_post, restore_post
|
||||
from app.shared.tasks.flags import report_reply
|
||||
from app.shared.tasks.flags import report_reply, report_post
|
||||
from app.shared.tasks.pages import make_post, edit_post
|
||||
|
||||
from flask import current_app
|
||||
|
@ -22,7 +22,8 @@ def task_selector(task_key, send_async=True, **kwargs):
|
|||
'make_post': make_post,
|
||||
'edit_post': edit_post,
|
||||
'delete_post': delete_post,
|
||||
'restore_post': restore_post
|
||||
'restore_post': restore_post,
|
||||
'report_post': report_post
|
||||
}
|
||||
|
||||
if current_app.debug:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from app import celery
|
||||
from app.activitypub.signature import default_context, post_request
|
||||
from app.models import CommunityBan, PostReply, User
|
||||
from app.models import CommunityBan, Post, PostReply, User
|
||||
from app.utils import gibberish, instance_banned
|
||||
|
||||
from flask import current_app
|
||||
|
@ -27,6 +27,12 @@ def report_reply(send_async, user_id, reply_id, summary):
|
|||
report_object(user_id, reply, summary)
|
||||
|
||||
|
||||
@celery.task
|
||||
def report_post(send_async, user_id, post_id, summary):
|
||||
post = Post.query.filter_by(id=post_id).one()
|
||||
report_object(user_id, post, summary)
|
||||
|
||||
|
||||
def report_object(user_id, object, summary):
|
||||
user = User.query.filter_by(id=user_id).one()
|
||||
community = object.community
|
||||
|
|
Loading…
Reference in a new issue