2021-07-21 01:12:26 +00:00
|
|
|
import time
|
|
|
|
import calendar
|
|
|
|
from sqlalchemy.orm import lazyload
|
|
|
|
import imagehash
|
2021-07-26 18:57:00 +00:00
|
|
|
from os import remove
|
2021-09-10 03:25:42 +00:00
|
|
|
from os.path import exists
|
2021-07-21 01:12:26 +00:00
|
|
|
from PIL import Image as IMAGE
|
|
|
|
|
2021-08-04 15:35:10 +00:00
|
|
|
from files.helpers.wrappers import *
|
|
|
|
from files.helpers.alerts import *
|
|
|
|
from files.helpers.sanitize import *
|
|
|
|
from files.helpers.markdown import *
|
|
|
|
from files.helpers.security import *
|
|
|
|
from files.helpers.get import *
|
|
|
|
from files.helpers.images import *
|
2021-08-21 11:06:28 +00:00
|
|
|
from files.helpers.const import *
|
2021-08-04 15:35:10 +00:00
|
|
|
from files.classes import *
|
2021-07-21 01:12:26 +00:00
|
|
|
from flask import *
|
|
|
|
import matplotlib.pyplot as plt
|
2021-08-22 16:55:55 +00:00
|
|
|
from files.__main__ import app, cache, limiter
|
2021-07-30 09:42:17 +00:00
|
|
|
from .front import frontlist
|
2021-08-13 02:43:38 +00:00
|
|
|
from files.helpers.discord import add_role
|
2021-07-28 04:00:26 +00:00
|
|
|
|
2021-09-02 13:29:36 +00:00
|
|
|
IMGUR_KEY = environ.get("IMGUR_KEY", "").strip()
|
|
|
|
|
2021-08-31 20:05:06 +00:00
|
|
|
@app.post("/@<username>/make_admin")
|
|
|
|
@admin_level_required(6)
|
|
|
|
def make_admin(v, username):
|
|
|
|
user = get_user(username)
|
|
|
|
if not user: abort(404)
|
|
|
|
user.admin_level = 6
|
|
|
|
g.db.add(user)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User has been made admin!"}
|
2021-08-31 20:05:06 +00:00
|
|
|
|
2021-08-31 20:08:43 +00:00
|
|
|
|
2021-09-06 00:51:27 +00:00
|
|
|
@app.post("/@<username>/make_fake_admin")
|
|
|
|
@admin_level_required(6)
|
|
|
|
def make_fake_admin(v, username):
|
|
|
|
user = get_user(username)
|
|
|
|
if not user: abort(404)
|
|
|
|
user.admin_level = 1
|
|
|
|
g.db.add(user)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User has been made fake admin!"}
|
2021-09-06 00:51:27 +00:00
|
|
|
|
|
|
|
|
2021-08-31 20:08:43 +00:00
|
|
|
@app.post("/@<username>/remove_admin")
|
|
|
|
@admin_level_required(6)
|
|
|
|
def remove_admin(v, username):
|
|
|
|
user = get_user(username)
|
|
|
|
if not user: abort(404)
|
|
|
|
user.admin_level = 0
|
|
|
|
g.db.add(user)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Admin removed!"}
|
2021-08-31 20:08:43 +00:00
|
|
|
|
|
|
|
|
2021-09-09 11:02:06 +00:00
|
|
|
@app.get('/admin/rules')
|
|
|
|
@admin_level_required(6)
|
|
|
|
def get_rules(v):
|
|
|
|
|
|
|
|
try:
|
|
|
|
with open('./rules.md', 'r') as f:
|
|
|
|
rules = f.read()
|
|
|
|
except Exception:
|
|
|
|
rules = None
|
|
|
|
|
|
|
|
return render_template('admin/rules.html', v=v, rules=rules)
|
|
|
|
|
|
|
|
|
|
|
|
@app.post('/admin/rules')
|
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def post_rules(v):
|
|
|
|
|
|
|
|
text = request.form.get('rules', '')
|
|
|
|
|
|
|
|
with open('./rules.md', 'w+') as f:
|
|
|
|
f.write(text)
|
|
|
|
|
|
|
|
with open('./rules.md', 'r') as f:
|
|
|
|
rules = f.read()
|
|
|
|
|
|
|
|
return render_template('admin/rules.html', v=v, rules=rules)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/shadowbanned")
|
2021-07-21 01:12:26 +00:00
|
|
|
@auth_required
|
|
|
|
def shadowbanned(v):
|
|
|
|
if not (v and v.admin_level == 6): abort(404)
|
2021-07-30 14:41:01 +00:00
|
|
|
users = [x for x in g.db.query(User).filter_by(shadowbanned = True).all()]
|
2021-07-21 01:12:26 +00:00
|
|
|
return render_template("banned.html", v=v, users=users)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/agendaposters")
|
2021-07-21 01:12:26 +00:00
|
|
|
@auth_required
|
|
|
|
def agendaposters(v):
|
|
|
|
if not (v and v.admin_level == 6): abort(404)
|
2021-07-30 14:41:01 +00:00
|
|
|
users = [x for x in g.db.query(User).filter_by(agendaposter = True).all()]
|
2021-07-21 01:12:26 +00:00
|
|
|
return render_template("banned.html", v=v, users=users)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/image_posts")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
def image_posts_listing(v):
|
|
|
|
|
2021-08-30 16:41:38 +00:00
|
|
|
try: page = int(request.args.get('page', 1))
|
|
|
|
except: page = 1
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-14 21:49:33 +00:00
|
|
|
posts = g.db.query(Submission).order_by(Submission.id.desc())
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-01 04:58:34 +00:00
|
|
|
firstrange = 25 * (page - 1)
|
|
|
|
secondrange = firstrange+26
|
|
|
|
posts = [x.id for x in posts if x.is_image][firstrange:secondrange]
|
2021-07-21 01:12:26 +00:00
|
|
|
next_exists = (len(posts) == 26)
|
2021-08-01 04:58:34 +00:00
|
|
|
posts = get_posts(posts[:25], v=v)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-31 05:28:05 +00:00
|
|
|
return render_template("admin/image_posts.html", v=v, listing=posts, next_exists=next_exists, page=page, sort="new")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-08-14 21:52:18 +00:00
|
|
|
@app.get("/admin/flagged/posts")
|
|
|
|
@admin_level_required(3)
|
|
|
|
def flagged_posts(v):
|
|
|
|
|
|
|
|
page = max(1, int(request.args.get("page", 1)))
|
|
|
|
|
|
|
|
posts = g.db.query(Submission).filter_by(
|
|
|
|
is_approved=0,
|
|
|
|
is_banned=False
|
2021-08-14 21:53:23 +00:00
|
|
|
).join(Submission.flags).order_by(Submission.id.desc()).offset(25 * (page - 1)).limit(26)
|
2021-08-14 21:52:18 +00:00
|
|
|
|
|
|
|
listing = [p.id for p in posts]
|
|
|
|
next_exists = (len(listing) == 26)
|
|
|
|
listing = listing[:25]
|
|
|
|
|
|
|
|
listing = get_posts(listing, v=v)
|
|
|
|
|
|
|
|
return render_template("admin/flagged_posts.html",
|
|
|
|
next_exists=next_exists, listing=listing, page=page, v=v)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/flagged/comments")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
def flagged_comments(v):
|
2021-08-14 21:52:18 +00:00
|
|
|
|
2021-07-21 01:12:26 +00:00
|
|
|
page = max(1, int(request.args.get("page", 1)))
|
|
|
|
|
2021-08-14 21:52:18 +00:00
|
|
|
posts = g.db.query(Comment
|
|
|
|
).filter_by(
|
|
|
|
is_approved=0,
|
|
|
|
is_banned=False
|
2021-08-14 21:53:23 +00:00
|
|
|
).join(Comment.flags).order_by(Comment.id.desc()).offset(25 * (page - 1)).limit(26).all()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-14 21:52:18 +00:00
|
|
|
listing = [p.id for p in posts]
|
|
|
|
next_exists = (len(listing) == 26)
|
|
|
|
listing = listing[:25]
|
|
|
|
|
|
|
|
listing = get_comments(listing, v=v)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
return render_template("admin/flagged_comments.html",
|
|
|
|
next_exists=next_exists,
|
2021-08-14 21:52:18 +00:00
|
|
|
listing=listing,
|
2021-07-21 01:12:26 +00:00
|
|
|
page=page,
|
|
|
|
v=v,
|
|
|
|
standalone=True)
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
def admin_home(v):
|
2021-07-26 18:52:00 +00:00
|
|
|
with open('./disablesignups', 'r') as f:
|
|
|
|
x = f.read()
|
|
|
|
return render_template("admin/admin_home.html", v=v, x=x)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-22 16:49:41 +00:00
|
|
|
@app.post("/admin/monthly")
|
2021-08-22 17:37:18 +00:00
|
|
|
@limiter.limit("1/day")
|
2021-08-22 16:46:52 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
def monthly(v):
|
2021-08-22 16:52:43 +00:00
|
|
|
thing = g.db.query(AwardRelationship).order_by(AwardRelationship.id.desc()).first().id
|
2021-08-22 16:51:39 +00:00
|
|
|
_awards = []
|
2021-08-22 16:46:52 +00:00
|
|
|
for u in g.db.query(User).filter(User.patron > 0).all():
|
2021-08-22 16:50:59 +00:00
|
|
|
grant_awards = {}
|
|
|
|
|
2021-08-22 16:46:52 +00:00
|
|
|
if u.patron == 1:
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["shit"] = 1
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 1
|
2021-08-22 16:46:52 +00:00
|
|
|
elif u.patron == 2:
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["shit"] = 3
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 3
|
2021-08-22 16:46:52 +00:00
|
|
|
elif u.patron == 3:
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["shit"] = 5
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 5
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["ban"] = 1
|
2021-08-31 18:47:26 +00:00
|
|
|
elif u.patron == 4:
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["shit"] = 10
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 10
|
2021-08-24 17:45:07 +00:00
|
|
|
grant_awards["ban"] = 3
|
2021-08-31 18:47:26 +00:00
|
|
|
elif u.patron == 5 or u.patron == 8:
|
2021-08-30 21:25:21 +00:00
|
|
|
grant_awards["shit"] = 20
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 20
|
2021-08-30 21:19:10 +00:00
|
|
|
grant_awards["ban"] = 6
|
2021-08-22 16:46:52 +00:00
|
|
|
|
|
|
|
|
2021-08-22 16:50:59 +00:00
|
|
|
for name in grant_awards:
|
|
|
|
for count in range(grant_awards[name]):
|
2021-08-22 16:46:52 +00:00
|
|
|
|
2021-08-22 16:50:59 +00:00
|
|
|
thing += 1
|
2021-08-22 16:46:52 +00:00
|
|
|
|
2021-08-22 16:50:59 +00:00
|
|
|
_awards.append(AwardRelationship(
|
|
|
|
id=thing,
|
|
|
|
user_id=u.id,
|
|
|
|
kind=name
|
|
|
|
))
|
2021-08-22 16:46:52 +00:00
|
|
|
|
2021-08-22 17:32:14 +00:00
|
|
|
text = "You were given the following awards:\n\n"
|
|
|
|
|
|
|
|
for key, value in grant_awards.items():
|
|
|
|
text += f" - **{value}** {AWARDS[key]['title']} {'Awards' if value != 1 else 'Award'}\n"
|
|
|
|
|
2021-08-22 17:36:34 +00:00
|
|
|
send_notification(NOTIFICATIONS_ACCOUNT, u, text)
|
2021-08-22 17:32:14 +00:00
|
|
|
|
2021-08-22 16:46:52 +00:00
|
|
|
g.db.bulk_save_objects(_awards)
|
|
|
|
|
2021-08-22 17:32:14 +00:00
|
|
|
|
2021-08-22 16:46:52 +00:00
|
|
|
return {"message": "Monthly awards granted"}
|
|
|
|
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/disablesignups")
|
2021-07-26 19:15:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def disablesignups(v):
|
2021-07-26 19:18:04 +00:00
|
|
|
with open('./disablesignups', 'r+') as f:
|
2021-09-08 10:57:56 +00:00
|
|
|
if f.read() == "yes":
|
|
|
|
f.write("no")
|
|
|
|
return {"message": "Signups enabed!"}
|
|
|
|
else:
|
|
|
|
f.write("yes")
|
|
|
|
return {"message": "Signups disabled!"}
|
2021-07-26 19:15:26 +00:00
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/badge_grant")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
def badge_grant_get(v):
|
|
|
|
|
2021-09-03 20:35:09 +00:00
|
|
|
badge_types = g.db.query(BadgeDef).all()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
errors = {"already_owned": "That user already has that badge.",
|
|
|
|
"no_user": "That user doesn't exist."
|
|
|
|
}
|
|
|
|
|
|
|
|
return render_template("admin/badge_grant.html",
|
|
|
|
v=v,
|
|
|
|
badge_types=badge_types,
|
|
|
|
error=errors.get(
|
|
|
|
request.args.get("error"),
|
|
|
|
None) if request.args.get('error') else None,
|
|
|
|
msg="Badge successfully assigned" if request.args.get(
|
|
|
|
"msg") else None
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/badge_grant")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
|
|
|
def badge_grant_post(v):
|
|
|
|
|
|
|
|
user = get_user(request.form.get("username"), graceful=True)
|
|
|
|
if not user: return redirect("/badge_grant?error=no_user")
|
|
|
|
|
2021-09-09 04:41:02 +00:00
|
|
|
try: badge_id = int(request.form.get("badge_id"))
|
|
|
|
except: abort(400)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
if user.has_badge(badge_id):
|
|
|
|
g.db.query(Badge).filter_by(badge_id=badge_id, user_id=user.id,).delete()
|
2021-09-03 14:02:25 +00:00
|
|
|
return redirect("/admin/badge_grant")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
new_badge = Badge(badge_id=badge_id,
|
|
|
|
user_id=user.id,
|
|
|
|
)
|
|
|
|
|
|
|
|
desc = request.form.get("description")
|
|
|
|
if desc: new_badge.description = desc
|
|
|
|
|
|
|
|
url = request.form.get("url")
|
|
|
|
if url: new_badge.url = url
|
|
|
|
|
|
|
|
g.db.add(new_badge)
|
2021-08-13 00:07:07 +00:00
|
|
|
g.db.flush()
|
|
|
|
|
2021-07-21 01:12:26 +00:00
|
|
|
text = f"""
|
|
|
|
@{v.username} has given you the following profile badge:
|
|
|
|
\n\n![]({new_badge.path})
|
|
|
|
\n\n{new_badge.name}
|
|
|
|
"""
|
2021-08-21 11:06:28 +00:00
|
|
|
send_notification(NOTIFICATIONS_ACCOUNT, user, text)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-03 14:02:25 +00:00
|
|
|
if badge_id == 16 and user.has_badge(17):
|
|
|
|
g.db.query(Badge).filter_by(badge_id=17, user_id=user.id).delete()
|
|
|
|
|
|
|
|
elif badge_id in [21,22,23,24,28]:
|
2021-07-31 21:50:25 +00:00
|
|
|
user.patron = int(str(badge_id)[-1])
|
|
|
|
|
|
|
|
grant_awards = {}
|
|
|
|
|
2021-08-02 07:15:01 +00:00
|
|
|
if badge_id == 21:
|
2021-08-26 13:37:47 +00:00
|
|
|
if user.discord_id: add_role(user, "1")
|
2021-08-02 07:15:01 +00:00
|
|
|
grant_awards["shit"] = 1
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 1
|
2021-08-02 07:15:01 +00:00
|
|
|
elif badge_id == 22:
|
2021-08-26 13:37:47 +00:00
|
|
|
if user.discord_id: add_role(user, "2")
|
2021-08-02 07:15:01 +00:00
|
|
|
grant_awards["shit"] = 3
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 3
|
2021-08-02 07:15:01 +00:00
|
|
|
elif badge_id == 23:
|
2021-08-26 13:37:47 +00:00
|
|
|
if user.discord_id: add_role(user, "3")
|
2021-07-31 21:50:25 +00:00
|
|
|
grant_awards["shit"] = 5
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 5
|
2021-08-02 07:15:01 +00:00
|
|
|
grant_awards["ban"] = 1
|
2021-07-31 21:50:25 +00:00
|
|
|
elif badge_id in [24, 28]:
|
2021-08-26 13:37:47 +00:00
|
|
|
if user.discord_id: add_role(user, "4")
|
2021-07-31 21:50:25 +00:00
|
|
|
grant_awards["shit"] = 10
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 10
|
2021-08-02 07:15:01 +00:00
|
|
|
grant_awards["ban"] = 3
|
2021-08-30 21:23:42 +00:00
|
|
|
elif badge_id == 25:
|
|
|
|
if user.discord_id: add_role(user, "5")
|
2021-08-30 21:25:21 +00:00
|
|
|
grant_awards["shit"] = 20
|
2021-09-08 03:22:13 +00:00
|
|
|
grant_awards["stars"] = 20
|
2021-08-30 21:23:42 +00:00
|
|
|
grant_awards["ban"] = 6
|
2021-07-31 21:50:25 +00:00
|
|
|
|
|
|
|
if len(grant_awards):
|
|
|
|
|
|
|
|
_awards = []
|
|
|
|
|
|
|
|
thing = g.db.query(AwardRelationship).order_by(AwardRelationship.id.desc()).first().id
|
|
|
|
|
|
|
|
for name in grant_awards:
|
|
|
|
for count in range(grant_awards[name]):
|
|
|
|
|
|
|
|
thing += 1
|
|
|
|
|
|
|
|
_awards.append(AwardRelationship(
|
|
|
|
id=thing,
|
|
|
|
user_id=user.id,
|
|
|
|
kind=name
|
|
|
|
))
|
|
|
|
|
|
|
|
g.db.bulk_save_objects(_awards)
|
|
|
|
|
2021-08-22 17:32:14 +00:00
|
|
|
text = "You were given the following awards:\n\n"
|
|
|
|
|
|
|
|
for key, value in grant_awards.items():
|
|
|
|
text += f" - **{value}** {AWARDS[key]['title']} {'Awards' if value != 1 else 'Award'}\n"
|
|
|
|
|
|
|
|
send_notification(NOTIFICATIONS_ACCOUNT, user, text)
|
|
|
|
|
|
|
|
|
2021-07-31 21:50:25 +00:00
|
|
|
g.db.add(user)
|
2021-07-23 14:08:49 +00:00
|
|
|
|
2021-08-31 15:25:17 +00:00
|
|
|
return redirect("/admin/badge_grant")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/users")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(2)
|
|
|
|
def users_list(v):
|
|
|
|
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
|
|
users = g.db.query(User).filter_by(is_banned=0
|
|
|
|
).order_by(User.created_utc.desc()
|
|
|
|
).offset(25 * (page - 1)).limit(26)
|
|
|
|
|
|
|
|
users = [x for x in users]
|
|
|
|
|
|
|
|
next_exists = (len(users) == 26)
|
2021-07-28 10:57:41 +00:00
|
|
|
users = users[:25]
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
return render_template("admin/new_users.html",
|
|
|
|
v=v,
|
|
|
|
users=users,
|
|
|
|
next_exists=next_exists,
|
|
|
|
page=page,
|
|
|
|
)
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/alt_votes")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
def alt_votes_get(v):
|
|
|
|
|
|
|
|
if not request.args.get("u1") or not request.args.get("u2"):
|
|
|
|
return render_template("admin/alt_votes.html", v=v)
|
|
|
|
|
|
|
|
u1 = request.args.get("u1")
|
|
|
|
u2 = request.args.get("u2")
|
|
|
|
|
|
|
|
if not u1 or not u2:
|
|
|
|
return redirect("/admin/alt_votes")
|
|
|
|
|
|
|
|
u1 = get_user(u1)
|
|
|
|
u2 = get_user(u2)
|
|
|
|
|
|
|
|
u1_post_ups = g.db.query(
|
|
|
|
Vote.submission_id).filter_by(
|
|
|
|
user_id=u1.id,
|
|
|
|
vote_type=1).all()
|
|
|
|
u1_post_downs = g.db.query(
|
|
|
|
Vote.submission_id).filter_by(
|
|
|
|
user_id=u1.id,
|
|
|
|
vote_type=-1).all()
|
|
|
|
u1_comment_ups = g.db.query(
|
|
|
|
CommentVote.comment_id).filter_by(
|
|
|
|
user_id=u1.id,
|
|
|
|
vote_type=1).all()
|
|
|
|
u1_comment_downs = g.db.query(
|
|
|
|
CommentVote.comment_id).filter_by(
|
|
|
|
user_id=u1.id,
|
|
|
|
vote_type=-1).all()
|
|
|
|
u2_post_ups = g.db.query(
|
|
|
|
Vote.submission_id).filter_by(
|
|
|
|
user_id=u2.id,
|
|
|
|
vote_type=1).all()
|
|
|
|
u2_post_downs = g.db.query(
|
|
|
|
Vote.submission_id).filter_by(
|
|
|
|
user_id=u2.id,
|
|
|
|
vote_type=-1).all()
|
|
|
|
u2_comment_ups = g.db.query(
|
|
|
|
CommentVote.comment_id).filter_by(
|
|
|
|
user_id=u2.id,
|
|
|
|
vote_type=1).all()
|
|
|
|
u2_comment_downs = g.db.query(
|
|
|
|
CommentVote.comment_id).filter_by(
|
|
|
|
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
|
|
|
|
|
|
|
|
return render_template("admin/alt_votes.html",
|
|
|
|
u1=u1,
|
|
|
|
u2=u2,
|
|
|
|
v=v,
|
|
|
|
data=data
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/link_accounts")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
|
|
|
def admin_link_accounts(v):
|
|
|
|
|
|
|
|
u1 = int(request.form.get("u1"))
|
|
|
|
u2 = int(request.form.get("u2"))
|
|
|
|
|
|
|
|
new_alt = Alt(
|
|
|
|
user1=u1,
|
|
|
|
user2=u2,
|
|
|
|
is_manual=True
|
|
|
|
)
|
|
|
|
|
|
|
|
g.db.add(new_alt)
|
|
|
|
|
|
|
|
return redirect(f"/admin/alt_votes?u1={g.db.query(User).get(u1).username}&u2={g.db.query(User).get(u2).username}")
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/removed")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
def admin_removed(v):
|
|
|
|
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
|
|
ids = g.db.query(Submission.id).options(lazyload('*')).filter_by(is_banned=True).order_by(
|
|
|
|
Submission.id.desc()).offset(25 * (page - 1)).limit(26).all()
|
|
|
|
|
|
|
|
ids=[x[0] for x in ids]
|
|
|
|
|
|
|
|
next_exists = len(ids) == 26
|
|
|
|
|
2021-07-28 10:57:41 +00:00
|
|
|
ids = ids[:25]
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
posts = get_posts(ids, v=v)
|
|
|
|
|
|
|
|
return render_template("admin/removed_posts.html",
|
|
|
|
v=v,
|
|
|
|
listing=posts,
|
|
|
|
page=page,
|
|
|
|
next_exists=next_exists
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/image_purge")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(5)
|
|
|
|
def admin_image_purge(v):
|
|
|
|
|
2021-07-29 07:53:32 +00:00
|
|
|
name = request.form.get("url")
|
|
|
|
image = g.db.query(Image).filter(Image.text == name).first()
|
|
|
|
if image:
|
2021-08-05 14:43:54 +00:00
|
|
|
requests.delete(f'https://api.imgur.com/3/image/{image.deletehash}', headers = {"Authorization": f"Client-ID {IMGUR_KEY}"})
|
2021-07-29 07:53:32 +00:00
|
|
|
headers = {"Authorization": f"Bearer {CF_KEY}", "Content-Type": "application/json"}
|
|
|
|
data = {'files': [name]}
|
|
|
|
url = f"https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache"
|
|
|
|
requests.post(url, headers=headers, json=data)
|
2021-07-21 01:12:26 +00:00
|
|
|
return redirect("/admin/image_purge")
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/image_ban")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
|
|
|
def admin_image_ban(v):
|
|
|
|
|
|
|
|
i=request.files['file']
|
|
|
|
|
|
|
|
|
|
|
|
#make phash
|
|
|
|
tempname = f"admin_image_ban_{v.username}_{int(time.time())}"
|
|
|
|
|
|
|
|
i.save(tempname)
|
|
|
|
|
|
|
|
h=imagehash.phash(IMAGE.open(tempname))
|
2021-07-30 05:42:50 +00:00
|
|
|
|
|
|
|
value = int(str(h), 16)
|
|
|
|
bindigits = []
|
|
|
|
|
|
|
|
# Seed digit: 2**0
|
|
|
|
digit = (value % 2)
|
|
|
|
value //= 2
|
|
|
|
bindigits.append(digit)
|
|
|
|
|
|
|
|
while value > 0:
|
|
|
|
# Next power of 2**n
|
|
|
|
digit = (value % 2)
|
|
|
|
value //= 2
|
|
|
|
bindigits.append(digit)
|
|
|
|
|
|
|
|
h = ''.join([str(d) for d in bindigits])
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
#check db for existing
|
|
|
|
badpic = g.db.query(BadPic).filter_by(
|
|
|
|
phash=h
|
|
|
|
).first()
|
|
|
|
|
|
|
|
remove(tempname)
|
|
|
|
|
|
|
|
if badpic:
|
|
|
|
return render_template("admin/image_ban.html", v=v, existing=badpic)
|
|
|
|
|
|
|
|
new_bp=BadPic(
|
|
|
|
phash=h,
|
|
|
|
ban_reason=request.form.get("ban_reason"),
|
|
|
|
ban_time=int(request.form.get("ban_length",0))
|
|
|
|
)
|
|
|
|
|
|
|
|
g.db.add(new_bp)
|
|
|
|
|
|
|
|
return render_template("admin/image_ban.html", v=v, success=True)
|
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/agendaposter/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def agendaposter(user_id, v):
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
|
|
|
|
expiry = request.form.get("days", 0)
|
|
|
|
if expiry:
|
|
|
|
expiry = int(expiry)
|
|
|
|
expiry = g.timestamp + expiry*60*60*24
|
|
|
|
else:
|
|
|
|
expiry = 0
|
|
|
|
|
|
|
|
user.agendaposter = not user.agendaposter
|
|
|
|
user.agendaposter_expires_utc = expiry
|
|
|
|
g.db.add(user)
|
|
|
|
for alt in user.alts:
|
|
|
|
if alt.admin_level > 0: break
|
|
|
|
alt.agendaposter = user.agendaposter
|
|
|
|
alt.agendaposter_expires_utc = expiry
|
|
|
|
g.db.add(alt)
|
|
|
|
|
|
|
|
note = None
|
|
|
|
|
|
|
|
if not user.agendaposter: kind = "unagendaposter"
|
|
|
|
else:
|
|
|
|
kind = "agendaposter"
|
|
|
|
note = f"for {request.form.get('days')} days" if expiry else "never expires"
|
|
|
|
|
|
|
|
ma = ModAction(
|
|
|
|
kind=kind,
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
note = note
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
2021-08-11 17:01:19 +00:00
|
|
|
user.refresh_selfset_badges()
|
|
|
|
|
2021-09-08 07:05:43 +00:00
|
|
|
g.db.flush()
|
|
|
|
|
2021-09-08 07:08:10 +00:00
|
|
|
if user.agendaposter: send_notification(NOTIFICATIONS_ACCOUNT, user, f"You have been marked by an admin as an agendaposter ({note}).")
|
|
|
|
else: send_notification(NOTIFICATIONS_ACCOUNT, user, f"You have been unmarked by an admin as an agendaposter.")
|
2021-09-08 07:05:43 +00:00
|
|
|
|
2021-08-19 06:22:40 +00:00
|
|
|
return (redirect(user.url), user)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/shadowban/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def shadowban(user_id, v):
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
if user.admin_level != 0: abort(403)
|
|
|
|
user.shadowbanned = True
|
|
|
|
g.db.add(user)
|
|
|
|
for alt in user.alts:
|
|
|
|
if alt.admin_level > 0: break
|
|
|
|
alt.shadowbanned = True
|
|
|
|
g.db.add(alt)
|
|
|
|
ma = ModAction(
|
|
|
|
kind="shadowban",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
2021-07-28 11:00:15 +00:00
|
|
|
|
2021-08-18 00:32:36 +00:00
|
|
|
cache.delete_memoized(frontlist)
|
2021-07-30 09:42:17 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User shadowbanned!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/unshadowban/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def unshadowban(user_id, v):
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
if user.admin_level != 0: abort(403)
|
|
|
|
user.shadowbanned = False
|
|
|
|
g.db.add(user)
|
|
|
|
for alt in user.alts:
|
|
|
|
alt.shadowbanned = False
|
|
|
|
g.db.add(alt)
|
|
|
|
|
|
|
|
ma = ModAction(
|
|
|
|
kind="unshadowban",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
2021-07-28 11:00:15 +00:00
|
|
|
|
2021-08-18 00:32:36 +00:00
|
|
|
cache.delete_memoized(frontlist)
|
2021-07-30 09:42:17 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User unshadowbanned!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-06 02:24:27 +00:00
|
|
|
@app.post("/admin/verify/<user_id>")
|
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def verify(user_id, v):
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
2021-09-06 02:59:59 +00:00
|
|
|
user.verified = "Verified"
|
2021-09-06 02:24:27 +00:00
|
|
|
g.db.add(user)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User verfied!"}
|
2021-09-06 02:24:27 +00:00
|
|
|
|
|
|
|
@app.post("/admin/unverify/<user_id>")
|
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
2021-09-06 02:48:53 +00:00
|
|
|
def unverify(user_id, v):
|
2021-09-06 02:24:27 +00:00
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
2021-09-06 02:59:59 +00:00
|
|
|
user.verified = None
|
2021-09-06 02:24:27 +00:00
|
|
|
g.db.add(user)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "User unverified!"}
|
2021-09-06 02:24:27 +00:00
|
|
|
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/title_change/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def admin_title_change(user_id, v):
|
|
|
|
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
|
|
|
|
if user.admin_level != 0: abort(403)
|
|
|
|
|
|
|
|
new_name=request.form.get("title").strip()
|
|
|
|
|
|
|
|
user.customtitleplain=new_name
|
2021-08-21 12:57:16 +00:00
|
|
|
new_name = sanitize(new_name)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
user=g.db.query(User).with_for_update().options(lazyload('*')).filter_by(id=user.id).first()
|
|
|
|
user.customtitle=new_name
|
|
|
|
user.flairchanged = bool(request.form.get("locked"))
|
|
|
|
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,
|
|
|
|
note=f'"{new_name}"'
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
|
|
|
return (redirect(user.url), user)
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/ban_user/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def ban_user(user_id, v):
|
|
|
|
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
|
2021-07-28 22:11:18 +00:00
|
|
|
if user.admin_level >= v.admin_level: abort(403)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
# check for number of days for suspension
|
|
|
|
days = int(request.form.get("days")) if request.form.get('days') else 0
|
2021-09-05 09:49:48 +00:00
|
|
|
reason = sanitize(request.values.get("reason", ""))
|
2021-08-11 17:01:19 +00:00
|
|
|
message = request.values.get("reason", "")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
if not user: abort(400)
|
|
|
|
|
2021-07-28 22:11:18 +00:00
|
|
|
#if user.admin_level > 0: abort(403)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
if days > 0:
|
|
|
|
if message:
|
2021-08-04 16:00:57 +00:00
|
|
|
text = f"Your account has been suspended for {days} days for the following reason:\n\n> {message}"
|
2021-07-21 01:12:26 +00:00
|
|
|
else:
|
2021-08-04 16:00:57 +00:00
|
|
|
text = f"Your account has been suspended for {days} days."
|
2021-07-21 01:12:26 +00:00
|
|
|
user.ban(admin=v, reason=reason, days=days)
|
|
|
|
|
|
|
|
else:
|
|
|
|
if message:
|
2021-08-04 16:00:57 +00:00
|
|
|
text = f"Your account has been permanently suspended for the following reason:\n\n> {message}"
|
2021-07-21 01:12:26 +00:00
|
|
|
else:
|
2021-08-04 16:00:57 +00:00
|
|
|
text = "Your account has been permanently suspended."
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
user.ban(admin=v, reason=reason)
|
|
|
|
|
2021-07-29 21:01:22 +00:00
|
|
|
if request.form.get("alts", ""):
|
|
|
|
for x in user.alts:
|
|
|
|
if x.admin_level > 0: break
|
|
|
|
x.ban(admin=v, reason=reason)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-21 11:06:28 +00:00
|
|
|
send_notification(NOTIFICATIONS_ACCOUNT, user, text)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-29 21:01:22 +00:00
|
|
|
if days == 0: duration = "permanent"
|
2021-07-21 01:12:26 +00:00
|
|
|
elif days == 1: duration = "1 day"
|
|
|
|
else: duration = f"{days} days"
|
|
|
|
ma=ModAction(
|
|
|
|
kind="exile_user",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
2021-09-08 08:53:57 +00:00
|
|
|
note=f'reason: "{reason}", duration: {duration}'
|
2021-07-21 01:12:26 +00:00
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
2021-08-11 22:26:04 +00:00
|
|
|
if 'reason' in request.args:
|
|
|
|
if reason.startswith("/post/"):
|
|
|
|
post = reason.split("/post/")[1].split("/")[0]
|
|
|
|
post = get_post(post)
|
|
|
|
post.bannedfor = True
|
|
|
|
g.db.add(post)
|
|
|
|
elif reason.startswith("/comment/"):
|
2021-08-11 22:27:07 +00:00
|
|
|
comment = reason.split("/comment/")[1].split("/")[0]
|
2021-08-11 22:26:04 +00:00
|
|
|
comment = get_comment(comment)
|
|
|
|
comment.bannedfor = True
|
|
|
|
g.db.add(comment)
|
|
|
|
return {"message": f"@{user.username} was banned!"}
|
2021-08-11 17:01:19 +00:00
|
|
|
else: return redirect(user.url)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/unban_user/<user_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(6)
|
|
|
|
@validate_formkey
|
|
|
|
def unban_user(user_id, v):
|
|
|
|
|
|
|
|
user = g.db.query(User).filter_by(id=user_id).first()
|
|
|
|
|
|
|
|
if not user:
|
|
|
|
abort(400)
|
|
|
|
|
|
|
|
user.unban()
|
|
|
|
|
2021-07-29 21:01:22 +00:00
|
|
|
if request.form.get("alts", ""):
|
|
|
|
for x in user.alts:
|
|
|
|
if x.admin_level == 0:
|
|
|
|
x.unban()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-21 11:06:28 +00:00
|
|
|
send_notification(NOTIFICATIONS_ACCOUNT, user,
|
2021-08-04 16:00:57 +00:00
|
|
|
"Your account has been reinstated. Please carefully review and abide by the [rules](/post/2510) to ensure that you don't get suspended again.")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
ma=ModAction(
|
|
|
|
kind="unexile_user",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
2021-07-30 09:42:17 +00:00
|
|
|
|
2021-09-08 21:19:48 +00:00
|
|
|
if "@" in request.referrer:
|
2021-08-11 17:01:19 +00:00
|
|
|
return redirect(user.url)
|
2021-09-08 21:19:48 +00:00
|
|
|
else:
|
|
|
|
return {"message": f"@{user.username} was unbanned!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/ban_post/<post_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
@validate_formkey
|
|
|
|
def ban_post(post_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
post = g.db.query(Submission).filter_by(id=post_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
if not post:
|
|
|
|
abort(400)
|
|
|
|
|
|
|
|
post.is_banned = True
|
|
|
|
post.is_approved = 0
|
|
|
|
post.stickied = False
|
|
|
|
post.is_pinned = False
|
|
|
|
|
|
|
|
ban_reason=request.form.get("reason", "")
|
2021-09-03 17:09:42 +00:00
|
|
|
ban_reason = ban_reason.replace("\n", "\n\n").replace("\n\n\n\n\n\n", "\n\n").replace("\n\n\n\n", "\n\n").replace("\n\n\n", "\n\n")
|
2021-07-21 01:12:26 +00:00
|
|
|
with CustomRenderer() as renderer:
|
|
|
|
ban_reason = renderer.render(mistletoe.Document(ban_reason))
|
2021-08-21 12:57:16 +00:00
|
|
|
ban_reason = sanitize(ban_reason)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
post.ban_reason = ban_reason
|
|
|
|
|
|
|
|
g.db.add(post)
|
|
|
|
|
2021-07-28 11:00:15 +00:00
|
|
|
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
ma=ModAction(
|
|
|
|
kind="ban_post",
|
|
|
|
user_id=v.id,
|
|
|
|
target_submission_id=post.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
2021-07-30 09:42:17 +00:00
|
|
|
|
2021-08-18 00:32:36 +00:00
|
|
|
cache.delete_memoized(frontlist)
|
2021-07-30 09:42:17 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Post removed!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/unban_post/<post_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
@validate_formkey
|
|
|
|
def unban_post(post_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
post = g.db.query(Submission).filter_by(id=post_id).first()
|
2021-07-21 01:12:26 +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
|
|
|
|
post.is_approved = v.id
|
|
|
|
|
|
|
|
g.db.add(post)
|
|
|
|
|
2021-08-18 00:32:36 +00:00
|
|
|
cache.delete_memoized(frontlist)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Post approved!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/distinguish/<post_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(1)
|
|
|
|
@validate_formkey
|
|
|
|
def api_distinguish_post(post_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
post = g.db.query(Submission).filter_by(id=post_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
if not post:
|
|
|
|
abort(404)
|
|
|
|
|
|
|
|
if not post.author_id == v.id:
|
|
|
|
abort(403)
|
|
|
|
|
|
|
|
if post.distinguish_level:
|
|
|
|
post.distinguish_level = 0
|
|
|
|
else:
|
|
|
|
post.distinguish_level = v.admin_level
|
|
|
|
|
|
|
|
g.db.add(post)
|
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Post distinguished!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/sticky/<post_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(3)
|
|
|
|
def api_sticky_post(post_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
post = g.db.query(Submission).filter_by(id=post_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
if post:
|
|
|
|
post.stickied = not (post.stickied)
|
|
|
|
g.db.add(post)
|
2021-08-27 21:19:08 +00:00
|
|
|
|
|
|
|
ma=ModAction(
|
2021-08-27 21:23:18 +00:00
|
|
|
kind="pin_post" if post.stickied else "unpin_post",
|
2021-08-27 21:19:08 +00:00
|
|
|
user_id=v.id,
|
2021-08-27 21:20:06 +00:00
|
|
|
target_submission_id=post.id
|
2021-08-27 21:19:08 +00:00
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
|
|
|
cache.delete_memoized(frontlist)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
g.db.flush()
|
|
|
|
if post.stickied: return {"message": "Post pinned!"}
|
|
|
|
else: return {"message": "Post unpinned!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/pin/<post_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@auth_required
|
|
|
|
def api_pin_post(post_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
post = g.db.query(Submission).filter_by(id=post_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
if post:
|
|
|
|
post.is_pinned = not (post.is_pinned)
|
|
|
|
g.db.add(post)
|
2021-09-08 10:57:56 +00:00
|
|
|
g.db.flush()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
if post.is_pinned: return {"message": "Post pinned!"}
|
|
|
|
else: return {"message": "Post unpinned!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/ban_comment/<c_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(1)
|
|
|
|
def api_ban_comment(c_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
comment = g.db.query(Comment).filter_by(id=c_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
if not comment:
|
|
|
|
abort(404)
|
|
|
|
|
|
|
|
comment.is_banned = True
|
|
|
|
comment.is_approved = 0
|
|
|
|
|
|
|
|
g.db.add(comment)
|
|
|
|
ma=ModAction(
|
|
|
|
kind="ban_comment",
|
|
|
|
user_id=v.id,
|
|
|
|
target_comment_id=comment.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Comment removed!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/unban_comment/<c_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(1)
|
|
|
|
def api_unban_comment(c_id, v):
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
comment = g.db.query(Comment).filter_by(id=c_id).first()
|
2021-07-21 01:12:26 +00:00
|
|
|
if not comment:
|
|
|
|
abort(404)
|
|
|
|
g.db.add(comment)
|
|
|
|
|
|
|
|
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
|
|
|
|
comment.is_approved = v.id
|
|
|
|
|
|
|
|
|
2021-09-08 10:57:56 +00:00
|
|
|
return {"message": "Comment approved!"}
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-31 04:48:47 +00:00
|
|
|
@app.post("/distinguish_comment/<c_id>")
|
2021-07-21 01:12:26 +00:00
|
|
|
@auth_required
|
|
|
|
def admin_distinguish_comment(c_id, v):
|
|
|
|
|
|
|
|
if v.admin_level == 0: abort(403)
|
|
|
|
|
|
|
|
comment = get_comment(c_id, v=v)
|
|
|
|
|
|
|
|
if comment.author_id != v.id:
|
|
|
|
abort(403)
|
|
|
|
|
|
|
|
comment.distinguish_level = 0 if comment.distinguish_level else v.admin_level
|
|
|
|
|
|
|
|
g.db.add(comment)
|
|
|
|
html=render_template(
|
|
|
|
"comments.html",
|
|
|
|
v=v,
|
|
|
|
comments=[comment],
|
|
|
|
render_replies=False,
|
|
|
|
)
|
|
|
|
|
2021-07-30 05:31:38 +00:00
|
|
|
html=str(BeautifulSoup(html, features="html.parser").find(id=f"comment-{comment.id}-only"))
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-31 05:28:05 +00:00
|
|
|
return html
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.get("/admin/dump_cache")
|
2021-07-23 16:01:10 +00:00
|
|
|
@admin_level_required(6)
|
2021-07-23 15:57:38 +00:00
|
|
|
def admin_dump_cache(v):
|
|
|
|
cache.clear()
|
2021-07-31 05:28:05 +00:00
|
|
|
return {"message": "Internal cache cleared."}
|
2021-07-23 15:57:38 +00:00
|
|
|
|
|
|
|
|
2021-08-03 12:07:06 +00:00
|
|
|
@app.get("/admin/banned_domains/")
|
|
|
|
@admin_level_required(4)
|
|
|
|
def admin_banned_domains(v):
|
|
|
|
|
2021-08-03 12:16:57 +00:00
|
|
|
banned_domains = g.db.query(BannedDomain).all()
|
|
|
|
return render_template("admin/banned_domains.html", v=v, banned_domains=banned_domains)
|
2021-08-03 12:07:06 +00:00
|
|
|
|
2021-08-03 12:26:12 +00:00
|
|
|
@app.post("/admin/banned_domains")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
2021-08-03 12:25:47 +00:00
|
|
|
def admin_toggle_ban_domain(v):
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-09 22:41:37 +00:00
|
|
|
domain=request.form.get("domain", "").strip()
|
2021-08-01 04:24:46 +00:00
|
|
|
if not domain: abort(400)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-03 12:24:56 +00:00
|
|
|
reason=request.form.get("reason", "").strip()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-08-03 19:00:12 +00:00
|
|
|
d = g.db.query(BannedDomain).filter_by(domain=domain).first()
|
2021-08-03 12:23:10 +00:00
|
|
|
if d: g.db.delete(d)
|
|
|
|
else:
|
|
|
|
d = BannedDomain(domain=domain, reason=reason)
|
|
|
|
g.db.add(d)
|
2021-08-03 12:16:57 +00:00
|
|
|
return redirect("/admin/banned_domains/")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/nuke_user")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
|
|
|
def admin_nuke_user(v):
|
|
|
|
|
|
|
|
user=get_user(request.form.get("user"))
|
|
|
|
|
|
|
|
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
|
|
|
|
if post.is_banned:
|
|
|
|
continue
|
|
|
|
|
|
|
|
post.is_banned=True
|
|
|
|
g.db.add(post)
|
|
|
|
|
|
|
|
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
|
|
|
|
if comment.is_banned:
|
|
|
|
continue
|
|
|
|
|
|
|
|
comment.is_banned=True
|
|
|
|
g.db.add(comment)
|
|
|
|
|
|
|
|
ma=ModAction(
|
|
|
|
kind="nuke_user",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
2021-07-27 00:05:58 +00:00
|
|
|
return redirect(user.url)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-27 22:31:28 +00:00
|
|
|
@app.post("/admin/unnuke_user")
|
2021-07-21 01:12:26 +00:00
|
|
|
@admin_level_required(4)
|
|
|
|
@validate_formkey
|
|
|
|
def admin_nunuke_user(v):
|
|
|
|
|
|
|
|
user=get_user(request.form.get("user"))
|
|
|
|
|
|
|
|
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
|
|
|
|
if not post.is_banned:
|
|
|
|
continue
|
|
|
|
|
|
|
|
post.is_banned=False
|
|
|
|
g.db.add(post)
|
|
|
|
|
|
|
|
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
|
|
|
|
if not comment.is_banned:
|
|
|
|
continue
|
|
|
|
|
|
|
|
comment.is_banned=False
|
|
|
|
g.db.add(comment)
|
|
|
|
|
|
|
|
ma=ModAction(
|
|
|
|
kind="unnuke_user",
|
|
|
|
user_id=v.id,
|
|
|
|
target_user_id=user.id,
|
|
|
|
)
|
|
|
|
g.db.add(ma)
|
|
|
|
|
2021-07-27 00:05:58 +00:00
|
|
|
return redirect(user.url)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-09-10 03:33:36 +00:00
|
|
|
@app.get("/chart")
|
|
|
|
@auth_required
|
|
|
|
def chart(v):
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
days = int(request.args.get("days", 25))
|
|
|
|
|
|
|
|
now = time.gmtime()
|
|
|
|
midnight_this_morning = time.struct_time((now.tm_year,
|
|
|
|
now.tm_mon,
|
|
|
|
now.tm_mday,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
now.tm_wday,
|
|
|
|
now.tm_yday,
|
|
|
|
0)
|
|
|
|
)
|
|
|
|
today_cutoff = calendar.timegm(midnight_this_morning)
|
|
|
|
|
|
|
|
day = 3600 * 24
|
|
|
|
|
|
|
|
day_cutoffs = [today_cutoff - day * i for i in range(days)]
|
|
|
|
day_cutoffs.insert(0, calendar.timegm(now))
|
|
|
|
|
|
|
|
daily_signups = [{"date": time.strftime("%d", time.gmtime(day_cutoffs[i + 1])),
|
|
|
|
"day_start":day_cutoffs[i + 1],
|
|
|
|
"signups": g.db.query(User).filter(User.created_utc < day_cutoffs[i],
|
2021-08-07 11:21:16 +00:00
|
|
|
User.created_utc > day_cutoffs[i + 1] ).count()
|
2021-07-21 01:12:26 +00:00
|
|
|
} for i in range(len(day_cutoffs) - 1)
|
|
|
|
]
|
|
|
|
|
|
|
|
user_stats = {'current_users': g.db.query(User).filter_by(is_banned=0, reserved=None).count(),
|
|
|
|
'banned_users': g.db.query(User).filter(User.is_banned != 0).count(),
|
2021-07-28 04:17:23 +00:00
|
|
|
'reserved_users': g.db.query(User).filter(User.reserved != None).count(),
|
2021-07-21 01:12:26 +00:00
|
|
|
'email_verified_users': g.db.query(User).filter_by(is_banned=0, is_activated=True).count(),
|
|
|
|
}
|
|
|
|
|
|
|
|
post_stats = [{"date": time.strftime("%d", time.gmtime(day_cutoffs[i + 1])),
|
|
|
|
"day_start":day_cutoffs[i + 1],
|
|
|
|
"posts": g.db.query(Submission).filter(Submission.created_utc < day_cutoffs[i],
|
|
|
|
Submission.created_utc > day_cutoffs[i + 1],
|
|
|
|
Submission.is_banned == False
|
|
|
|
).count()
|
|
|
|
} for i in range(len(day_cutoffs) - 1)
|
|
|
|
]
|
|
|
|
|
|
|
|
comment_stats = [{"date": time.strftime("%d", time.gmtime(day_cutoffs[i + 1])),
|
|
|
|
"day_start": day_cutoffs[i + 1],
|
|
|
|
"comments": g.db.query(Comment).filter(Comment.created_utc < day_cutoffs[i],
|
|
|
|
Comment.created_utc > day_cutoffs[i + 1],
|
|
|
|
Comment.is_banned == False,
|
|
|
|
Comment.author_id != 1
|
|
|
|
).count()
|
|
|
|
} for i in range(len(day_cutoffs) - 1)
|
|
|
|
]
|
|
|
|
|
|
|
|
x = create_plot(sign_ups={'daily_signups': daily_signups},
|
|
|
|
posts={'post_stats': post_stats},
|
|
|
|
comments={'comment_stats': comment_stats},
|
|
|
|
)
|
|
|
|
|
2021-09-10 03:36:44 +00:00
|
|
|
return send_file("image.png")
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_plot(**kwargs):
|
|
|
|
|
|
|
|
if not kwargs:
|
|
|
|
return abort(400)
|
|
|
|
|
|
|
|
# create multiple charts
|
2021-09-10 03:35:00 +00:00
|
|
|
daily_signups = [d["signups"] for d in kwargs["sign_ups"]['daily_signups']][2:][::-1]
|
|
|
|
post_stats = [d["posts"] for d in kwargs["posts"]['post_stats']][2:][::-1]
|
|
|
|
comment_stats = [d["comments"] for d in kwargs["comments"]['comment_stats']][2:][::-1]
|
|
|
|
daily_times = [d["date"] for d in kwargs["sign_ups"]['daily_signups']][2:][::-1]
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
multi_plots = multiple_plots(sign_ups=daily_signups,
|
|
|
|
posts=post_stats,
|
|
|
|
comments=comment_stats,
|
|
|
|
daily_times=daily_times)
|
|
|
|
|
|
|
|
return multi_plots
|
|
|
|
|
|
|
|
|
|
|
|
def multiple_plots(**kwargs):
|
|
|
|
|
|
|
|
# create multiple charts
|
|
|
|
signup_chart = plt.subplot2grid((20, 4), (0, 0), rowspan=5, colspan=4)
|
2021-07-26 21:01:22 +00:00
|
|
|
posts_chart = plt.subplot2grid((20, 4), (7, 0), rowspan=5, colspan=4)
|
|
|
|
comments_chart = plt.subplot2grid((20, 4), (14, 0), rowspan=5, colspan=4)
|
2021-07-21 01:12:26 +00:00
|
|
|
|
2021-07-26 21:01:22 +00:00
|
|
|
signup_chart.grid(), posts_chart.grid(), comments_chart.grid()
|
2021-07-21 01:12:26 +00:00
|
|
|
|
|
|
|
signup_chart.plot(
|
2021-08-07 11:33:09 +00:00
|
|
|
kwargs['daily_times'],
|
|
|
|
kwargs['sign_ups'],
|
2021-07-21 01:12:26 +00:00
|
|
|
color='red')
|
|
|
|
posts_chart.plot(
|
2021-08-07 11:33:09 +00:00
|
|
|
kwargs['daily_times'],
|
|
|
|
kwargs['posts'],
|
2021-07-21 01:12:26 +00:00
|
|
|
color='green')
|
|
|
|
comments_chart.plot(
|
2021-08-07 11:33:09 +00:00
|
|
|
kwargs['daily_times'],
|
|
|
|
kwargs['comments'],
|
2021-07-21 01:12:26 +00:00
|
|
|
color='gold')
|
|
|
|
|
|
|
|
signup_chart.set_ylabel("Signups")
|
|
|
|
posts_chart.set_ylabel("Posts")
|
|
|
|
comments_chart.set_ylabel("Comments")
|
|
|
|
comments_chart.set_xlabel("Time (UTC)")
|
|
|
|
|
|
|
|
signup_chart.legend(loc='upper left', frameon=True)
|
|
|
|
posts_chart.legend(loc='upper left', frameon=True)
|
|
|
|
comments_chart.legend(loc='upper left', frameon=True)
|
|
|
|
|
2021-08-01 14:25:39 +00:00
|
|
|
plt.savefig("image.png")
|
2021-09-10 03:36:44 +00:00
|
|
|
plt.clf()
|