MarseyWorld/files/routes/admin.py

1698 lines
44 KiB
Python
Raw Normal View History

2021-10-15 14:08:27 +00:00
import time
from os import remove
from PIL import Image as IMAGE
2022-01-14 06:59:17 +00:00
2021-10-15 14:08:27 +00:00
from files.helpers.wrappers import *
from files.helpers.alerts import *
from files.helpers.sanitize import *
from files.helpers.security import *
from files.helpers.get import *
from files.helpers.images import *
from files.helpers.const import *
from files.classes import *
from flask import *
2022-01-14 06:59:17 +00:00
from files.__main__ import app, cache, limiter
2021-10-15 14:08:27 +00:00
from .front import frontlist
2022-03-19 15:33:02 +00:00
from files.helpers.discord import add_role
2021-12-20 20:03:59 +00:00
from datetime import datetime
2021-12-31 13:02:54 +00:00
import requests
2022-02-26 15:56:44 +00:00
from urllib.parse import quote, urlencode
2021-10-15 14:08:27 +00:00
GUMROAD_ID = environ.get("GUMROAD_ID", "tfcvri").strip()
GUMROAD_TOKEN = environ.get("GUMROAD_TOKEN", "").strip()
2021-12-28 04:47:02 +00:00
2021-12-20 20:03:59 +00:00
month = datetime.now().strftime('%B')
2021-10-15 14:08:27 +00:00
2022-03-19 14:34:24 +00:00
2022-03-21 21:35:38 +00:00
@app.get('/admin/merge/<id1>/<id2>')
2022-02-26 14:21:07 +00:00
@admin_level_required(3)
def merge(v, id1, id2):
2022-02-26 15:46:11 +00:00
if v.id != AEVANN_ID: abort(403)
2022-03-21 21:36:57 +00:00
if time.time() - session.get('verified', 0) > 3:
2022-02-26 15:36:06 +00:00
session.pop("session_id", None)
session.pop("lo_user", None)
2022-02-26 15:56:44 +00:00
path = request.path
qs = urlencode(dict(request.values))
argval = quote(f"{path}?{qs}", safe='')
2022-04-02 17:11:35 +00:00
return redirect(f"/login?redirect={argval}")
2022-02-26 15:36:06 +00:00
2022-02-26 14:39:47 +00:00
user1 = get_account(id1)
user2 = get_account(id2)
2022-02-26 14:21:07 +00:00
2022-02-26 14:39:47 +00:00
awards = g.db.query(AwardRelationship).filter_by(user_id=user2.id)
comments = g.db.query(Comment).filter_by(author_id=user2.id)
submissions = g.db.query(Submission).filter_by(author_id=user2.id)
badges = g.db.query(Badge).filter_by(user_id=user2.id)
mods = g.db.query(Mod).filter_by(user_id=user2.id)
2022-02-26 15:13:01 +00:00
exiles = g.db.query(Exile).filter_by(user_id=user2.id)
2022-02-26 14:39:47 +00:00
for award in awards:
2022-02-26 14:21:07 +00:00
award.user_id = user1.id
g.db.add(award)
2022-02-26 14:39:47 +00:00
for comment in comments:
2022-02-26 14:21:07 +00:00
comment.author_id = user1.id
g.db.add(comment)
2022-02-26 14:39:47 +00:00
for submission in submissions:
2022-02-26 14:21:07 +00:00
submission.author_id = user1.id
g.db.add(submission)
2022-02-26 14:39:47 +00:00
for badge in badges:
if not user1.has_badge(badge.badge_id):
badge.user_id = user1.id
g.db.add(badge)
2022-02-26 16:00:49 +00:00
g.db.flush()
2022-02-26 14:39:47 +00:00
for mod in mods:
if not user1.mods(mod.sub):
mod.user_id = user1.id
g.db.add(mod)
2022-02-26 16:00:49 +00:00
g.db.flush()
2022-02-26 15:13:01 +00:00
for exile in exiles:
if not user1.exiled_from(exile.sub):
exile.user_id = user1.id
g.db.add(exile)
2022-02-26 16:00:49 +00:00
g.db.flush()
2022-02-26 14:21:07 +00:00
for kind in ('comment_count', 'post_count', 'winnings', 'received_award_count', 'coins_spent', 'lootboxes_bought', 'coins', 'truecoins', 'procoins', 'subs_created'):
2022-02-26 14:39:47 +00:00
amount = getattr(user1, kind) + getattr(user2, kind)
setattr(user1, kind, amount)
2022-02-26 14:21:07 +00:00
setattr(user2, kind, 0)
g.db.add(user1)
g.db.add(user2)
g.db.commit()
2022-02-26 14:39:47 +00:00
cache.clear()
2022-02-26 18:23:04 +00:00
return redirect(user1.url)
2022-02-26 14:21:07 +00:00
2022-03-21 21:35:38 +00:00
@app.get('/admin/merge_all/<id>')
2022-02-26 14:53:42 +00:00
@admin_level_required(3)
def merge_all(v, id):
if v.id != AEVANN_ID: abort(403)
2022-02-26 15:46:11 +00:00
2022-03-21 21:36:57 +00:00
if time.time() - session.get('verified', 0) > 3:
2022-02-26 15:46:11 +00:00
session.pop("session_id", None)
session.pop("lo_user", None)
2022-02-26 15:56:44 +00:00
path = request.path
qs = urlencode(dict(request.values))
argval = quote(f"{path}?{qs}", safe='')
2022-04-02 17:11:35 +00:00
return redirect(f"/login?redirect={argval}")
2022-02-26 15:46:11 +00:00
2022-02-26 14:53:42 +00:00
user = get_account(id)
alt_ids = [x.id for x in user.alts_unique]
2022-02-26 15:54:39 +00:00
things = g.db.query(AwardRelationship).filter(AwardRelationship.user_id.in_(alt_ids)).all() + g.db.query(Mod).filter(Mod.user_id.in_(alt_ids)).all() + g.db.query(Exile).filter(Exile.user_id.in_(alt_ids)).all()
2022-02-26 14:53:42 +00:00
for thing in things:
thing.user_id = user.id
g.db.add(thing)
things = g.db.query(Submission).filter(Submission.author_id.in_(alt_ids)).all() + g.db.query(Comment).filter(Comment.author_id.in_(alt_ids)).all()
for thing in things:
thing.author_id = user.id
g.db.add(thing)
2022-02-26 15:54:39 +00:00
2022-02-26 16:00:49 +00:00
badges = g.db.query(Badge).filter(Badge.user_id.in_(alt_ids)).all()
for badge in badges:
2022-02-26 15:54:39 +00:00
if not user.has_badge(badge.badge_id):
badge.user_id = user.id
g.db.add(badge)
2022-02-26 16:00:49 +00:00
g.db.flush()
2022-02-26 15:54:39 +00:00
2022-02-26 14:53:42 +00:00
for alt in user.alts_unique:
for kind in ('comment_count', 'post_count', 'winnings', 'received_award_count', 'coins_spent', 'lootboxes_bought', 'coins', 'truecoins', 'procoins', 'subs_created'):
amount = getattr(user, kind) + getattr(alt, kind)
setattr(user, kind, amount)
setattr(alt, kind, 0)
g.db.add(alt)
g.db.add(user)
g.db.commit()
cache.clear()
2022-02-26 18:23:04 +00:00
return redirect(user.url)
2022-02-26 14:53:42 +00:00
2022-02-26 14:21:07 +00:00
2022-02-17 07:02:44 +00:00
if SITE_NAME == 'PCM':
@app.get('/admin/sidebar')
@admin_level_required(3)
def get_sidebar(v):
try:
with open(f'files/templates/sidebar_{SITE_NAME}.html', 'r', encoding="utf-8") as f: sidebar = f.read()
except:
sidebar = None
return render_template('admin/sidebar.html', v=v, sidebar=sidebar)
@app.post('/admin/sidebar')
@limiter.limit("1/second;30/minute;200/hour;1000/day")
@admin_level_required(3)
def post_sidebar(v):
text = request.values.get('sidebar', '').strip()
with open(f'files/templates/sidebar_{SITE_NAME}.html', 'w+', encoding="utf-8") as f: f.write(text)
with open(f'files/templates/sidebar_{SITE_NAME}.html', 'r', encoding="utf-8") as f: sidebar = f.read()
ma = ModAction(
kind="change_sidebar",
user_id=v.id,
)
g.db.add(ma)
g.db.commit()
return render_template('admin/sidebar.html', v=v, sidebar=sidebar, msg='Sidebar edited successfully!')
2022-01-18 00:09:40 +00:00
2022-01-03 10:32:31 +00:00
@app.post("/@<username>/make_admin")
@admin_level_required(3)
def make_admin(v, username):
user = get_user(username)
if not user: abort(404)
user.admin_level = 2
g.db.add(user)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="make_admin",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2022-01-03 10:32:31 +00:00
g.db.commit()
return {"message": "User has been made admin!"}
@app.post("/@<username>/remove_admin")
@admin_level_required(3)
def remove_admin(v, username):
user = get_user(username)
if not user: abort(404)
user.admin_level = 0
g.db.add(user)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="remove_admin",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2022-01-03 10:32:31 +00:00
g.db.commit()
return {"message": "Admin removed!"}
2021-12-23 18:59:49 +00:00
@app.post("/distribute/<comment>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-12-11 03:32:43 +00:00
@admin_level_required(3)
2021-12-23 18:46:07 +00:00
def distribute(v, comment):
2022-01-17 12:07:50 +00:00
autobetter = g.db.query(User).filter_by(id=AUTOBETTER_ID).one_or_none()
if autobetter.coins == 0: return {"error": "@AutoBetter has 0 coins"}
2021-12-23 18:48:57 +00:00
try: comment = int(comment)
2021-12-11 03:18:14 +00:00
except: abort(400)
2022-01-16 00:10:33 +00:00
post = g.db.query(Comment.parent_submission).filter_by(id=comment).one_or_none()[0]
post = g.db.query(Submission).filter_by(id=post).one_or_none()
2021-12-23 18:18:25 +00:00
pool = 0
for option in post.bet_options: pool += option.upvotes
2021-12-23 18:30:34 +00:00
pool *= 200
2022-01-17 11:47:30 +00:00
autobetter.coins -= pool
if autobetter.coins < 0: autobetter.coins = 0
g.db.add(autobetter)
2021-12-23 18:43:52 +00:00
votes = g.db.query(CommentVote).filter_by(comment_id=comment)
2021-12-23 18:18:25 +00:00
coinsperperson = int(pool / votes.count())
2022-02-24 13:20:48 +00:00
cid = notif_comment(f"You won {coinsperperson} coins betting on [{post.title}]({post.shortlink}) :marseyparty:")
2021-12-11 03:07:51 +00:00
for vote in votes:
u = vote.user
u.coins += coinsperperson
2021-12-20 20:03:59 +00:00
add_notif(cid, u.id)
2021-12-11 03:07:51 +00:00
2022-02-24 13:20:48 +00:00
cid = notif_comment(f"You lost the 200 coins you bet on [{post.title}]({post.shortlink}) :marseylaugh:")
2021-12-23 18:39:39 +00:00
cids = [x.id for x in post.bet_options]
2021-12-23 18:43:52 +00:00
cids.remove(comment)
2021-12-23 18:28:20 +00:00
votes = g.db.query(CommentVote).filter(CommentVote.comment_id.in_(cids)).all()
2021-12-23 18:29:38 +00:00
for vote in votes: add_notif(cid, vote.user.id)
2021-12-23 18:28:20 +00:00
2022-01-16 00:10:33 +00:00
post.body += '\n\nclosed'
g.db.add(post)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="distribute",
user_id=v.id,
2022-03-01 00:20:11 +00:00
target_comment_id=comment
2022-02-04 13:11:11 +00:00
)
g.db.add(ma)
2021-12-11 03:07:51 +00:00
g.db.commit()
2021-12-23 18:59:49 +00:00
return {"message": f"Each winner has received {coinsperperson} coins!"}
2021-12-11 03:07:51 +00:00
2021-10-15 14:08:27 +00:00
@app.post("/@<username>/revert_actions")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-12-17 03:25:05 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def revert_actions(v, username):
2021-12-17 03:25:05 +00:00
user = get_user(username)
if not user: abort(404)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="revert",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2021-12-17 03:25:05 +00:00
cutoff = int(time.time()) - 86400
2021-12-17 03:44:26 +00:00
posts = [x[0] for x in g.db.query(ModAction.target_submission_id).filter(ModAction.user_id == user.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_post').all()]
2021-12-17 03:52:05 +00:00
posts = g.db.query(Submission).filter(Submission.id.in_(posts)).all()
2021-12-17 03:50:55 +00:00
2021-12-17 03:44:26 +00:00
comments = [x[0] for x in g.db.query(ModAction.target_comment_id).filter(ModAction.user_id == user.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_comment').all()]
2021-12-17 03:52:05 +00:00
comments = g.db.query(Comment).filter(Comment.id.in_(comments)).all()
2021-12-17 03:50:55 +00:00
2021-12-17 03:25:05 +00:00
for item in posts + comments:
item.is_banned = False
2022-04-22 14:51:40 +00:00
item.ban_reason = None
2021-12-17 03:25:05 +00:00
g.db.add(item)
2021-12-17 03:48:44 +00:00
users = (x[0] for x in g.db.query(ModAction.target_user_id).filter(ModAction.user_id == user.id, ModAction.created_utc > cutoff, ModAction.kind.in_(('shadowban', 'ban_user'))).all())
2021-12-17 03:51:21 +00:00
users = g.db.query(User).filter(User.id.in_(users)).all()
2021-12-17 03:50:55 +00:00
2021-12-17 03:25:05 +00:00
for user in users:
user.shadowbanned = None
user.is_banned = 0
user.unban_utc = 0
user.ban_evade = 0
2022-02-22 11:43:38 +00:00
send_repeatable_notification(user.id, f"@{v.username} has unbanned you!")
2021-12-17 03:25:05 +00:00
g.db.add(user)
for u in user.alts:
u.shadowbanned = None
u.is_banned = 0
u.unban_utc = 0
u.ban_evade = 0
2022-02-22 11:43:38 +00:00
send_repeatable_notification(u.id, f"@{v.username} has unbanned you!")
2021-12-17 03:25:05 +00:00
g.db.add(u)
2021-10-15 14:08:27 +00:00
2021-12-17 03:25:05 +00:00
g.db.commit()
2021-10-15 14:08:27 +00:00
return {"message": "Admin actions reverted!"}
@app.post("/@<username>/club_allow")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def club_allow(v, username):
u = get_user(username, v=v)
if not u: abort(404)
if u.admin_level >= v.admin_level: return {"error": "noob"}
u.club_allowed = True
g.db.add(u)
for x in u.alts_unique:
x.club_allowed = True
g.db.add(x)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="club_allow",
user_id=v.id,
target_user_id=u.id
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-01-19 09:07:16 +00:00
return {"message": f"@{username} has been allowed into the {CC_TITLE}!"}
2021-10-15 14:08:27 +00:00
@app.post("/@<username>/club_ban")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def club_ban(v, username):
u = get_user(username, v=v)
if not u: abort(404)
if u.admin_level >= v.admin_level: return {"error": "noob"}
u.club_allowed = False
for x in u.alts_unique:
u.club_allowed = False
g.db.add(x)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="club_ban",
user_id=v.id,
target_user_id=u.id
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-01-19 09:07:16 +00:00
return {"message": f"@{username} has been kicked from the {CC_TITLE}. Deserved."}
2021-10-15 14:08:27 +00:00
2021-11-26 19:28:55 +00:00
@app.post("/@<username>/make_meme_admin")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-01-31 23:10:24 +00:00
@admin_level_required(3)
2021-11-26 19:28:55 +00:00
def make_meme_admin(v, username):
2022-02-07 15:07:44 +00:00
user = get_user(username)
if not user: abort(404)
user.admin_level = 1
g.db.add(user)
2022-02-04 13:11:11 +00:00
2022-02-07 15:07:44 +00:00
ma = ModAction(
kind="make_meme_admin",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2022-02-04 13:11:11 +00:00
2022-02-07 15:07:44 +00:00
g.db.commit()
2021-11-26 19:28:55 +00:00
return {"message": "User has been made meme admin!"}
2021-10-15 14:08:27 +00:00
2021-11-26 19:28:55 +00:00
@app.post("/@<username>/remove_meme_admin")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-01-31 23:10:24 +00:00
@admin_level_required(3)
2021-11-26 19:28:55 +00:00
def remove_meme_admin(v, username):
2022-02-07 15:07:44 +00:00
user = get_user(username)
if not user: abort(404)
user.admin_level = 0
g.db.add(user)
2022-02-04 13:11:11 +00:00
2022-02-07 15:07:44 +00:00
ma = ModAction(
kind="remove_meme_admin",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2022-02-04 13:11:11 +00:00
2022-02-07 15:07:44 +00:00
g.db.commit()
2021-11-26 19:28:55 +00:00
return {"message": "Meme admin removed!"}
2021-10-15 14:08:27 +00:00
@app.post("/admin/monthly")
2021-12-31 12:56:59 +00:00
@limiter.limit("1/day")
2021-12-31 12:56:47 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def monthly(v):
2022-04-02 16:54:27 +00:00
if SITE_NAME == 'rDrama' and v.id != AEVANN_ID: abort (403)
2022-01-01 22:06:53 +00:00
data = {'access_token': GUMROAD_TOKEN}
emails = [x['email'] for x in requests.get(f'https://api.gumroad.com/v2/products/{GUMROAD_ID}/subscribers', data=data, timeout=5).json()["subscribers"]]
2022-01-29 02:48:34 +00:00
for u in g.db.query(User).filter(User.patron > 0, User.patron_utc == 0).all():
2022-02-28 23:01:57 +00:00
if u.patron > 4 or u.email and u.email.lower() in emails:
2022-04-19 19:13:36 +00:00
procoins = procoins_li[u.patron]
2022-01-01 22:06:53 +00:00
u.procoins += procoins
g.db.add(u)
2022-02-22 11:43:38 +00:00
send_repeatable_notification(u.id, f"@{v.username} has given you {procoins} Marseybux for the month of {month}! You can use them to buy awards in the [shop](/shop).")
2022-01-28 20:30:07 +00:00
elif u.patron == 1 and u.admin_level > 0:
procoins = 2500
u.procoins += procoins
g.db.add(u)
2022-02-22 11:43:38 +00:00
send_repeatable_notification(u.id, f"@{v.username} has given you {procoins} Marseybux for the month of {month}! You can use them to buy awards in the [shop](/shop).")
2022-01-30 21:00:48 +00:00
else: print(u.username)
2022-01-27 20:50:34 +00:00
if request.host == 'pcmemes.net':
u = g.db.query(User).filter_by(id=KIPPY_ID).one()
u.procoins += 50000
g.db.add(u)
2022-02-28 23:01:57 +00:00
if request.host == 'rdrama.net':
u = g.db.query(User).filter_by(id=A_ID).one()
u.procoins += 25000
g.db.add(u)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="monthly",
user_id=v.id
)
g.db.add(ma)
2022-01-01 22:06:53 +00:00
g.db.commit()
2021-10-21 22:55:48 +00:00
return {"message": "Monthly coins granted"}
2021-10-15 14:08:27 +00:00
@app.get("/admin/shadowbanned")
@auth_required
def shadowbanned(v):
2021-11-15 22:13:29 +00:00
if not (v and v.admin_level > 1): abort(404)
2022-01-03 10:55:35 +00:00
users = [x for x in g.db.query(User).filter(User.shadowbanned != None).order_by(User.shadowbanned).all()]
2022-01-14 12:04:35 +00:00
return render_template("shadowbanned.html", v=v, users=users)
2021-10-15 14:08:27 +00:00
@app.get("/admin/image_posts")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def image_posts_listing(v):
try: page = int(request.values.get('page', 1))
except: page = 1
2021-11-06 15:52:48 +00:00
posts = g.db.query(Submission).order_by(Submission.id.desc())
2021-10-15 14:08:27 +00:00
firstrange = 25 * (page - 1)
secondrange = firstrange+26
posts = [x.id for x in posts if x.is_image][firstrange:secondrange]
next_exists = (len(posts) > 25)
posts = get_posts(posts[:25], v=v)
2022-01-14 12:04:35 +00:00
return render_template("admin/image_posts.html", v=v, listing=posts, next_exists=next_exists, page=page, sort="new")
2021-10-15 14:08:27 +00:00
@app.get("/admin/reported/posts")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def reported_posts(v):
page = max(1, int(request.values.get("page", 1)))
2022-01-11 22:37:37 +00:00
listing = g.db.query(Submission).filter_by(
2022-02-13 11:02:44 +00:00
is_approved=None,
2021-10-15 14:08:27 +00:00
is_banned=False
2021-12-17 17:55:11 +00:00
).join(Submission.reports).order_by(Submission.id.desc()).offset(25 * (page - 1)).limit(26)
2021-10-15 14:08:27 +00:00
2022-01-11 22:40:16 +00:00
listing = [p.id for p in listing]
2022-01-11 22:37:37 +00:00
next_exists = len(listing) > 25
2021-10-15 14:08:27 +00:00
listing = listing[:25]
listing = get_posts(listing, v=v)
2022-01-14 12:04:35 +00:00
return render_template("admin/reported_posts.html",
2021-10-15 14:08:27 +00:00
next_exists=next_exists, listing=listing, page=page, v=v)
@app.get("/admin/reported/comments")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def reported_comments(v):
page = max(1, int(request.values.get("page", 1)))
2022-01-11 22:37:37 +00:00
listing = g.db.query(Comment
2021-11-06 15:52:48 +00:00
).filter_by(
2022-02-13 11:02:44 +00:00
is_approved=None,
2021-10-15 14:08:27 +00:00
is_banned=False
2021-12-17 17:55:11 +00:00
).join(Comment.reports).order_by(Comment.id.desc()).offset(25 * (page - 1)).limit(26).all()
2021-10-15 14:08:27 +00:00
2022-01-11 22:40:16 +00:00
listing = [c.id for c in listing]
2022-01-11 22:37:37 +00:00
next_exists = len(listing) > 25
2021-10-15 14:08:27 +00:00
listing = listing[:25]
listing = get_comments(listing, v=v)
2022-01-14 12:04:35 +00:00
return render_template("admin/reported_comments.html",
2021-10-15 14:08:27 +00:00
next_exists=next_exists,
listing=listing,
page=page,
v=v,
standalone=True)
@app.get("/admin")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_home(v):
2022-03-22 15:45:52 +00:00
if CF_ZONE == 'blahblahblah': response = 'high'
2022-02-24 17:48:14 +00:00
else: response = requests.get(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value']
2022-04-12 19:05:50 +00:00
under_attack = response == 'under_attack'
2022-02-08 14:49:49 +00:00
2022-04-12 19:05:50 +00:00
return render_template("admin/admin_home.html", v=v, under_attack=under_attack, site_settings=app.config['SETTINGS'])
2022-04-12 17:29:52 +00:00
2021-10-15 14:08:27 +00:00
2022-04-12 19:05:50 +00:00
@app.post("/admin/site_settings/<setting>")
2022-04-12 17:29:52 +00:00
@admin_level_required(3)
2022-04-12 19:05:50 +00:00
def change_settings(v, setting):
site_settings = app.config['SETTINGS']
site_settings[setting] = not site_settings[setting]
with open("site_settings.json", "w") as f:
json.dump(site_settings, f)
if site_settings[setting]: word = 'enable'
else: word = 'disable'
body = f"@{v.username} has {word}d `{setting}` in the [admin dashboard](/admin)!"
2022-04-17 20:20:40 +00:00
body_html = sanitize(body)
2022-04-12 19:05:50 +00:00
new_comment = Comment(author_id=NOTIFICATIONS_ID,
parent_submission=None,
level=1,
body_html=body_html,
sentto=2,
distinguish_level=6
)
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
g.db.add(notif)
ma = ModAction(
kind=f"{word}_{setting}",
user_id=v.id,
)
g.db.add(ma)
g.db.commit()
return {'message': f"{setting} {word}d successfully!"}
2022-04-12 17:29:52 +00:00
2022-01-09 15:15:02 +00:00
2022-01-14 06:59:17 +00:00
@app.post("/admin/purge_cache")
@admin_level_required(3)
def purge_cache(v):
2022-01-24 19:06:41 +00:00
cache.clear()
2022-02-24 17:48:14 +00:00
response = str(requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, data='{"purge_everything":true}', timeout=5))
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="purge_cache",
user_id=v.id
)
g.db.add(ma)
2022-01-14 06:59:17 +00:00
if response == "<Response [200]>": return {"message": "Cache purged!"}
return {"error": "Failed to purge cache."}
2022-01-09 15:15:02 +00:00
@app.post("/admin/under_attack")
2022-01-31 23:10:24 +00:00
@admin_level_required(3)
2022-01-09 15:15:02 +00:00
def under_attack(v):
2022-02-24 17:48:14 +00:00
response = requests.get(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value']
2022-02-08 14:49:49 +00:00
if response == 'under_attack':
2022-01-28 03:22:31 +00:00
ma = ModAction(
kind="disable_under_attack",
user_id=v.id,
)
g.db.add(ma)
g.db.commit()
2022-02-24 17:48:14 +00:00
response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"medium"}', timeout=5))
2022-01-28 03:22:31 +00:00
if response == "<Response [200]>": return {"message": "Under attack mode disabled!"}
return {"error": "Failed to disable under attack mode."}
else:
ma = ModAction(
kind="enable_under_attack",
user_id=v.id,
)
g.db.add(ma)
g.db.commit()
2022-02-24 17:48:14 +00:00
response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"under_attack"}', timeout=5))
2022-01-28 03:22:31 +00:00
if response == "<Response [200]>": return {"message": "Under attack mode enabled!"}
return {"error": "Failed to enable under attack mode."}
2022-01-09 15:15:02 +00:00
2021-10-15 14:08:27 +00:00
@app.get("/admin/badge_grant")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def badge_grant_get(v):
2022-02-21 01:35:01 +00:00
badges = g.db.query(BadgeDef).order_by(BadgeDef.id).all()
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_grant.html", v=v, badge_types=badges)
2021-10-15 14:08:27 +00:00
@app.post("/admin/badge_grant")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def badge_grant_post(v):
2022-02-21 01:35:01 +00:00
badges = g.db.query(BadgeDef).order_by(BadgeDef.id).all()
2022-01-22 10:43:06 +00:00
2021-10-15 14:08:27 +00:00
user = get_user(request.values.get("username").strip(), graceful=True)
2021-12-28 14:11:50 +00:00
if not user:
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_grant.html", v=v, badge_types=badges, error="User not found.")
2021-10-15 14:08:27 +00:00
try: badge_id = int(request.values.get("badge_id"))
except: abort(400)
2022-03-05 00:47:04 +00:00
if badge_id in {16,17,94,95,96,97,98,109} and v.id != AEVANN_ID:
abort(403)
2022-02-01 04:44:05 +00:00
2021-12-28 14:11:50 +00:00
if user.has_badge(badge_id):
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_grant.html", v=v, badge_types=badges, error="User already has that badge.")
2021-10-15 14:08:27 +00:00
2021-10-23 19:15:50 +00:00
new_badge = Badge(badge_id=badge_id, user_id=user.id)
2021-10-15 14:08:27 +00:00
desc = request.values.get("description")
if desc: new_badge.description = desc
url = request.values.get("url")
if url: new_badge.url = url
g.db.add(new_badge)
2022-02-13 11:02:44 +00:00
g.db.flush()
2022-01-03 10:32:31 +00:00
if v.id != user.id:
text = f"@{v.username} has given you the following profile badge:\n\n![]({new_badge.path})\n\n{new_badge.name}"
send_notification(user.id, text)
2021-10-15 14:08:27 +00:00
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="badge_grant",
user_id=v.id,
target_user_id=user.id,
_note=new_badge.name
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_grant.html", v=v, badge_types=badges, msg="Badge granted!")
2021-10-15 14:08:27 +00:00
2022-01-11 03:28:35 +00:00
@app.get("/admin/badge_remove")
@admin_level_required(2)
def badge_remove_get(v):
2022-02-21 01:35:01 +00:00
badges = g.db.query(BadgeDef).order_by(BadgeDef.id).all()
2022-01-22 10:43:06 +00:00
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_remove.html", v=v, badge_types=badges)
2022-01-11 03:28:35 +00:00
@app.post("/admin/badge_remove")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-01-11 03:28:35 +00:00
@admin_level_required(2)
def badge_remove_post(v):
2022-02-21 01:35:01 +00:00
badges = g.db.query(BadgeDef).order_by(BadgeDef.id).all()
2022-01-22 10:43:06 +00:00
2022-01-11 03:28:35 +00:00
user = get_user(request.values.get("username").strip(), graceful=True)
if not user:
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_remove.html", v=v, badge_types=badges, error="User not found.")
2022-01-11 03:28:35 +00:00
try: badge_id = int(request.values.get("badge_id"))
except: abort(400)
badge = user.has_badge(badge_id)
2022-02-28 19:54:33 +00:00
if not badge:
return render_template("admin/badge_remove.html", v=v, badge_types=badges, error="User doesn't have that badge.")
ma = ModAction(
kind="badge_remove",
user_id=v.id,
target_user_id=user.id,
_note=badge.name
)
g.db.add(ma)
2022-02-04 13:11:11 +00:00
2022-02-28 19:54:33 +00:00
g.db.delete(badge)
g.db.commit()
2022-02-13 11:02:44 +00:00
2022-01-23 19:51:56 +00:00
return render_template("admin/badge_remove.html", v=v, badge_types=badges, msg="Badge removed!")
2022-01-11 03:28:35 +00:00
2021-10-15 14:08:27 +00:00
@app.get("/admin/users")
@admin_level_required(2)
def users_list(v):
2022-04-17 09:23:42 +00:00
try: page = int(request.values.get("page", 1))
except: page = 1
2021-10-15 14:08:27 +00:00
2022-05-03 04:28:42 +00:00
users = g.db.query(User).order_by(User.id.desc()).offset(25 * (page - 1)).limit(26).all()
next_exists = (len(users) > 25)
users = users[:25]
return render_template("admin/new_users.html",
v=v,
users=users,
next_exists=next_exists,
page=page,
)
2021-10-15 14:08:27 +00:00
2022-05-03 04:28:42 +00:00
@app.get("/badge_owners/<bid>")
@auth_required
def bid_list(v, bid):
try: bid = int(bid)
except: abort(400)
try: page = int(request.values.get("page", 1))
except: page = 1
users = g.db.query(User).join(Badge, Badge.user_id == User.id).filter(Badge.badge_id==bid).offset(25 * (page - 1)).limit(26).all()
2021-10-15 14:08:27 +00:00
next_exists = (len(users) > 25)
users = users[:25]
2022-01-14 12:04:35 +00:00
return render_template("admin/new_users.html",
2021-10-15 14:08:27 +00:00
v=v,
users=users,
next_exists=next_exists,
page=page,
)
2022-05-03 04:28:42 +00:00
2021-10-15 14:08:27 +00:00
@app.get("/admin/alt_votes")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def alt_votes_get(v):
u1 = request.values.get("u1")
u2 = request.values.get("u2")
if not u1 or not u2:
2022-01-17 11:06:12 +00:00
return render_template("admin/alt_votes.html", v=v)
2021-10-15 14:08:27 +00:00
u1 = get_user(u1)
u2 = get_user(u2)
u1_post_ups = g.db.query(
2021-11-06 15:52:48 +00:00
Vote.submission_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u1.id,
vote_type=1).all()
u1_post_downs = g.db.query(
2021-11-06 15:52:48 +00:00
Vote.submission_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u1.id,
vote_type=-1).all()
u1_comment_ups = g.db.query(
2021-11-06 15:52:48 +00:00
CommentVote.comment_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u1.id,
vote_type=1).all()
u1_comment_downs = g.db.query(
2021-11-06 15:52:48 +00:00
CommentVote.comment_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u1.id,
vote_type=-1).all()
u2_post_ups = g.db.query(
2021-11-06 15:52:48 +00:00
Vote.submission_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u2.id,
vote_type=1).all()
u2_post_downs = g.db.query(
2021-11-06 15:52:48 +00:00
Vote.submission_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u2.id,
vote_type=-1).all()
u2_comment_ups = g.db.query(
2021-11-06 15:52:48 +00:00
CommentVote.comment_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u2.id,
vote_type=1).all()
u2_comment_downs = g.db.query(
2021-11-06 15:52:48 +00:00
CommentVote.comment_id).filter_by(
2021-10-15 14:08:27 +00:00
user_id=u2.id,
vote_type=-1).all()
data = {}
data['u1_only_post_ups'] = len(
[x for x in u1_post_ups if x not in u2_post_ups])
data['u2_only_post_ups'] = len(
[x for x in u2_post_ups if x not in u1_post_ups])
data['both_post_ups'] = len(list(set(u1_post_ups) & set(u2_post_ups)))
data['u1_only_post_downs'] = len(
[x for x in u1_post_downs if x not in u2_post_downs])
data['u2_only_post_downs'] = len(
[x for x in u2_post_downs if x not in u1_post_downs])
data['both_post_downs'] = len(
list(set(u1_post_downs) & set(u2_post_downs)))
data['u1_only_comment_ups'] = len(
[x for x in u1_comment_ups if x not in u2_comment_ups])
data['u2_only_comment_ups'] = len(
[x for x in u2_comment_ups if x not in u1_comment_ups])
data['both_comment_ups'] = len(
list(set(u1_comment_ups) & set(u2_comment_ups)))
data['u1_only_comment_downs'] = len(
[x for x in u1_comment_downs if x not in u2_comment_downs])
data['u2_only_comment_downs'] = len(
[x for x in u2_comment_downs if x not in u1_comment_downs])
data['both_comment_downs'] = len(
list(set(u1_comment_downs) & set(u2_comment_downs)))
data['u1_post_ups_unique'] = 100 * \
data['u1_only_post_ups'] // len(u1_post_ups) if u1_post_ups else 0
data['u2_post_ups_unique'] = 100 * \
data['u2_only_post_ups'] // len(u2_post_ups) if u2_post_ups else 0
data['u1_post_downs_unique'] = 100 * \
data['u1_only_post_downs'] // len(
u1_post_downs) if u1_post_downs else 0
data['u2_post_downs_unique'] = 100 * \
data['u2_only_post_downs'] // len(
u2_post_downs) if u2_post_downs else 0
data['u1_comment_ups_unique'] = 100 * \
data['u1_only_comment_ups'] // len(
u1_comment_ups) if u1_comment_ups else 0
data['u2_comment_ups_unique'] = 100 * \
data['u2_only_comment_ups'] // len(
u2_comment_ups) if u2_comment_ups else 0
data['u1_comment_downs_unique'] = 100 * \
data['u1_only_comment_downs'] // len(
u1_comment_downs) if u1_comment_downs else 0
data['u2_comment_downs_unique'] = 100 * \
data['u2_only_comment_downs'] // len(
u2_comment_downs) if u2_comment_downs else 0
2022-01-14 12:04:35 +00:00
return render_template("admin/alt_votes.html",
2021-10-15 14:08:27 +00:00
u1=u1,
u2=u2,
v=v,
data=data
)
@app.post("/admin/link_accounts")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_link_accounts(v):
u1 = int(request.values.get("u1"))
u2 = int(request.values.get("u2"))
new_alt = Alt(
user1=u1,
user2=u2,
is_manual=True
)
g.db.add(new_alt)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="link_accounts",
user_id=v.id,
target_user_id=u1,
_note=f'with {u2}'
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-04-02 17:11:35 +00:00
return redirect(f"/admin/alt_votes?u1={g.db.query(User).get(u1).username}&u2={g.db.query(User).get(u2).username}")
2021-10-15 14:08:27 +00:00
2021-12-17 17:55:11 +00:00
@app.get("/admin/removed/posts")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_removed(v):
2022-04-17 09:23:42 +00:00
try: page = int(request.values.get("page", 1))
except: page = 1
2022-01-16 06:20:11 +00:00
if page < 1: abort(400)
2021-10-15 14:08:27 +00:00
2021-11-06 15:52:48 +00:00
ids = g.db.query(Submission.id).join(User, User.id == Submission.author_id).filter(or_(Submission.is_banned==True, User.shadowbanned != None)).order_by(Submission.id.desc()).offset(25 * (page - 1)).limit(26).all()
2021-10-15 14:08:27 +00:00
ids=[x[0] for x in ids]
next_exists = len(ids) > 25
ids = ids[:25]
posts = get_posts(ids, v=v)
2022-01-14 12:04:35 +00:00
return render_template("admin/removed_posts.html",
2021-10-15 14:08:27 +00:00
v=v,
listing=posts,
page=page,
next_exists=next_exists
)
2021-12-17 17:55:11 +00:00
@app.get("/admin/removed/comments")
@admin_level_required(2)
def admin_removed_comments(v):
2022-04-17 09:23:42 +00:00
try: page = int(request.values.get("page", 1))
except: page = 1
2021-12-17 17:55:11 +00:00
ids = g.db.query(Comment.id).join(User, User.id == Comment.author_id).filter(or_(Comment.is_banned==True, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(25 * (page - 1)).limit(26).all()
ids=[x[0] for x in ids]
next_exists = len(ids) > 25
ids = ids[:25]
comments = get_comments(ids, v=v)
2022-01-14 12:04:35 +00:00
return render_template("admin/removed_comments.html",
2021-12-17 17:55:11 +00:00
v=v,
listing=comments,
page=page,
next_exists=next_exists
)
2021-10-15 14:08:27 +00:00
@app.post("/agendaposter/<user_id>")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def agendaposter(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
2022-03-13 22:58:07 +00:00
days = request.values.get("days") or 30
2022-02-19 21:42:55 +00:00
expiry = float(days)
expiry = int(time.time() + expiry*60*60*24)
2021-10-15 14:08:27 +00:00
2022-02-12 23:10:29 +00:00
user.agendaposter = expiry
2021-10-15 14:08:27 +00:00
g.db.add(user)
2022-02-12 23:10:29 +00:00
2021-10-15 14:08:27 +00:00
for alt in user.alts:
2022-02-12 23:10:29 +00:00
if alt.admin_level: return {"error": "User is an admin!"}
alt.agendaposter = expiry
2021-10-15 14:08:27 +00:00
g.db.add(alt)
2022-02-19 21:42:55 +00:00
note = f"for {days} days"
2021-10-15 14:08:27 +00:00
ma = ModAction(
2022-02-12 23:10:29 +00:00
kind="agendaposter",
2021-10-15 14:08:27 +00:00
user_id=v.id,
target_user_id=user.id,
note = note
)
g.db.add(ma)
2022-02-19 21:42:55 +00:00
if not user.has_badge(28):
badge = Badge(user_id=user.id, badge_id=28)
2022-02-12 23:10:29 +00:00
g.db.add(badge)
g.db.flush()
send_notification(user.id, f"@AutoJanny has given you the following profile badge:\n\n![]({badge.path})\n\n{badge.name}")
2021-12-28 13:51:26 +00:00
2022-04-12 16:52:18 +00:00
send_repeatable_notification(user.id, f"@{v.username} has marked you as a chud ({note}).")
2022-02-12 23:10:29 +00:00
g.db.commit()
return redirect(user.url)
@app.post("/unagendaposter/<user_id>")
@admin_level_required(2)
def unagendaposter(user_id, v):
user = g.db.query(User).filter_by(id=user_id).one_or_none()
user.agendaposter = 0
g.db.add(user)
for alt in user.alts:
alt.agendaposter = 0
g.db.add(alt)
ma = ModAction(
kind="unagendaposter",
user_id=v.id,
target_user_id=user.id
)
g.db.add(ma)
2022-02-19 21:42:55 +00:00
badge = user.has_badge(28)
2022-02-12 23:10:29 +00:00
if badge: g.db.delete(badge)
2021-10-15 14:08:27 +00:00
2022-04-12 16:52:18 +00:00
send_repeatable_notification(user.id, f"@{v.username} has unmarked you as a chud.")
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-01-28 04:37:40 +00:00
return {"message": "Chud theme disabled!"}
2021-10-15 14:08:27 +00:00
@app.post("/shadowban/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def shadowban(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
if user.admin_level != 0: abort(403)
user.shadowbanned = v.username
g.db.add(user)
2022-04-22 15:08:42 +00:00
2021-10-15 14:08:27 +00:00
for alt in user.alts:
2022-01-12 01:19:13 +00:00
if alt.admin_level: break
2021-10-15 14:08:27 +00:00
alt.shadowbanned = v.username
g.db.add(alt)
2022-04-22 15:08:42 +00:00
2021-10-15 14:08:27 +00:00
ma = ModAction(
kind="shadowban",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
cache.delete_memoized(frontlist)
2022-01-31 23:55:11 +00:00
body = f"@{v.username} has shadowbanned @{user.username}"
body_html = sanitize(body)
2022-02-21 01:58:12 +00:00
new_comment = Comment(author_id=NOTIFICATIONS_ID,
parent_submission=None,
level=1,
body_html=body_html,
2022-03-31 15:00:57 +00:00
distinguish_level=6
2022-02-21 01:58:12 +00:00
)
g.db.add(new_comment)
g.db.flush()
2022-04-04 01:41:20 +00:00
new_comment.top_comment_id = new_comment.id
2022-02-21 01:58:12 +00:00
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
g.db.add(notif)
2022-01-31 23:55:11 +00:00
2021-10-15 14:08:27 +00:00
g.db.commit()
return {"message": "User shadowbanned!"}
@app.post("/unshadowban/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def unshadowban(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
user.shadowbanned = None
2022-01-01 22:51:39 +00:00
user.ban_evade = 0
2021-10-15 14:08:27 +00:00
g.db.add(user)
for alt in user.alts:
alt.shadowbanned = None
2022-01-01 22:51:39 +00:00
alt.ban_evade = 0
2021-10-15 14:08:27 +00:00
g.db.add(alt)
ma = ModAction(
kind="unshadowban",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
cache.delete_memoized(frontlist)
g.db.commit()
return {"message": "User unshadowbanned!"}
@app.post("/admin/verify/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-02-09 21:19:02 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def verify(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
user.verified = "Verified"
g.db.add(user)
2021-10-25 18:08:03 +00:00
ma = ModAction(
kind="check",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
return {"message": "User verfied!"}
@app.post("/admin/unverify/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-02-09 21:19:02 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def unverify(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
user.verified = None
g.db.add(user)
2021-10-25 18:08:03 +00:00
ma = ModAction(
kind="uncheck",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
return {"message": "User unverified!"}
@app.post("/admin/title_change/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_title_change(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
new_name=request.values.get("title").strip()[:256]
user.customtitleplain=new_name
2022-01-14 06:59:17 +00:00
new_name = filter_emojis_only(new_name)
2021-10-15 14:08:27 +00:00
2022-01-14 06:59:17 +00:00
user=g.db.query(User).filter_by(id=user.id).one_or_none()
2021-10-15 14:08:27 +00:00
user.customtitle=new_name
2021-12-31 23:45:27 +00:00
if request.values.get("locked"): user.flairchanged = int(time.time()) + 2629746
2022-02-09 23:08:55 +00:00
else:
user.flairchanged = None
badge = user.has_badge(96)
if badge: g.db.delete(badge)
2021-10-15 14:08:27 +00:00
g.db.add(user)
if user.flairchanged: kind = "set_flair_locked"
else: kind = "set_flair_notlocked"
ma=ModAction(
kind=kind,
user_id=v.id,
target_user_id=user.id,
2021-12-10 16:31:38 +00:00
_note=f'"{user.customtitleplain}"'
2021-10-15 14:08:27 +00:00
)
g.db.add(ma)
g.db.commit()
return redirect(user.url)
@app.post("/ban_user/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def ban_user(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
2022-01-14 06:59:17 +00:00
if not user: abort(404)
2021-10-15 14:08:27 +00:00
if user.admin_level >= v.admin_level: abort(403)
2021-12-03 19:20:52 +00:00
days = float(request.values.get("days")) if request.values.get('days') else 0
2021-10-15 14:08:27 +00:00
2022-01-14 06:59:17 +00:00
reason = request.values.get("reason", "").strip()[:256]
passed_reason = filter_emojis_only(reason)
if len(passed_reason) > 256: passed_reason = reason
2021-10-15 14:08:27 +00:00
2022-01-14 06:59:17 +00:00
user.ban(admin=v, reason=passed_reason, days=days)
2021-10-15 14:08:27 +00:00
2021-12-26 12:53:51 +00:00
if request.values.get("alts"):
2021-10-15 14:08:27 +00:00
for x in user.alts:
2022-01-12 01:19:13 +00:00
if x.admin_level: break
2022-02-26 18:23:04 +00:00
x.ban(admin=v, reason=passed_reason, days=days)
2021-10-15 14:08:27 +00:00
2022-01-12 01:19:13 +00:00
if days:
2022-04-15 15:35:11 +00:00
if reason: text = f"@{v.username} has banned you for **{days}** days for the following reason:\n\n> {reason}"
else: text = f"@{v.username} has banned you for **{days}** days."
2021-12-19 23:31:47 +00:00
else:
2022-04-15 15:35:11 +00:00
if reason: text = f"@{v.username} has banned you permanently for the following reason:\n\n> {reason}"
else: text = f"@{v.username} has banned you permanently."
2021-12-19 23:31:47 +00:00
2021-12-20 20:03:59 +00:00
send_repeatable_notification(user.id, text)
2021-10-15 14:08:27 +00:00
if days == 0: duration = "permanent"
elif days == 1: duration = "1 day"
else: duration = f"{days} days"
2022-01-31 23:55:11 +00:00
note = f'reason: "{reason}", duration: {duration}'
2021-10-15 14:08:27 +00:00
ma=ModAction(
kind="ban_user",
user_id=v.id,
target_user_id=user.id,
2022-01-31 23:55:11 +00:00
_note=note
2021-10-15 14:08:27 +00:00
)
g.db.add(ma)
if 'reason' in request.values:
if reason.startswith("/post/"):
2022-04-20 17:34:27 +00:00
try:
post = int(reason.split("/post/")[1].split(None, 1)[0])
post = get_post(post)
post.bannedfor = True
g.db.add(post)
except: pass
2021-11-25 21:33:00 +00:00
elif reason.startswith("/comment/"):
2022-04-20 17:34:27 +00:00
try:
comment = int(reason.split("/comment/")[1].split(None, 1)[0])
comment = get_comment(comment)
comment.bannedfor = True
g.db.add(comment)
except: pass
2022-01-31 23:55:11 +00:00
body = f"@{v.username} has banned @{user.username} ({note})"
body_html = sanitize(body)
2022-02-21 01:58:12 +00:00
new_comment = Comment(author_id=NOTIFICATIONS_ID,
parent_submission=None,
level=1,
body_html=body_html,
2022-03-31 15:00:57 +00:00
distinguish_level=6
2022-02-21 01:58:12 +00:00
)
g.db.add(new_comment)
g.db.flush()
2022-04-04 01:41:20 +00:00
new_comment.top_comment_id = new_comment.id
2022-02-21 01:58:12 +00:00
for admin in g.db.query(User).filter(User.admin_level > 2, User.id != v.id).all():
notif = Notification(comment_id=new_comment.id, user_id=admin.id)
g.db.add(notif)
2022-01-31 23:55:11 +00:00
2021-10-15 14:08:27 +00:00
g.db.commit()
if 'redir' in request.values: return redirect(user.url)
else: return {"message": f"@{user.username} was banned!"}
@app.post("/unban_user/<user_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def unban_user(user_id, v):
2022-01-02 00:06:46 +00:00
user = g.db.query(User).filter_by(id=user_id).one_or_none()
2021-10-15 14:08:27 +00:00
2022-05-01 21:44:38 +00:00
if not user or not user.is_banned: abort(400)
2021-10-15 14:08:27 +00:00
user.is_banned = 0
user.unban_utc = 0
2021-10-21 18:06:57 +00:00
user.ban_evade = 0
2021-12-20 21:04:15 +00:00
user.ban_reason = None
2022-02-22 11:43:38 +00:00
send_repeatable_notification(user.id, f"@{v.username} has unbanned you!")
2021-10-15 14:08:27 +00:00
g.db.add(user)
2021-12-29 13:07:51 +00:00
for x in user.alts:
2022-05-01 21:44:38 +00:00
if x.is_banned: send_repeatable_notification(x.id, f"@{v.username} has unbanned you!")
2021-12-29 13:07:51 +00:00
x.is_banned = 0
x.unban_utc = 0
x.ban_evade = 0
2021-12-29 13:23:21 +00:00
x.ban_reason = None
2021-12-29 13:07:51 +00:00
g.db.add(x)
2021-10-15 14:08:27 +00:00
ma=ModAction(
kind="unban_user",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
g.db.commit()
if "@" in request.referrer: return redirect(user.url)
else: return {"message": f"@{user.username} was unbanned!"}
@app.post("/ban_post/<post_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def ban_post(post_id, v):
2022-01-02 00:06:46 +00:00
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
2021-10-15 14:08:27 +00:00
if not post:
abort(400)
post.is_banned = True
2022-02-13 11:02:44 +00:00
post.is_approved = None
2021-10-15 14:08:27 +00:00
post.stickied = None
post.is_pinned = False
2021-10-29 02:32:23 +00:00
post.ban_reason = v.username
2021-10-15 14:08:27 +00:00
g.db.add(post)
ma=ModAction(
kind="ban_post",
user_id=v.id,
target_submission_id=post.id,
)
g.db.add(ma)
cache.delete_memoized(frontlist)
2021-12-27 01:08:06 +00:00
v.coins += 1
2021-10-15 14:08:27 +00:00
g.db.add(v)
2022-02-24 17:48:14 +00:00
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, json={'files': [f"{SITE_FULL}/logged_out/"]}, timeout=5)
2022-02-15 23:38:33 +00:00
2021-10-15 14:08:27 +00:00
g.db.commit()
return {"message": "Post removed!"}
@app.post("/unban_post/<post_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def unban_post(post_id, v):
2022-01-02 00:06:46 +00:00
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
2021-10-15 14:08:27 +00:00
if not post:
abort(400)
if post.is_banned:
ma=ModAction(
kind="unban_post",
user_id=v.id,
target_submission_id=post.id,
)
g.db.add(ma)
post.is_banned = False
2022-04-22 14:51:40 +00:00
post.ban_reason = None
2021-10-15 14:08:27 +00:00
post.is_approved = v.id
g.db.add(post)
cache.delete_memoized(frontlist)
2021-12-27 01:08:06 +00:00
v.coins -= 1
2021-10-15 14:08:27 +00:00
g.db.add(v)
g.db.commit()
return {"message": "Post approved!"}
@app.post("/distinguish/<post_id>")
@admin_level_required(1)
def api_distinguish_post(post_id, v):
2022-01-02 00:06:46 +00:00
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
2021-10-15 14:08:27 +00:00
2022-01-17 22:24:04 +00:00
if not post: abort(404)
2021-10-15 14:08:27 +00:00
2022-01-17 22:24:04 +00:00
if post.author_id != v.id and v.admin_level < 2 : abort(403)
2021-10-15 14:08:27 +00:00
2022-02-04 13:11:11 +00:00
if post.distinguish_level:
post.distinguish_level = 0
kind = 'undistinguish_post'
else:
post.distinguish_level = v.admin_level
kind = 'distinguish_post'
2021-10-15 14:08:27 +00:00
g.db.add(post)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind=kind,
user_id=v.id,
target_submission_id=post.id
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2021-12-31 16:26:27 +00:00
if post.distinguish_level: return {"message": "Post distinguished!"}
else: return {"message": "Post undistinguished!"}
2021-10-15 14:08:27 +00:00
@app.post("/sticky/<post_id>")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-12-26 01:03:21 +00:00
def sticky_post(post_id, v):
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
if post and not post.stickied:
pins = g.db.query(Submission.id).filter(Submission.stickied != None, Submission.is_banned == False).count()
if pins > 2:
if v.admin_level > 2:
post.stickied = v.username
post.stickied_utc = int(time.time()) + 3600
else: return {"error": "Can't exceed 3 pinned posts limit!"}, 403
else: post.stickied = v.username
g.db.add(post)
2021-10-15 14:08:27 +00:00
2022-02-04 13:11:11 +00:00
ma=ModAction(
kind="pin_post",
user_id=v.id,
target_submission_id=post.id
)
g.db.add(ma)
2021-12-26 01:03:21 +00:00
if v.id != post.author_id:
send_repeatable_notification(post.author_id, f"@{v.username} has pinned your [post](/post/{post_id})!")
cache.delete_memoized(frontlist)
g.db.commit()
return {"message": "Post pinned!"}
@app.post("/unsticky/<post_id>")
@admin_level_required(2)
def unsticky_post(post_id, v):
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
if post and post.stickied:
if post.stickied.endswith('(pin award)'): return {"error": "Can't unpin award pins!"}, 403
post.stickied = None
post.stickied_utc = None
2021-10-15 14:08:27 +00:00
g.db.add(post)
ma=ModAction(
2021-12-26 01:03:21 +00:00
kind="unpin_post",
2021-10-15 14:08:27 +00:00
user_id=v.id,
target_submission_id=post.id
)
g.db.add(ma)
2021-12-26 01:03:21 +00:00
if v.id != post.author_id:
send_repeatable_notification(post.author_id, f"@{v.username} has unpinned your [post](/post/{post_id})!")
2021-10-15 14:08:27 +00:00
cache.delete_memoized(frontlist)
2021-12-26 01:03:21 +00:00
g.db.commit()
return {"message": "Post unpinned!"}
@app.post("/sticky_comment/<cid>")
@admin_level_required(2)
def sticky_comment(cid, v):
comment = get_comment(cid, v=v)
if not comment.is_pinned:
comment.is_pinned = v.username
g.db.add(comment)
2022-02-04 13:11:11 +00:00
ma=ModAction(
kind="pin_comment",
user_id=v.id,
target_comment_id=comment.id
)
g.db.add(ma)
2021-12-26 01:03:21 +00:00
if v.id != comment.author_id:
2022-02-24 13:20:48 +00:00
message = f"@{v.username} has pinned your [comment]({comment.shortlink})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
2021-12-26 01:03:21 +00:00
return {"message": "Comment pinned!"}
@app.post("/unsticky_comment/<cid>")
@admin_level_required(2)
def unsticky_comment(cid, v):
comment = get_comment(cid, v=v)
if comment.is_pinned:
if comment.is_pinned.endswith("(pin award)"): return {"error": "Can't unpin award pins!"}, 403
2021-12-26 01:03:21 +00:00
comment.is_pinned = None
g.db.add(comment)
2021-12-26 01:03:21 +00:00
ma=ModAction(
kind="unpin_comment",
user_id=v.id,
target_comment_id=comment.id
)
g.db.add(ma)
2021-12-26 01:03:21 +00:00
if v.id != comment.author_id:
2022-02-24 13:20:48 +00:00
message = f"@{v.username} has unpinned your [comment]({comment.shortlink})!"
send_repeatable_notification(comment.author_id, message)
2021-12-26 01:03:21 +00:00
g.db.commit()
2021-12-26 01:03:21 +00:00
return {"message": "Comment unpinned!"}
2021-10-15 14:08:27 +00:00
@app.post("/ban_comment/<c_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-12-13 01:23:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def api_ban_comment(c_id, v):
2022-01-02 00:06:46 +00:00
comment = g.db.query(Comment).filter_by(id=c_id).one_or_none()
2021-10-15 14:08:27 +00:00
if not comment:
abort(404)
comment.is_banned = True
2022-02-13 11:02:44 +00:00
comment.is_approved = None
2021-10-29 02:32:23 +00:00
comment.ban_reason = v.username
2021-10-15 14:08:27 +00:00
g.db.add(comment)
ma=ModAction(
kind="ban_comment",
user_id=v.id,
target_comment_id=comment.id,
)
g.db.add(ma)
g.db.commit()
return {"message": "Comment removed!"}
@app.post("/unban_comment/<c_id>")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-12-13 01:23:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def api_unban_comment(c_id, v):
2022-01-02 00:06:46 +00:00
comment = g.db.query(Comment).filter_by(id=c_id).one_or_none()
2021-12-01 15:37:36 +00:00
if not comment: abort(404)
2022-01-02 00:05:22 +00:00
2022-01-21 08:44:19 +00:00
if comment.author.agendaposter and AGENDAPOSTER_PHRASE not in comment.body.lower():
2022-04-12 16:52:18 +00:00
return {"error": "You can't bypass the chud award!"}
2021-10-15 14:08:27 +00:00
if comment.is_banned:
ma=ModAction(
kind="unban_comment",
user_id=v.id,
target_comment_id=comment.id,
)
g.db.add(ma)
comment.is_banned = False
2022-04-22 14:51:40 +00:00
comment.ban_reason = None
2021-10-15 14:08:27 +00:00
comment.is_approved = v.id
2022-01-02 00:05:22 +00:00
g.db.add(comment)
2021-10-15 14:08:27 +00:00
g.db.commit()
return {"message": "Comment approved!"}
@app.post("/distinguish_comment/<c_id>")
2021-12-01 15:37:36 +00:00
@admin_level_required(1)
2021-10-15 14:08:27 +00:00
def admin_distinguish_comment(c_id, v):
2022-01-21 14:22:44 +00:00
2021-10-15 14:08:27 +00:00
comment = get_comment(c_id, v=v)
2021-12-01 15:37:36 +00:00
if comment.author_id != v.id: abort(403)
2021-10-15 14:08:27 +00:00
2022-02-04 13:11:11 +00:00
if comment.distinguish_level:
comment.distinguish_level = 0
2022-04-19 17:50:13 +00:00
kind = 'undistinguish_comment'
2022-02-04 13:11:11 +00:00
else:
comment.distinguish_level = v.admin_level
2022-04-19 17:50:13 +00:00
kind = 'distinguish_comment'
2021-10-15 14:08:27 +00:00
g.db.add(comment)
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind=kind,
user_id=v.id,
target_comment_id=comment.id
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2021-12-31 16:26:27 +00:00
if comment.distinguish_level: return {"message": "Comment distinguished!"}
else: return {"message": "Comment undistinguished!"}
2021-10-15 14:08:27 +00:00
@app.get("/admin/dump_cache")
2021-11-15 22:13:29 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_dump_cache(v):
2022-01-23 23:06:34 +00:00
cache.clear()
2022-02-04 13:11:11 +00:00
ma = ModAction(
kind="dump_cache",
user_id=v.id
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
return {"message": "Internal cache cleared."}
@app.get("/admin/banned_domains/")
2022-01-31 23:10:24 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def admin_banned_domains(v):
2021-11-06 15:52:48 +00:00
banned_domains = g.db.query(BannedDomain).all()
2022-01-14 12:04:35 +00:00
return render_template("admin/banned_domains.html", v=v, banned_domains=banned_domains)
2021-10-15 14:08:27 +00:00
@app.post("/admin/banned_domains")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2022-01-31 23:10:24 +00:00
@admin_level_required(3)
2021-10-15 14:08:27 +00:00
def admin_toggle_ban_domain(v):
domain=request.values.get("domain", "").strip()
if not domain: abort(400)
reason=request.values.get("reason", "").strip()
2022-01-02 00:06:46 +00:00
d = g.db.query(BannedDomain).filter_by(domain=domain).one_or_none()
2021-10-25 18:08:03 +00:00
if d:
g.db.delete(d)
ma = ModAction(
kind="unban_domain",
user_id=v.id,
_note=domain
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
else:
d = BannedDomain(domain=domain, reason=reason)
g.db.add(d)
2021-10-25 18:08:03 +00:00
ma = ModAction(
kind="ban_domain",
user_id=v.id,
_note=f'{domain}, reason: {reason}'
)
g.db.add(ma)
2021-10-15 14:08:27 +00:00
g.db.commit()
2022-04-02 17:11:35 +00:00
return redirect("/admin/banned_domains/")
2021-10-15 14:08:27 +00:00
@app.post("/admin/nuke_user")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_nuke_user(v):
user=get_user(request.values.get("user"))
2021-11-06 15:52:48 +00:00
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
2021-10-15 14:08:27 +00:00
if post.is_banned:
continue
2022-04-22 14:51:40 +00:00
post.is_banned = True
post.ban_reason = v.username
2021-10-15 14:08:27 +00:00
g.db.add(post)
2021-11-06 15:52:48 +00:00
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
2021-10-15 14:08:27 +00:00
if comment.is_banned:
continue
2022-04-22 14:51:40 +00:00
comment.is_banned = True
comment.ban_reason = v.username
2021-10-15 14:08:27 +00:00
g.db.add(comment)
ma=ModAction(
kind="nuke_user",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
g.db.commit()
return redirect(user.url)
@app.post("/admin/unnuke_user")
2022-01-15 06:31:17 +00:00
@limiter.limit("1/second;30/minute;200/hour;1000/day")
2021-11-16 04:18:36 +00:00
@admin_level_required(2)
2021-10-15 14:08:27 +00:00
def admin_nunuke_user(v):
user=get_user(request.values.get("user"))
2021-11-06 15:52:48 +00:00
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
2021-10-15 14:08:27 +00:00
if not post.is_banned:
continue
2022-04-22 14:51:40 +00:00
post.is_banned = False
post.ban_reason = None
2021-10-15 14:08:27 +00:00
g.db.add(post)
2021-11-06 15:52:48 +00:00
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
2021-10-15 14:08:27 +00:00
if not comment.is_banned:
continue
2022-04-22 14:51:40 +00:00
comment.is_banned = False
comment.ban_reason = None
2021-10-15 14:08:27 +00:00
g.db.add(comment)
ma=ModAction(
kind="unnuke_user",
user_id=v.id,
target_user_id=user.id,
)
g.db.add(ma)
g.db.commit()
2021-09-24 18:37:44 +00:00
return redirect(user.url)