Add admin mute for user reports and modmail.

remotes/1693045480750635534/spooky-22
Snakes 2022-09-01 17:29:27 -04:00
parent ba05430a80
commit c506ff0c40
10 changed files with 95 additions and 4 deletions

View File

@ -71,4 +71,31 @@ function approveComment2(post_id,button1,button2) {
document.getElementById(button1).classList.toggle("d-none");
document.getElementById(button2).classList.toggle("d-none");
}
}
}
function adminMuteUser(userId, muteStatus, buttonId) {
let form = new FormData();
form.append("formkey", formkey());
const xhr = new XMLHttpRequest();
xhr.open("POST", `/mute_user/${userId}/${muteStatus}`);
xhr.setRequestHeader('xhr', 'xhr');
xhr.onload = function() {
let data
try {data = JSON.parse(xhr.response)}
catch(e) {console.log(e)}
if (xhr.status >= 200 && xhr.status < 300 && data && data['message']) {
document.getElementById('toast-post-success-text').innerText = data["message"];
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success')).show();
} else {
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
}
};
xhr.send(form);
document.getElementById('mute-user-' + buttonId).classList.add("d-none");
}

View File

@ -279,6 +279,16 @@ ACTIONTYPES = {
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'mod_mute_user': {
"str": 'muted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-danger'
},
'mod_unmute_user': {
"str": 'unmuted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-success'
},
'monthly': {
"str": 'distributed monthly marseybux',
"icon": 'fa-sack-dollar',

View File

@ -108,6 +108,7 @@ class User(Base):
is_banned = Column(Integer, default=0)
unban_utc = Column(Integer, default=0)
ban_reason = deferred(Column(String))
is_muted = Column(Boolean, default=False, nullable=False)
club_allowed = Column(Boolean)
login_nonce = Column(Integer, default=0)
reserved = deferred(Column(String))

View File

@ -1093,6 +1093,37 @@ def unban_user(user_id, v):
if "@" in request.referrer: return redirect(user.url)
else: return {"message": f"@{user.username} was unbanned!"}
@app.post("/mute_user/<int:user_id>/<int:mute_status>")
@limiter.limit("1/second;30/minute;200/hour;1000/day")
@admin_level_required(2)
def mute_user(v, user_id, mute_status):
user = get_account(user_id)
if not user:
abort(400)
if mute_status != 0 and not user.is_muted:
user.is_muted = True
log_action = 'mod_mute_user'
success_msg = f"@{user.username} was muted!"
elif mute_status == 0 and user.is_muted:
user.is_muted = False
log_action = 'mod_unmute_user'
success_msg = f"@{user.username} was un-muted!"
else:
abort(400)
ma = ModAction(
kind=log_action,
user_id=v.id,
target_user_id=user.id,
)
g.db.add(user)
g.db.add(ma)
if 'redir' in request.values:
return redirect(user.url)
else:
return {"message": success_msg}
@app.post("/remove_post/<post_id>")
@limiter.limit("1/second;30/minute;200/hour;1000/day")

View File

@ -20,6 +20,9 @@ def flag_post(pid, v):
v.shadowbanned = 'AutoJanny'
send_repeatable_notification(CARP_ID, f"reports on {post.permalink}")
if v.is_muted:
return {"error": "You are forbidden from making reports."}
reason = reason[:100]
reason = filter_emojis_only(reason)

View File

@ -194,6 +194,9 @@ def submit_contact(v):
body = request.values.get("message")
if not body: abort(400)
if v.is_muted:
abort(403)
body = f'This message has been sent automatically to all admins via [/contact](/contact)\n\nMessage:\n\n' + body
body += process_files()

View File

@ -735,6 +735,8 @@ def messagereply(v):
if v.is_suspended_permanently and parent.sentto != 2:
return {"error": "You are permabanned and may not reply to messages."}
elif v.is_muted and parent.sentto == 2:
return {"error": "You are forbidden from replying to modmail."}
if parent.sentto == 2: user_id = None
elif v.id == user_id: user_id = parent.sentto

View File

@ -617,6 +617,10 @@
{% endif %}
{% if request.path.startswith('/notifications') and c.level == 1 and c.sentto and not c.parent_submission and c.author_id != AUTOJANNY_ID %}
{% if (v and v.admin_level >= 2) and (c.sentto == 2) and not c.author.is_muted %}
<a class="btn btn-primary" role="button" id="mute-user-{{c.id}}" onclick="adminMuteUser({{c.author_id}}, 1, {{c.id}})">Mute</a>
{% endif %}
<a class="btn btn-primary" role="button" onclick="ToggleReplyBox('reply-message-{{c.id}}')">Reply</a>
<div id="reply-message-{{c.id}}" class="d-none">
<div id="comment-form-space-{{c.id}}" class="comment-write collapsed child">
@ -873,13 +877,13 @@
{% if v %}
<script src="{{asset('js/marked.js')}}"></script>
<script src="/assets/js/comments_v.js?v=289"></script>
<script src="{{asset('js/comments_v.js')}}"></script>
{% endif %}
<script src="/assets/js/clipboard.js?v=250"></script>
{% if v and v.admin_level > 1 %}
<script src="/assets/js/comments_admin.js?v=252"></script>
{% if v and v.admin_level >= 2 %}
<script src="{{asset('js/comments_admin.js')}}"></script>
{% endif %}
{% include "expanded_image_modal.html" %}

View File

@ -320,6 +320,10 @@
<a id="unshadowban" class="{% if not u.shadowbanned %}d-none{% endif %} btn btn-success" role="button" onclick="post_toast(this,'/unshadowban/{{u.id}}','shadowban','unshadowban','d-none')">Unshadowban</a>
<a id="mute-user" class="{% if u.is_muted %}d-none{% endif %} btn btn-danger" role="button" onclick="post_toast(this,'/mute_user/{{u.id}}/1','mute-user','unmute-user','d-none')">Mute</a>
<a id="unmute-user" class="{% if not u.is_muted %}d-none{% endif %} btn btn-success" role="button" onclick="post_toast(this,'/mute_user/{{u.id}}/0','mute-user','unmute-user','d-none')">Unmute</a>
<pre></pre>
@ -666,6 +670,10 @@
<a id="unshadowban2" class="{% if not u.shadowbanned %}d-none{% endif %} btn btn-success" role="button" onclick="post_toast(this,'/unshadowban/{{u.id}}','shadowban2','unshadowban2','d-none')">Unshadowban</a>
<a id="mute-user2" class="{% if u.is_muted %}d-none{% endif %} btn btn-danger" role="button" onclick="post_toast(this,'/mute_user/{{u.id}}/1','mute-user2','unmute-user2','d-none')">Mute</a>
<a id="unmute-user2" class="{% if not u.is_muted %}d-none{% endif %} btn btn-success" role="button" onclick="post_toast(this,'/mute_user/{{u.id}}/0','mute-user2','unmute-user2','d-none')">Unmute</a>
<pre></pre>

View File

@ -20,6 +20,8 @@ set CACHE_VER = {
'js/bootstrap.js': 279,
'js/category_modal.js': 200,
'js/comments+submission_listing.js': 269,
'js/comments_admin.js': 255,
'js/comments_v.js': 290,
'js/submission_listing.js': 261,
'js/emoji_modal.js': 314,
'js/formatting.js': 240,