Merge branch 'frost' of https://github.com/Aevann1/rDrama into frost

remotes/1693176582716663532/tmp_refs/heads/watchparty
Aevann1 2022-10-11 18:41:12 +02:00
commit 466867afd1
32 changed files with 301 additions and 544 deletions

View File

@ -218,6 +218,7 @@ function post_toast(t, url, button1, button2, classname, extra_actions) {
} else { } else {
document.getElementById('toast-post-error-text').innerText = "Error, please try again later." document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"]; if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show(); bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
} }
if (!isShopConfirm) if (!isShopConfirm)

View File

@ -257,6 +257,73 @@ FEATURES = {
'PATRON_ICONS': False, 'PATRON_ICONS': False,
} }
WERKZEUG_ERROR_DESCRIPTIONS = {
400: "The browser (or proxy) sent a request that this server could not understand.",
401: "The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.",
403: "You don't have the permission to access the requested resource. It is either read-protected or not readable by the server.",
404: "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
405: "The method is not allowed for the requested URL.",
406: "The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.",
409: "A conflict happened while processing the request. The resource might have been modified while the request was being processed.",
413: "The data value transmitted exceeds the capacity limit.",
414: "The length of the requested URL exceeds the capacity limit for this server. The request cannot be processed.",
415: "The server does not support the media type transmitted in the request.",
417: "The server could not meet the requirements of the Expect header",
418: "This server is a teapot, not a coffee machine",
429: "This user has exceeded an allotted request count. Try again later.",
500: "The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.",
}
ERROR_TITLES = {
400: "Bad Request",
401: "Unauthorized",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Too Many Pings",
409: "Conflict",
413: "Max image/audio size is 8 MB (16 MB for paypigs)",
414: "Max video size is 32 MB (64 MB for paypigs)",
415: "Unsupported Media Type",
417: "Image already exists!",
418: "WEBM videos are not allowed",
429: "Too Many Requests",
500: "Internal Server Error",
}
ERROR_MSGS = {
400: "That request was bad and you should feel bad.",
401: "What you're trying to do requires an account. I think. The original error message said something about a castle and I hated that.",
403: "YOU AREN'T WELCOME HERE GO AWAY",
404: "Someone typed something wrong and it was probably you, please do better.",
405: "idk how anyone gets this error but if you see this, remember to follow @carpathianflorist<BR>the original error text here talked about internet gremlins and wtf",
406: "Max limit is 5 for comments and 50 for posts",
409: "There's a conflict between what you're trying to do and what you or someone else has done and because of that you can't do what you're trying to do. So maybe like... don't try and do that? Sorry not sorry",
413: "Max image/audio size is 8 MB (16 MB for paypigs)",
414: "Max video size is 32 MB (64 MB for paypigs)",
415: "Please upload only Image, Video, or Audio files!",
417: "Image already exists!",
418: "Please convert your video to MP4 and re-upload it!",
429: "go spam somewhere else nerd",
500: "Hiiiii it's carp! I think this error means that there's a timeout error. And I think that means something took too long to load so it decided not to work at all. If you keep seeing this on the same page <I>but not other pages</I>, then something is probably wrong with that specific function. It may not be called a function, but that sounds right to me. Anyway, ping me and I'll whine to someone smarter to fix it. Don't bother them. Thanks ily &lt;3",
}
ERROR_MARSEYS = {
400: "marseybrainlet",
401: "marseydead",
403: "marseytroll",
404: "marseyconfused",
405: "marseyretard",
406: "marseyrage",
409: "marseynoyou",
413: "marseyretard",
414: "marseychonker2",
415: "marseydetective",
418: "marseytea",
429: "marseyrentfree",
500: "marseycarp3",
}
EMOJI_MARSEYS = True EMOJI_MARSEYS = True
EMOJI_SRCS = ['files/assets/emojis.json'] EMOJI_SRCS = ['files/assets/emojis.json']
@ -389,6 +456,8 @@ elif SITE == 'pcmemes.net':
PIN_LIMIT = 10 PIN_LIMIT = 10
FEATURES['REPOST_DETECTION'] = False FEATURES['REPOST_DETECTION'] = False
FEATURES['GAMBLING'] = False FEATURES['GAMBLING'] = False
ERROR_MSGS[500] = "Hiiiii it's <b>nigger</b>! I think this error means that there's a <b>nigger</b> error. And I think that means something took too long to load so it decided to be a <b>nigger</b>. If you keep seeing this on the same page but not other pages, then something its probably a <b>niggerfaggot</b>. It may not be called a <b>nigger</b>, but that sounds right to me. Anyway, ping me and I'll whine to someone smarter to fix it. Don't bother them. Thanks ily &lt;3"
ERROR_MARSEYS[500] = "wholesome"
POST_RATE_LIMIT = '1/second;4/minute;20/hour;100/day' POST_RATE_LIMIT = '1/second;4/minute;20/hour;100/day'
HOLE_COST = 2000 HOLE_COST = 2000

View File

@ -196,7 +196,7 @@ def remove_admin(v, username):
@admin_level_required(PERMS['POST_BETS_DISTRIBUTE']) @admin_level_required(PERMS['POST_BETS_DISTRIBUTE'])
def distribute(v, option_id): def distribute(v, option_id):
autojanny = get_account(AUTOJANNY_ID) autojanny = get_account(AUTOJANNY_ID)
if autojanny.coins == 0: return {"error": "@AutoJanny has 0 coins"}, 400 if autojanny.coins == 0: abort(400, "@AutoJanny has 0 coins")
try: option_id = int(option_id) try: option_id = int(option_id)
except: abort(400) except: abort(400)
@ -303,7 +303,7 @@ def revert_actions(v, username):
def club_allow(v, username): def club_allow(v, username):
u = get_user(username, v=v) u = get_user(username, v=v)
if u.admin_level >= v.admin_level: return {"error": "noob"}, 400 if u.admin_level >= v.admin_level: abort(403, 'noob')
u.club_allowed = True u.club_allowed = True
g.db.add(u) g.db.add(u)
@ -329,7 +329,7 @@ def club_allow(v, username):
def club_ban(v, username): def club_ban(v, username):
u = get_user(username, v=v) u = get_user(username, v=v)
if u.admin_level >= v.admin_level: return {"error": "noob"}, 400 if u.admin_level >= v.admin_level: abort(403, 'noob')
u.club_allowed = False u.club_allowed = False
@ -490,7 +490,7 @@ def purge_cache(v):
g.db.add(ma) g.db.add(ma)
if response == "<Response [200]>": return {"message": "Cache purged!"} if response == "<Response [200]>": return {"message": "Cache purged!"}
return {"error": "Failed to purge cache."}, 400 abort(400, 'Failed to purge cache.')
@app.post("/admin/under_attack") @app.post("/admin/under_attack")
@ -507,7 +507,7 @@ def under_attack(v):
response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"high"}', timeout=5)) response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"high"}', timeout=5))
if response == "<Response [200]>": return {"message": "Under attack mode disabled!"} if response == "<Response [200]>": return {"message": "Under attack mode disabled!"}
return {"error": "Failed to disable under attack mode."}, 400 abort(400, "Failed to disable under attack mode.")
else: else:
ma = ModAction( ma = ModAction(
kind="enable_under_attack", kind="enable_under_attack",
@ -517,7 +517,7 @@ def under_attack(v):
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)) 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))
if response == "<Response [200]>": return {"message": "Under attack mode enabled!"} if response == "<Response [200]>": return {"message": "Under attack mode enabled!"}
return {"error": "Failed to enable under attack mode."}, 400 abort(400, "Failed to enable under attack mode.")
@app.get("/admin/badge_grant") @app.get("/admin/badge_grant")
@admin_level_required(PERMS['USER_BADGES']) @admin_level_required(PERMS['USER_BADGES'])
@ -1158,7 +1158,7 @@ def approve_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
if post.author.id == v.id and post.author.agendaposter and AGENDAPOSTER_PHRASE not in post.body.lower() and post.sub != 'chudrama': if post.author.id == v.id and post.author.agendaposter and AGENDAPOSTER_PHRASE not in post.body.lower() and post.sub != 'chudrama':
return {"error": "You can't bypass the chud award!"}, 400 abort(400, "You can't bypass the chud award!")
if post.is_banned: if post.is_banned:
ma=ModAction( ma=ModAction(
@ -1223,7 +1223,7 @@ def sticky_post(post_id, v):
if v.admin_level >= PERMS['BYPASS_PIN_LIMIT']: if v.admin_level >= PERMS['BYPASS_PIN_LIMIT']:
post.stickied = v.username post.stickied = v.username
post.stickied_utc = int(time.time()) + 3600 post.stickied_utc = int(time.time()) + 3600
else: return {"error": f"Can't exceed {PIN_LIMIT} pinned posts limit!"}, 403 else: abort(403, f"Can't exceed {PIN_LIMIT} pinned posts limit!")
else: post.stickied = v.username else: post.stickied = v.username
g.db.add(post) g.db.add(post)
@ -1246,7 +1246,7 @@ def unsticky_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
if post.stickied: if post.stickied:
if post.stickied.endswith('(pin award)'): return {"error": "Can't unpin award pins!"}, 403 if post.stickied.endswith('(pin award)'): abort(403, "Can't unpin award pins!")
post.stickied = None post.stickied = None
post.stickied_utc = None post.stickied_utc = None
@ -1296,7 +1296,7 @@ def unsticky_comment(cid, v):
comment = get_comment(cid, v=v) comment = get_comment(cid, v=v)
if comment.stickied: if comment.stickied:
if comment.stickied.endswith("(pin award)"): return {"error": "Can't unpin award pins!"}, 403 if comment.stickied.endswith("(pin award)"): abort(403, "Can't unpin award pins!")
comment.stickied = None comment.stickied = None
g.db.add(comment) g.db.add(comment)
@ -1344,7 +1344,7 @@ def approve_comment(c_id, v):
if not comment: abort(404) if not comment: abort(404)
if comment.author.id == v.id and comment.author.agendaposter and AGENDAPOSTER_PHRASE not in comment.body.lower() and comment.post.sub != 'chudrama': if comment.author.id == v.id and comment.author.agendaposter and AGENDAPOSTER_PHRASE not in comment.body.lower() and comment.post.sub != 'chudrama':
return {"error": "You can't bypass the chud award!"}, 400 abort(400, "You can't bypass the chud award!")
if comment.is_banned: if comment.is_banned:
ma=ModAction( ma=ModAction(

View File

@ -96,27 +96,27 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'):
@admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_MARSEYS']) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_MARSEYS'])
def approve_marsey(v, name): def approve_marsey(v, name):
if AEVANN_ID and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID): if AEVANN_ID and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID):
return {"error": "Only Carp can approve marseys!"}, 403 abort(403, "Only Carp can approve marseys!")
name = name.lower().strip() name = name.lower().strip()
marsey = g.db.query(Marsey).filter_by(name=name).one_or_none() marsey = g.db.query(Marsey).filter_by(name=name).one_or_none()
if not marsey: if not marsey:
return {"error": f"This marsey '{name}' doesn't exist!"}, 404 abort(404, f"This marsey '{name}' doesn't exist!")
tags = request.values.get('tags').lower().strip() tags = request.values.get('tags').lower().strip()
if not tags: if not tags:
return {"error": "You need to include tags!"}, 400 abort(400, "You need to include tags!")
new_name = request.values.get('name').lower().strip() new_name = request.values.get('name').lower().strip()
if not new_name: if not new_name:
return {"error": "You need to include name!"}, 400 abort(400, "You need to include name!")
if not marsey_regex.fullmatch(new_name): if not marsey_regex.fullmatch(new_name):
return {"error": "Invalid name!"}, 400 abort(400, "Invalid name!")
if not tags_regex.fullmatch(tags): if not tags_regex.fullmatch(tags):
return {"error": "Invalid tags!"}, 400 abort(400, "Invalid tags!")
marsey.name = new_name marsey.name = new_name
@ -168,10 +168,10 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'):
marsey = g.db.query(Marsey).filter_by(name=name).one_or_none() marsey = g.db.query(Marsey).filter_by(name=name).one_or_none()
if not marsey: if not marsey:
return {"error": f"This marsey '{name}' doesn't exist!"}, 404 abort(404, f"This marsey '{name}' doesn't exist!")
if v.id not in (marsey.submitter_id, AEVANN_ID, CARP_ID): if v.id not in (marsey.submitter_id, AEVANN_ID, CARP_ID):
return {"error": "Only Carp can remove marseys!"}, 403 abort(403, "Only Carp can remove marseys!")
if v.id != marsey.submitter_id: if v.id != marsey.submitter_id:
msg = f"@{v.username} has rejected a marsey you submitted: `'{marsey.name}'`" msg = f"@{v.username} has rejected a marsey you submitted: `'{marsey.name}'`"
@ -257,27 +257,20 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'):
@admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_HATS']) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_HATS'])
def approve_hat(v, name): def approve_hat(v, name):
if AEVANN_ID and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID): if AEVANN_ID and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID):
return {"error": "Only Carp can approve hats!"}, 403 abort(403, "Only Carp can approve hats!")
name = name.strip() name = name.strip()
hat = g.db.query(HatDef).filter_by(name=name).one_or_none() hat = g.db.query(HatDef).filter_by(name=name).one_or_none()
if not hat: if not hat: abort(404, f"This hat '{name}' doesn't exist!")
return {"error": f"This hat '{name}' doesn't exist!"}, 404
description = request.values.get('description').strip() description = request.values.get('description').strip()
if not description: if not description: abort(400, "You need to include a description!")
return {"error": "You need to include description!"}, 400
new_name = request.values.get('name').strip() new_name = request.values.get('name').strip()
if not new_name: if not new_name: abort(400, "You need to include a name!")
return {"error": "You need to include name!"}, 400 if not hat_regex.fullmatch(new_name): abort(400, "Invalid name!")
if not description_regex.fullmatch(description): abort(400, "Invalid description!")
if not hat_regex.fullmatch(new_name):
return {"error": "Invalid name!"}, 400
if not description_regex.fullmatch(description):
return {"error": "Invalid description!"}, 400
hat.price = int(request.values.get('price')) hat.price = int(request.values.get('price'))
hat.name = new_name hat.name = new_name
@ -332,11 +325,9 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'):
name = name.strip() name = name.strip()
hat = g.db.query(HatDef).filter_by(name=name).one_or_none() hat = g.db.query(HatDef).filter_by(name=name).one_or_none()
if not hat: if not hat: abort(404, f"This hat '{name}' doesn't exist!")
return {"error": f"This hat '{name}' doesn't exist!"}, 404
if v.id not in (hat.submitter_id, AEVANN_ID, CARP_ID): if v.id not in (hat.submitter_id, AEVANN_ID, CARP_ID):
return {"error": "Only Carp can remove hats!"}, 403 abort(403, 'Only Carp can remove hats!')
if v.id != hat.submitter_id: if v.id != hat.submitter_id:
msg = f"@{v.username} has rejected a hat you submitted: `'{hat.name}'`" msg = f"@{v.username} has rejected a hat you submitted: `'{hat.name}'`"

View File

@ -49,10 +49,10 @@ def buy(v, award):
if award == 'benefactor' and not request.values.get("mb"): if award == 'benefactor' and not request.values.get("mb"):
return {"error": "You can only buy the Benefactor award with marseybux."}, 403 abort(403, "You can only buy the Benefactor award with marseybux.")
if award == 'ghost' and v.admin_level < PERMS['BUY_GHOST_AWARD']: if award == 'ghost' and v.admin_level < PERMS['BUY_GHOST_AWARD']:
return {"error": "Only admins can buy this award."}, 403 abort(403, "Only admins can buy this award")
AWARDS = deepcopy(AWARDS2) AWARDS = deepcopy(AWARDS2)
@ -67,15 +67,15 @@ def buy(v, award):
if request.values.get("mb"): if request.values.get("mb"):
if award == "grass": if award == "grass":
return {"error": "You can't buy the grass award with marseybux."}, 403 abort(403, "You can't buy the grass award with marseybux.")
charged = v.charge_account('procoins', price) charged = v.charge_account('procoins', price)
if not charged: if not charged:
return {"error": "Not enough marseybux."}, 400 abort(400, "Not enough marseybux.")
else: else:
charged = v.charge_account('coins', price) charged = v.charge_account('coins', price)
if not charged: if not charged:
return {"error": "Not enough coins."}, 400 abort(400, "Not enough coins.")
v.coins_spent += price v.coins_spent += price
if v.coins_spent >= 1000000: if v.coins_spent >= 1000000:
@ -129,8 +129,6 @@ def buy(v, award):
@is_not_permabanned @is_not_permabanned
@feature_required('BADGES') @feature_required('BADGES')
def award_thing(v, thing_type, id): def award_thing(v, thing_type, id):
if thing_type == 'post': thing = get_post(id) if thing_type == 'post': thing = get_post(id)
else: thing = get_comment(id) else: thing = get_comment(id)
@ -142,8 +140,7 @@ def award_thing(v, thing_type, id):
if v.house: if v.house:
AWARDS[v.house] = HOUSE_AWARDS[v.house] AWARDS[v.house] = HOUSE_AWARDS[v.house]
if kind not in AWARDS: if kind not in AWARDS: abort(404, "This award doesn't exist")
return {"error": "This award doesn't exist."}, 404
award = g.db.query(AwardRelationship).filter( award = g.db.query(AwardRelationship).filter(
AwardRelationship.kind == kind, AwardRelationship.kind == kind,
@ -152,8 +149,7 @@ def award_thing(v, thing_type, id):
AwardRelationship.comment_id == None AwardRelationship.comment_id == None
).first() ).first()
if not award: if not award: abort(404, "You don't have that award")
return {"error": "You don't have that award."}, 404
if thing_type == 'post': award.submission_id = thing.id if thing_type == 'post': award.submission_id = thing.id
else: award.comment_id = thing.id else: award.comment_id = thing.id
@ -167,13 +163,13 @@ def award_thing(v, thing_type, id):
if author.shadowbanned: abort(404) if author.shadowbanned: abort(404)
if SITE == 'rdrama.net' and author.id in (PIZZASHILL_ID, CARP_ID): if SITE == 'rdrama.net' and author.id in (PIZZASHILL_ID, CARP_ID):
return {"error": "This user is immune to awards."}, 403 abort(403, "This user is immune to awards.")
if kind == "benefactor" and author.id == v.id: if kind == "benefactor" and author.id == v.id:
return {"error": "You can't use this award on yourself."}, 400 abort(400, "You can't use this award on yourself.")
if kind == 'marsify' and author.marsify == 1: if kind == 'marsify' and author.marsify == 1:
return {"error": "User is already permanently marsified!"}, 403 abort(403, "User is already permanently marsified!")
if v.id != author.id: if v.id != author.id:
safe_username = "👻" if thing.ghost else f"@{author.username}" safe_username = "👻" if thing.ghost else f"@{author.username}"
@ -254,7 +250,7 @@ def award_thing(v, thing_type, id):
g.db.add(thing) g.db.add(thing)
elif kind == "agendaposter" and not (author.agendaposter and author.agendaposter == 0): elif kind == "agendaposter" and not (author.agendaposter and author.agendaposter == 0):
if author.marseyawarded: if author.marseyawarded:
return {"error": "This user is the under the effect of a conflicting award: Marsey award."}, 404 abort(400, "This user is under the effect of a conflicting award: Marsey award.")
if author.agendaposter and time.time() < author.agendaposter: author.agendaposter += 86400 if author.agendaposter and time.time() < author.agendaposter: author.agendaposter += 86400
else: author.agendaposter = int(time.time()) + 86400 else: author.agendaposter = int(time.time()) + 86400
@ -284,13 +280,13 @@ def award_thing(v, thing_type, id):
badge_grant(user=author, badge_id=98) badge_grant(user=author, badge_id=98)
elif kind == "pizzashill": elif kind == "pizzashill":
if author.bird: if author.bird:
return {"error": "This user is the under the effect of a conflicting award: Bird Site award."}, 404 abort(400, "This user is under the effect of a conflicting award: Bird Site award.")
if author.longpost: author.longpost += 86400 if author.longpost: author.longpost += 86400
else: author.longpost = int(time.time()) + 86400 else: author.longpost = int(time.time()) + 86400
badge_grant(user=author, badge_id=97) badge_grant(user=author, badge_id=97)
elif kind == "bird": elif kind == "bird":
if author.longpost: if author.longpost:
return {"error": "This user is the under the effect of a conflicting award: Pizzashill award."}, 404 abort(400, "This user is under the effect of a conflicting award: Pizzashill award.")
if author.bird: author.bird += 86400 if author.bird: author.bird += 86400
else: author.bird = int(time.time()) + 86400 else: author.bird = int(time.time()) + 86400
badge_grant(user=author, badge_id=95) badge_grant(user=author, badge_id=95)
@ -317,7 +313,7 @@ def award_thing(v, thing_type, id):
else: author.progressivestack = int(time.time()) + 21600 else: author.progressivestack = int(time.time()) + 21600
badge_grant(user=author, badge_id=94) badge_grant(user=author, badge_id=94)
elif kind == "benefactor": elif kind == "benefactor":
if author.patron: return {"error": "This user is already a paypig!"}, 400 if author.patron: abort(400, "This user is already a paypig!")
author.patron = 1 author.patron = 1
if author.patron_utc: author.patron_utc += 2629746 if author.patron_utc: author.patron_utc += 2629746
else: author.patron_utc = int(time.time()) + 2629746 else: author.patron_utc = int(time.time()) + 2629746

View File

@ -55,8 +55,8 @@ def casino_game_page(v, game):
@auth_required @auth_required
@feature_required('GAMBLING') @feature_required('GAMBLING')
def casino_game_feed(v, game): def casino_game_feed(v, game):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
elif game not in CASINO_GAME_KINDS: elif game not in CASINO_GAME_KINDS:
abort(404) abort(404)
@ -83,27 +83,27 @@ def lottershe(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def pull_slots(v): def pull_slots(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
wager = int(request.values.get("wager")) wager = int(request.values.get("wager"))
except: except:
return {"error": "Invalid wager."}, 400 abort(400, "Invalid wager.")
try: try:
currency = request.values.get("currency") currency = request.values.get("currency")
except: except:
return {"error": "Invalid currency (expected 'coin' or 'marseybux')."}, 400 abort(400, "Invalid currency (expected 'coin' or 'marseybux').")
if (currency == "coin" and wager > v.coins) or (currency == "marseybux" and wager > v.procoins): if (currency == "coin" and wager > v.coins) or (currency == "marseybux" and wager > v.procoins):
return {"error": f"Not enough {currency} to make that bet."}, 400 abort(400, f"Not enough {currency} to make that bet")
success, game_state = casino_slot_pull(v, wager, currency) success, game_state = casino_slot_pull(v, wager, currency)
if success: if success:
return {"game_state": game_state, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"game_state": game_state, "gambler": {"coins": v.coins, "procoins": v.procoins}}
else: else:
return {"error": f"Wager must be more than 5 {currency}."}, 400 abort(400, f"Wager must be more than 5 {currency}")
# 21 # 21
@ -113,7 +113,7 @@ def pull_slots(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def blackjack_deal_to_player(v): def blackjack_deal_to_player(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
wager = int(request.values.get("wager")) wager = int(request.values.get("wager"))
@ -124,7 +124,7 @@ def blackjack_deal_to_player(v):
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except Exception as e: except Exception as e:
return {"error": str(e)}, 400 abort(400, str(e))
@app.post("/casino/twentyone/hit") @app.post("/casino/twentyone/hit")
@ -133,14 +133,14 @@ def blackjack_deal_to_player(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def blackjack_player_hit(v): def blackjack_player_hit(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
state = dispatch_action(v, BlackjackAction.HIT) state = dispatch_action(v, BlackjackAction.HIT)
feed = get_game_feed('blackjack') feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except: except:
return {"error": "Unable to hit."}, 400 abort(400, "Unable to hit.")
@app.post("/casino/twentyone/stay") @app.post("/casino/twentyone/stay")
@ -149,14 +149,14 @@ def blackjack_player_hit(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def blackjack_player_stay(v): def blackjack_player_stay(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
state = dispatch_action(v, BlackjackAction.STAY) state = dispatch_action(v, BlackjackAction.STAY)
feed = get_game_feed('blackjack') feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except: except:
return {"error": "Unable to stay."}, 400 abort(400, "Unable to stay.")
@app.post("/casino/twentyone/double-down") @app.post("/casino/twentyone/double-down")
@ -165,14 +165,14 @@ def blackjack_player_stay(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def blackjack_player_doubled_down(v): def blackjack_player_doubled_down(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN) state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
feed = get_game_feed('blackjack') feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except: except:
return {"error": "Unable to double down."}, 400 abort(400, "Unable to double down.")
@app.post("/casino/twentyone/buy-insurance") @app.post("/casino/twentyone/buy-insurance")
@ -181,14 +181,14 @@ def blackjack_player_doubled_down(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def blackjack_player_bought_insurance(v): def blackjack_player_bought_insurance(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE) state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
feed = get_game_feed('blackjack') feed = get_game_feed('blackjack')
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except: except:
return {"error": "Unable to buy insurance."}, 400 abort(403, "Unable to buy insurance.")
# Roulette # Roulette
@app.get("/casino/roulette/bets") @app.get("/casino/roulette/bets")
@ -197,7 +197,7 @@ def blackjack_player_bought_insurance(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def roulette_get_bets(v): def roulette_get_bets(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
bets = get_roulette_bets() bets = get_roulette_bets()
@ -210,7 +210,7 @@ def roulette_get_bets(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def roulette_player_placed_bet(v): def roulette_player_placed_bet(v):
if v.rehab: if v.rehab:
return {"error": "You are under Rehab award effect!"}, 400 abort(403, "You are under Rehab award effect!")
try: try:
bet = request.values.get("bet") bet = request.values.get("bet")
@ -227,4 +227,4 @@ def roulette_player_placed_bet(v):
return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}} return {"success": True, "bets": bets, "gambler": {"coins": v.coins, "procoins": v.procoins}}
except: except:
return {"error": "Unable to place a bet."}, 400 abort(400, "Unable to place a bet.")

View File

@ -56,7 +56,7 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
post = get_post(pid, v=v) post = get_post(pid, v=v)
if post.over_18 and not (v and v.over_18) and not session.get('over_18', 0) >= int(time.time()): if post.over_18 and not (v and v.over_18) and not session.get('over_18', 0) >= int(time.time()):
if request.headers.get("Authorization"): return {"error": 'This content is not suitable for some users and situations.'}, 403 if request.headers.get("Authorization"): abort(403, "This content is not suitable for some users and situations.")
else: return render_template("errors/nsfw.html", v=v) else: return render_template("errors/nsfw.html", v=v)
try: context = min(int(request.values.get("context", 0)), 8) try: context = min(int(request.values.get("context", 0)), 8)
@ -126,17 +126,17 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
@limiter.limit("1/second;20/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;20/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required @auth_required
def comment(v): def comment(v):
if v.is_suspended: return {"error": "You can't perform this action while banned."}, 403 if v.is_suspended: abort(403, "You can't perform this action while banned.")
parent_submission = request.values.get("submission").strip() parent_submission = request.values.get("submission").strip()
parent_fullname = request.values.get("parent_fullname").strip() parent_fullname = request.values.get("parent_fullname").strip()
parent_post = get_post(parent_submission, v=v) parent_post = get_post(parent_submission, v=v)
sub = parent_post.sub sub = parent_post.sub
if sub and v.exiled_from(sub): return {"error": f"You're exiled from /h/{sub}"}, 403 if sub and v.exiled_from(sub): abort(403, f"You're exiled from /h/{sub}")
if sub in ('furry','vampire','racist','femboy') and not v.client and not v.house.lower().startswith(sub): if sub in ('furry','vampire','racist','femboy') and not v.client and not v.house.lower().startswith(sub):
return {"error": f"You need to be a member of House {sub.capitalize()} to comment in /h/{sub}"}, 400 abort(403, f"You need to be a member of House {sub.capitalize()} to comment in /h/{sub}")
if parent_post.club and not (v and (v.paid_dues or v.id == parent_post.author_id)): abort(403) if parent_post.club and not (v and (v.paid_dues or v.id == parent_post.author_id)): abort(403)
@ -157,18 +157,17 @@ def comment(v):
if not parent.can_see(v): abort(404) if not parent.can_see(v): abort(404)
if parent.deleted_utc != 0: abort(404) if parent.deleted_utc != 0: abort(404)
if level > COMMENT_MAX_DEPTH: if level > COMMENT_MAX_DEPTH: abort(400, f"Max comment level is {COMMENT_MAX_DEPTH}")
return {"error": f"Max comment level is {COMMENT_MAX_DEPTH}"}, 400
body = sanitize_raw_body(request.values.get("body", ""), False) body = sanitize_raw_body(request.values.get("body", ""), False)
if parent_post.id not in ADMIGGERS: if parent_post.id not in ADMIGGERS:
if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')): if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')):
return {"error":"You have to type more than 280 characters!"}, 403 abort(403, "You have to type more than 280 characters!")
elif v.bird and len(body) > 140: elif v.bird and len(body) > 140:
return {"error":"You have to type less than 140 characters!"}, 403 abort(403, "You have to type less than 140 characters!")
if not body and not request.files.get('file'): return {"error":"You need to actually write something!"}, 400 if not body and not request.files.get('file'): abort(400, "You need to actually write something!")
options = [] options = []
for i in poll_regex.finditer(body): for i in poll_regex.finditer(body):
@ -187,7 +186,7 @@ def comment(v):
oldname = f'/images/{time.time()}'.replace('.','') + '.webp' oldname = f'/images/{time.time()}'.replace('.','') + '.webp'
file.save(oldname) file.save(oldname)
image = process_image(oldname, patron=v.patron) image = process_image(oldname, patron=v.patron)
if image == "": return {"error":"Image upload failed"}, 400 if image == "": abort(400, "Image upload failed")
if v.admin_level >= PERMS['SITE_SETTINGS_SIDEBARS_BANNERS_BADGES'] and level == 1: if v.admin_level >= PERMS['SITE_SETTINGS_SIDEBARS_BANNERS_BADGES'] and level == 1:
if parent_post.id == SIDEBAR_THREAD: if parent_post.id == SIDEBAR_THREAD:
li = sorted(os.listdir(f'files/assets/images/{SITE_NAME}/sidebar'), li = sorted(os.listdir(f'files/assets/images/{SITE_NAME}/sidebar'),
@ -210,7 +209,7 @@ def comment(v):
name = badge_def["name"] name = badge_def["name"]
existing = g.db.query(BadgeDef).filter_by(name=name).one_or_none() existing = g.db.query(BadgeDef).filter_by(name=name).one_or_none()
if existing: return {"error": "A badge with this name already exists!"}, 403 if existing: abort(403, "A badge with this name already exists!")
badge = BadgeDef(name=name, description=badge_def["description"]) badge = BadgeDef(name=name, description=badge_def["description"])
g.db.add(badge) g.db.add(badge)
@ -221,7 +220,7 @@ def comment(v):
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS,
data=f'{{"files": ["https://{SITE}/assets/images/badges/{badge.id}.webp"]}}', timeout=5) data=f'{{"files": ["https://{SITE}/assets/images/badges/{badge.id}.webp"]}}', timeout=5)
except Exception as e: except Exception as e:
return {"error": str(e)}, 400 abort(400, str(e))
body += f"\n\n![]({image})" body += f"\n\n![]({image})"
elif file.content_type.startswith('video/'): elif file.content_type.startswith('video/'):
body += f"\n\n{process_video(file)}" body += f"\n\n{process_video(file)}"
@ -257,7 +256,7 @@ def comment(v):
if existing: return {"error": f"You already made that comment: /comment/{existing.id}"}, 409 if existing: return {"error": f"You already made that comment: /comment/{existing.id}"}, 409
if parent.author.any_block_exists(v) and v.admin_level < PERMS['POST_COMMENT_MODERATION']: if parent.author.any_block_exists(v) and v.admin_level < PERMS['POST_COMMENT_MODERATION']:
return {"error": "You can't reply to users who have blocked you or users that you have blocked."}, 403 abort(403, "You can't reply to users who have blocked you or users that you have blocked.")
is_bot = v.id != BBBB_ID and (bool(request.headers.get("Authorization")) or (SITE == 'pcmemes.net' and v.id == SNAPPY_ID)) is_bot = v.id != BBBB_ID and (bool(request.headers.get("Authorization")) or (SITE == 'pcmemes.net' and v.id == SNAPPY_ID))
@ -297,7 +296,7 @@ def comment(v):
g.db.add(ma) g.db.add(ma)
g.db.commit() g.db.commit()
return {"error": "Too much spam!"}, 403 abort(403, "Too much spam!")
if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT: abort(400) if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT: abort(400)
@ -442,7 +441,7 @@ def comment(v):
g.db.add(c) g.db.add(c)
if v.marseyawarded and parent_post.id not in ADMIGGERS and marseyaward_body_regex.search(body_html): if v.marseyawarded and parent_post.id not in ADMIGGERS and marseyaward_body_regex.search(body_html):
return {"error":"You can only type marseys!"}, 403 abort(403, "You can only type marseys!")
check_for_treasure(body, c) check_for_treasure(body, c)
@ -469,7 +468,7 @@ def edit_comment(cid, v):
c = get_comment(cid, v=v) c = get_comment(cid, v=v)
if time.time() - c.created_utc > 7*24*60*60 and not (c.post and c.post.private): if time.time() - c.created_utc > 7*24*60*60 and not (c.post and c.post.private):
return {"error":"You can't edit comments older than 1 week!"}, 403 abort(403, "You can't edit comments older than 1 week!")
if c.author_id != v.id: abort(403) if c.author_id != v.id: abort(403)
if not c.post: abort(403) if not c.post: abort(403)
@ -477,13 +476,13 @@ def edit_comment(cid, v):
body = sanitize_raw_body(request.values.get("body", ""), False) body = sanitize_raw_body(request.values.get("body", ""), False)
if len(body) < 1 and not (request.files.get("file") and request.headers.get("cf-ipcountry") != "T1"): if len(body) < 1 and not (request.files.get("file") and request.headers.get("cf-ipcountry") != "T1"):
return {"error":"You have to actually type something!"}, 400 abort(400, "You have to actually type something!")
if body != c.body or request.files.get("file") and request.headers.get("cf-ipcountry") != "T1": if body != c.body or request.files.get("file") and request.headers.get("cf-ipcountry") != "T1":
if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')): if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')):
return {"error":"You have to type more than 280 characters!"}, 403 abort(403, "You have to type more than 280 characters!")
elif v.bird and len(body) > 140: elif v.bird and len(body) > 140:
return {"error":"You have to type less than 140 characters!"}, 403 abort(403, "You have to type less than 140 characters!")
for i in poll_regex.finditer(body): for i in poll_regex.finditer(body):
body = body.replace(i.group(0), "") body = body.replace(i.group(0), "")
@ -535,7 +534,7 @@ def edit_comment(cid, v):
g.db.add(comment) g.db.add(comment)
g.db.commit() g.db.commit()
return {"error": "Too much spam!"}, 403 abort(403, "Too much spam!")
body += process_files() body += process_files()
body = body.strip()[:COMMENT_BODY_LENGTH_LIMIT] # process_files potentially adds characters to the post body = body.strip()[:COMMENT_BODY_LENGTH_LIMIT] # process_files potentially adds characters to the post
@ -553,7 +552,7 @@ def edit_comment(cid, v):
if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT: abort(400) if len(body_html) > COMMENT_BODY_HTML_LENGTH_LIMIT: abort(400)
if v.marseyawarded and marseyaward_body_regex.search(body_html): if v.marseyawarded and marseyaward_body_regex.search(body_html):
return {"error":"You can only type marseys!"}, 403 abort(403, "You can only type marseys!")
c.body = body c.body = body
c.body_html = body_html c.body_html = body_html
@ -568,7 +567,7 @@ def edit_comment(cid, v):
g.db.add(notif) g.db.add(notif)
if v.agendaposter and not v.marseyawarded and AGENDAPOSTER_PHRASE not in c.body.lower() and c.post.sub != 'chudrama': if v.agendaposter and not v.marseyawarded and AGENDAPOSTER_PHRASE not in c.body.lower() and c.post.sub != 'chudrama':
return {"error": f'You have to include "{AGENDAPOSTER_PHRASE}" in your comment!'}, 403 abort(403, f'You have to include "{AGENDAPOSTER_PHRASE}" in your comment!')
if int(time.time()) - c.created_utc > 60 * 3: c.edited_utc = int(time.time()) if int(time.time()) - c.created_utc > 60 * 3: c.edited_utc = int(time.time())
@ -745,7 +744,6 @@ def diff_words(answer, guess):
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required @auth_required
def handle_wordle_action(cid, v): def handle_wordle_action(cid, v):
comment = get_comment(cid) comment = get_comment(cid)
if v.id != comment.author_id: if v.id != comment.author_id:
@ -757,8 +755,7 @@ def handle_wordle_action(cid, v):
try: guess = request.values.get("thing").strip().lower() try: guess = request.values.get("thing").strip().lower()
except: abort(400) except: abort(400)
if len(guess) != 5: if len(guess) != 5: abort(400, "Not a valid guess!")
return {"error": "Not a valid guess!"}, 400
if status == "active": if status == "active":
guesses += "".join(cg + WORDLE_COLOR_MAPPINGS[diff] for cg, diff in zip(guess, diff_words(answer, guess))) guesses += "".join(cg + WORDLE_COLOR_MAPPINGS[diff] for cg, diff in zip(guess, diff_words(answer, guess)))

View File

@ -8,15 +8,10 @@ import requests
@app.get("/discord") @app.get("/discord")
@is_not_permabanned @is_not_permabanned
def join_discord(v): def join_discord(v):
if v.shadowbanned: return {"error": "Internal Server Error"}, 500
if v.shadowbanned: return {"error": "Internal server error"}, 400
now=int(time.time()) now=int(time.time())
state=generate_hash(f"{now}+{v.id}+discord") state=generate_hash(f"{now}+{v.id}+discord")
state=f"{now}.{state}" state=f"{now}.{state}"
return redirect(f"https://discord.com/api/oauth2/authorize?client_id={DISCORD_CLIENT_ID}&redirect_uri=https%3A%2F%2F{SITE}%2Fdiscord_redirect&response_type=code&scope=identify%20guilds.join&state={state}") return redirect(f"https://discord.com/api/oauth2/authorize?client_id={DISCORD_CLIENT_ID}&redirect_uri=https%3A%2F%2F{SITE}%2Fdiscord_redirect&response_type=code&scope=identify%20guilds.join&state={state}")

View File

@ -4,17 +4,39 @@ from urllib.parse import quote, urlencode
import time import time
from files.__main__ import app, limiter from files.__main__ import app, limiter
# If you're adding an error, go here:
# https://github.com/pallets/werkzeug/blob/main/src/werkzeug/exceptions.py
# and copy the description for the error code you're adding and add it to
# the constant WERKZEUG_ERROR_DESCRIPTIONS so that the default error message
# doesn't show up on the message. Be exact or it won't work properly.
@app.errorhandler(400) @app.errorhandler(400)
def error_400(e): @app.errorhandler(403)
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "400 Bad Request"}, 400 @app.errorhandler(404)
else: return render_template('errors/400.html', err=True), 400 @app.errorhandler(405)
@app.errorhandler(406)
@app.errorhandler(409)
@app.errorhandler(413)
@app.errorhandler(414)
@app.errorhandler(415)
@app.errorhandler(417)
@app.errorhandler(418)
@app.errorhandler(429)
def error(e):
title = ERROR_TITLES.get(e.code, str(e.code))
msg = ERROR_MSGS.get(e.code, str(e.code))
details = e.description
if WERKZEUG_ERROR_DESCRIPTIONS.get(e.code, None) == details:
details = None
if request.headers.get("Authorization") or request.headers.get("xhr"):
return {"error": title, "code": e.code, "description": msg, "details": details}
img = ERROR_MARSEYS.get(e.code, 'marseyl')
return render_template('errors/error.html', err=True, title=title, msg=msg, details=details, img=img), e.code
@app.errorhandler(401) @app.errorhandler(401)
def error_401(e): def error_401(e):
if request.headers.get("Authorization") or request.headers.get("xhr"): return error(e)
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "401 Not Authorized"}, 401
else: else:
path = request.path path = request.path
qs = urlencode(dict(request.values)) qs = urlencode(dict(request.values))
@ -23,75 +45,10 @@ def error_401(e):
if session.get("history"): return redirect(f"/login?redirect={argval}") if session.get("history"): return redirect(f"/login?redirect={argval}")
else: return redirect(f"/signup?redirect={argval}") else: return redirect(f"/signup?redirect={argval}")
@app.errorhandler(406)
def error_406(e):
if request.headers.get("Authorization") or request.headers.get("xhr"):
return {"error": "Too many pings: max limit is 5 for comments and 50 for posts"}, 406
else: return render_template('errors/406.html', err=True), 406
@app.errorhandler(403)
def error_403(e):
description = e.description
if description == "You don't have the permission to access the requested resource. It is either read-protected or not readable by the server.": description = ''
if request.headers.get("Authorization") or request.headers.get("xhr"):
if not description: description = "403 Forbidden"
return {"error": description}, 403
else:
if not description: description = "YOU AREN'T WELCOME HERE GO AWAY"
return render_template('errors/403.html', description=description, err=True), 403
@app.errorhandler(404)
def error_404(e):
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "404 Not Found"}, 404
else: return render_template('errors/404.html', err=True), 404
@app.errorhandler(405)
def error_405(e):
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "405 Method Not Allowed"}, 405
else: return render_template('errors/405.html', err=True), 405
@app.errorhandler(413)
def error_413(e):
if request.headers.get("Authorization") or request.headers.get("xhr"):
return {"error": "Max image/audio size is 8 MB (16 MB for paypigs)"}, 413
else: return render_template('errors/413.html', err=True), 413
@app.errorhandler(414)
def error_414(e):
if request.headers.get("Authorization") or request.headers.get("xhr"):
return {"error": "Max video size is 32 MB (64 MB for paypigs)"}, 414
else: return render_template('errors/414.html', err=True), 414
@app.errorhandler(415)
def error_415(e):
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "Please upload only Image, Video, or Audio files!"}, 415
else: return render_template('errors/415.html', err=True), 415
@app.errorhandler(417)
def error_417(e):
return {"error": "Image already exists!"}, 417
@app.errorhandler(418)
def error_418(e):
if request.headers.get("Authorization") or request.headers.get("xhr"):
return {"error": "WEBM videos are not allowed, please convert your video to MP4 and re-upload it!"}, 418
else: return render_template('errors/418.html', err=True), 418
@app.errorhandler(429)
def error_429(e):
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "429 Too Many Requests"}, 429
else: return render_template('errors/429.html', err=True), 429
@app.errorhandler(500) @app.errorhandler(500)
def error_500(e): def error_500(e):
g.db.rollback() g.db.rollback()
return error(e)
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "500 Internal Server Error"}, 500
else: return render_template('errors/500.html', err=True), 500
@app.post("/allow_nsfw") @app.post("/allow_nsfw")

View File

@ -36,25 +36,23 @@ def hats(v):
@feature_required('HATS') @feature_required('HATS')
def buy_hat(v, hat_id): def buy_hat(v, hat_id):
try: hat_id = int(hat_id) try: hat_id = int(hat_id)
except: return {"error": "Hat not found!"}, 400 except: abort(404, "Hat not found!")
hat = g.db.query(HatDef).filter_by(submitter_id=None, id=hat_id).one_or_none() hat = g.db.query(HatDef).filter_by(submitter_id=None, id=hat_id).one_or_none()
if not hat: return {"error": "Hat not found!"}, 400 if not hat: abort(404, "Hat not found!")
existing = g.db.query(Hat).filter_by(user_id=v.id, hat_id=hat.id).one_or_none() existing = g.db.query(Hat).filter_by(user_id=v.id, hat_id=hat.id).one_or_none()
if existing: return {"error": "You already own this hat!"}, 400 if existing: abort(400, "You already own this hat!")
if request.values.get("mb"): if request.values.get("mb"):
charged = v.charge_account('procoins', hat.price) charged = v.charge_account('procoins', hat.price)
if not charged: if not charged: abort(400, "Not enough marseybux.")
return {"error": "Not enough marseybux."}, 400
hat.author.procoins += hat.price * 0.1 hat.author.procoins += hat.price * 0.1
currency = "marseybux" currency = "marseybux"
else: else:
charged = v.charge_account('coins', hat.price) charged = v.charge_account('coins', hat.price)
if not charged: if not charged: abort(400, "Not enough coins.")
return {"error": "Not enough coins."}, 400
v.coins_spent_on_hats += hat.price v.coins_spent_on_hats += hat.price
hat.author.coins += hat.price * 0.1 hat.author.coins += hat.price * 0.1
@ -86,10 +84,10 @@ def buy_hat(v, hat_id):
@feature_required('HATS') @feature_required('HATS')
def equip_hat(v, hat_id): def equip_hat(v, hat_id):
try: hat_id = int(hat_id) try: hat_id = int(hat_id)
except: return {"error": "Hat not found!"}, 400 except: abort(404, "Hat not found!")
hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none() hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
if not hat: return {"error": "You don't own this hat!"}, 400 if not hat: abort(403, "You don't own this hat!")
hat.equipped = True hat.equipped = True
g.db.add(hat) g.db.add(hat)
@ -101,10 +99,10 @@ def equip_hat(v, hat_id):
@feature_required('HATS') @feature_required('HATS')
def unequip_hat(v, hat_id): def unequip_hat(v, hat_id):
try: hat_id = int(hat_id) try: hat_id = int(hat_id)
except: return {"error": "Hat not found!"}, 400 except: abort(404, "Hat not found!")
hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none() hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
if not hat: return {"error": "You don't own this hat!"}, 400 if not hat: abort(403, "You don't own this hat!")
hat.equipped = False hat.equipped = False
g.db.add(hat) g.db.add(hat)

View File

@ -29,7 +29,7 @@ def lottery_start(v):
@feature_required('GAMBLING') @feature_required('GAMBLING')
def lottery_buy(v): def lottery_buy(v):
try: quantity = int(request.values.get("quantity")) try: quantity = int(request.values.get("quantity"))
except: return {"error": "Invalid ticket quantity."}, 400 except: abort(400, "Invalid ticket quantity.")
success, message = purchase_lottery_tickets(v, quantity) success, message = purchase_lottery_tickets(v, quantity)
lottery, participants = get_active_lottery_stats() lottery, participants = get_active_lottery_stats()

View File

@ -19,10 +19,10 @@ def vote_option(option_id, v):
sub = option.post.sub sub = option.post.sub
if sub in ('furry','vampire','racist','femboy') and not v.house.lower().startswith(sub): if sub in ('furry','vampire','racist','femboy') and not v.house.lower().startswith(sub):
return {"error": f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}"}, 400 abort(403, f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}")
if option.exclusive == 2: if option.exclusive == 2:
if v.coins < POLL_BET_COINS: return {"error": f"You don't have {POLL_BET_COINS} coins!"}, 400 if v.coins < POLL_BET_COINS: abort(400, f"You don't have {POLL_BET_COINS} coins!")
v.coins -= POLL_BET_COINS v.coins -= POLL_BET_COINS
g.db.add(v) g.db.add(v)
autojanny = get_account(AUTOJANNY_ID) autojanny = get_account(AUTOJANNY_ID)
@ -35,7 +35,7 @@ def vote_option(option_id, v):
SubmissionOptionVote.submission_id==option.submission_id, SubmissionOptionVote.submission_id==option.submission_id,
SubmissionOption.exclusive==option.exclusive).one_or_none() SubmissionOption.exclusive==option.exclusive).one_or_none()
if vote: if vote:
if option.exclusive == 2: return {"error": "You already voted on this bet!"}, 400 if option.exclusive == 2: abort(400, "You already voted on this bet!")
g.db.delete(vote) g.db.delete(vote)
existing = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none() existing = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
@ -85,7 +85,7 @@ def vote_option_comment(option_id, v):
sub = option.comment.post.sub sub = option.comment.post.sub
if sub in ('furry','vampire','racist','femboy') and not v.house.lower().startswith(sub): if sub in ('furry','vampire','racist','femboy') and not v.house.lower().startswith(sub):
return {"error": f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}"}, 400 abort(403, f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}")
if option.exclusive: if option.exclusive:
vote = g.db.query(CommentOptionVote).join(CommentOption).filter( vote = g.db.query(CommentOptionVote).join(CommentOption).filter(

View File

@ -414,26 +414,26 @@ def edit_post(pid, v):
# Disable edits on things older than 1wk unless it's a draft or editor is a jannie # Disable edits on things older than 1wk unless it's a draft or editor is a jannie
if (time.time() - p.created_utc > 7*24*60*60 and not p.private if (time.time() - p.created_utc > 7*24*60*60 and not p.private
and not v.admin_level >= PERMS['POST_EDITING']): and not v.admin_level >= PERMS['POST_EDITING']):
return {"error": "You can't edit posts older than 1 week!"}, 403 abort(403, "You can't edit posts older than 1 week!")
title = sanitize_raw_title(request.values.get("title", "")) title = sanitize_raw_title(request.values.get("title", ""))
body = sanitize_raw_body(request.values.get("body", ""), True) body = sanitize_raw_body(request.values.get("body", ""), True)
if v.id == p.author_id: if v.id == p.author_id:
if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')): if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')):
return {"error":"You have to type more than 280 characters!"}, 403 abort(403, "You have to type more than 280 characters!")
elif v.bird and len(body) > 140: elif v.bird and len(body) > 140:
return {"error":"You have to type less than 140 characters!"}, 403 abort(403, "You have to type less than 140 characters!")
if not title: if not title:
return {"error": "Please enter a better title."}, 400 abort(400, "Please enter a better title.")
if title != p.title: if title != p.title:
torture = (v.agendaposter and not v.marseyawarded and p.sub != 'chudrama' and v.id == p.author_id) torture = (v.agendaposter and not v.marseyawarded and p.sub != 'chudrama' and v.id == p.author_id)
title_html = filter_emojis_only(title, golden=False, torture=torture) title_html = filter_emojis_only(title, golden=False, torture=torture)
if v.id == p.author_id and v.marseyawarded and not marseyaward_title_regex.fullmatch(title_html): if v.id == p.author_id and v.marseyawarded and not marseyaward_title_regex.fullmatch(title_html):
return {"error":"You can only type marseys!"}, 403 abort(403, "You can only type marseys!")
p.title = title p.title = title
p.title_html = title_html p.title_html = title_html
@ -466,7 +466,7 @@ def edit_post(pid, v):
body_html = sanitize(body, golden=False, limit_pings=100, showmore=False, torture=torture) body_html = sanitize(body, golden=False, limit_pings=100, showmore=False, torture=torture)
if v.id == p.author_id and v.marseyawarded and marseyaward_body_regex.search(body_html): if v.id == p.author_id and v.marseyawarded and marseyaward_body_regex.search(body_html):
return {"error":"You can only type marseys!"}, 403 abort(403, "You can only type marseys!")
p.body = body p.body = body
@ -477,12 +477,13 @@ def edit_post(pid, v):
g.db.add(v) g.db.add(v)
send_repeatable_notification(CARP_ID, p.permalink) send_repeatable_notification(CARP_ID, p.permalink)
if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT: return {"error":f"Submission body_html too long! (max {POST_BODY_HTML_LENGTH_LIMIT} characters)"}, 400 if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
abort(400, f"Submission body_html too long! (max {POST_BODY_HTML_LENGTH_LIMIT} characters)")
p.body_html = body_html p.body_html = body_html
if v.id == p.author_id and v.agendaposter and not v.marseyawarded and AGENDAPOSTER_PHRASE not in f'{p.body}{p.title}'.lower() and p.sub != 'chudrama': if v.id == p.author_id and v.agendaposter and not v.marseyawarded and AGENDAPOSTER_PHRASE not in f'{p.body}{p.title}'.lower() and p.sub != 'chudrama':
return {"error": f'You have to include "{AGENDAPOSTER_PHRASE}" in your post!'}, 403 abort(403, f'You have to include "{AGENDAPOSTER_PHRASE}" in your post!')
if not p.private and not p.ghost: if not p.private and not p.ghost:
@ -702,7 +703,7 @@ def submit_post(v, sub=None):
body = sanitize_raw_body(request.values.get("body", ""), True) body = sanitize_raw_body(request.values.get("body", ""), True)
def error(error): def error(error):
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": error}, 400 if request.headers.get("Authorization") or request.headers.get("xhr"): abort(400, error)
SUBS = [x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()] SUBS = [x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()]
return render_template("submit.html", SUBS=SUBS, v=v, error=error, title=title, url=url, body=body), 400 return render_template("submit.html", SUBS=SUBS, v=v, error=error, title=title, url=url, body=body), 400
@ -1204,7 +1205,7 @@ def pin_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
if post: if post:
if v.id != post.author_id: return {"error": "Only the post author's can do that!"}, 400 if v.id != post.author_id: abort(400, "Only the post author's can do that!")
post.is_pinned = not post.is_pinned post.is_pinned = not post.is_pinned
g.db.add(post) g.db.add(post)
@ -1212,7 +1213,7 @@ def pin_post(post_id, v):
if post.is_pinned: return {"message": "Post pinned!"} if post.is_pinned: return {"message": "Post pinned!"}
else: return {"message": "Post unpinned!"} else: return {"message": "Post unpinned!"}
return {"error": "Post not found!"}, 400 return abort(404, "Post not found!")
extensions = ( extensions = (

View File

@ -21,14 +21,13 @@ def flag_post(pid, v):
if not v.is_banned: v.ban_reason = 'Blackjack' if not v.is_banned: v.ban_reason = 'Blackjack'
send_repeatable_notification(CARP_ID, f"reports on {post.permalink}") send_repeatable_notification(CARP_ID, f"reports on {post.permalink}")
if v.is_muted: if v.is_muted: abort(400, "You are forbidden from making reports.")
return {"error": "You are forbidden from making reports."}, 400
reason = reason[:100] reason = reason[:100]
reason = filter_emojis_only(reason) reason = filter_emojis_only(reason)
if len(reason) > 350: return {"error": "Too long."}, 400 if len(reason) > 350: abort(400, "Too long.")
if reason.startswith('!') and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.sub and v.mods(post.sub)): if reason.startswith('!') and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.sub and v.mods(post.sub)):
post.flair = reason[1:] post.flair = reason[1:]
@ -58,16 +57,16 @@ def flag_post(pid, v):
sub_to = g.db.get(Sub, sub_to) sub_to = g.db.get(Sub, sub_to)
sub_to = sub_to.name if sub_to else None sub_to = sub_to.name if sub_to else None
if sub_from == sub_to: {"error": f"Post is already in /h/{sub_to}"}, 400 if sub_from == sub_to: abort(400, f"Post is already in /h/{sub_to}")
if post.author.exiled_from(sub_to): if post.author.exiled_from(sub_to):
return {"error": f"User is exiled from this {HOLE_NAME}!"}, 400 abort(400, f"User is exiled from this {HOLE_NAME}!")
if sub_to in ('furry','vampire','racist','femboy') and not v.client and not post.author.house.lower().startswith(sub_to): if sub_to in ('furry','vampire','racist','femboy') and not v.client and not post.author.house.lower().startswith(sub_to):
if v.id == post.author_id: if v.id == post.author_id:
return {"error": f"You need to be a member of House {sub.capitalize()} to post in /h/{sub}"}, 403 abort(403, f"You need to be a member of House {sub_to.capitalize()} to post in /h/{sub_to}")
else: else:
return {"error": f"@{post.author.username} needs to be a member of House {sub.capitalize()} for their post to be moved to /h/{sub}"}, 400 abort(403, f"@{post.author.username} needs to be a member of House {sub_to.capitalize()} for their post to be moved to /h/{sub_to}")
post.sub = sub_to post.sub = sub_to
g.db.add(post) g.db.add(post)
@ -103,8 +102,7 @@ def flag_post(pid, v):
return {"message": f"Post moved to /h/{post.sub}"} return {"message": f"Post moved to /h/{post.sub}"}
else: else:
existing = g.db.query(Flag.post_id).filter_by(user_id=v.id, post_id=post.id).one_or_none() existing = g.db.query(Flag.post_id).filter_by(user_id=v.id, post_id=post.id).one_or_none()
if existing: if existing: abort(409, "You already reported this post!")
return {"error": "You already reported this post!"}, 409
flag = Flag(post_id=post.id, user_id=v.id, reason=reason) flag = Flag(post_id=post.id, user_id=v.id, reason=reason)
g.db.add(flag) g.db.add(flag)
@ -121,8 +119,7 @@ def flag_comment(cid, v):
comment = get_comment(cid) comment = get_comment(cid)
existing = g.db.query(CommentFlag.comment_id).filter_by(user_id=v.id, comment_id=comment.id).one_or_none() existing = g.db.query(CommentFlag.comment_id).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
if existing: if existing: abort(409, "You already reported this comment!")
return {"error": "You already reported this comment!"}, 409
reason = request.values.get("reason", "").strip() reason = request.values.get("reason", "").strip()
@ -135,7 +132,7 @@ def flag_comment(cid, v):
reason = filter_emojis_only(reason) reason = filter_emojis_only(reason)
if len(reason) > 350: return {"error": "Too long."}, 400 if len(reason) > 350: abort(400, "Too long.")
flag = CommentFlag(comment_id=comment.id, user_id=v.id, reason=reason) flag = CommentFlag(comment_id=comment.id, user_id=v.id, reason=reason)

View File

@ -75,7 +75,7 @@ def searchposts(v):
author = get_user(criteria['author'], v=v, include_shadowbanned=False) author = get_user(criteria['author'], v=v, include_shadowbanned=False)
if author.is_private and author.id != v.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye: if author.is_private and author.id != v.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye:
if request.headers.get("Authorization"): if request.headers.get("Authorization"):
return {"error": f"@{author.username}'s profile is private; You can't use the 'author' syntax on them"}, 400 abort(403, f"@{author.username}'s profile is private; You can't use the 'author' syntax on them")
return render_template("search.html", return render_template("search.html",
v=v, v=v,
query=query, query=query,
@ -193,7 +193,7 @@ def searchcomments(v):
if 'post' in criteria: if 'post' in criteria:
try: post = int(criteria['post']) try: post = int(criteria['post'])
except: return {"error": f"Post with id {post} does not exist."}, 400 except: abort(404, f"Post with id {post} does not exist.")
comments = comments.filter(Comment.parent_submission == post) comments = comments.filter(Comment.parent_submission == post)
@ -202,7 +202,7 @@ def searchcomments(v):
author = get_user(criteria['author'], v=v, include_shadowbanned=False) author = get_user(criteria['author'], v=v, include_shadowbanned=False)
if author.is_private and author.id != v.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye: if author.is_private and author.id != v.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye:
if request.headers.get("Authorization"): if request.headers.get("Authorization"):
return {"error": f"@{author.username}'s profile is private; You can't use the 'author' syntax on them"}, 400 abort(403, f"@{author.username}'s profile is private; You can't use the 'author' syntax on them")
return render_template("search_comments.html", v=v, query=query, total=0, page=page, comments=[], sort=sort, t=t, next_exists=False, error=f"@{author.username}'s profile is private; You can't use the 'author' syntax on them.") return render_template("search_comments.html", v=v, query=query, total=0, page=page, comments=[], sort=sort, t=t, next_exists=False, error=f"@{author.username}'s profile is private; You can't use the 'author' syntax on them.")

View File

@ -263,7 +263,7 @@ def settings_profile_post(v):
if theme: if theme:
if theme in {"4chan","classic","classic_dark","coffee","dark","dramblr","light","midnight","transparent","tron","win98"}: if theme in {"4chan","classic","classic_dark","coffee","dark","dramblr","light","midnight","transparent","tron","win98"}:
if theme == "transparent" and not v.background: if theme == "transparent" and not v.background:
return {"error": "You need to set a background to use the transparent theme!"}, 400 abort(400, "You need to set a background to use the transparent theme!")
v.theme = theme v.theme = theme
if theme == "win98": v.themecolor = "30409f" if theme == "win98": v.themecolor = "30409f"
updated = True updated = True
@ -294,7 +294,7 @@ def settings_profile_post(v):
return {"message": "Your settings have been updated."} return {"message": "Your settings have been updated."}
else: else:
return {"error": "You didn't change anything."}, 400 abort(400, "You didn't change anything.")
@app.post("/settings/filters") @app.post("/settings/filters")
@ -348,23 +348,23 @@ def themecolor(v):
@auth_required @auth_required
def gumroad(v): def gumroad(v):
if not (v.email and v.is_activated): if not (v.email and v.is_activated):
return {"error": f"You must have a verified email to verify {patron} status and claim your rewards!"}, 400 abort(400, f"You must have a verified email to verify {patron} status and claim your rewards!")
data = {'access_token': GUMROAD_TOKEN, 'email': v.email} data = {'access_token': GUMROAD_TOKEN, 'email': v.email}
response = requests.get('https://api.gumroad.com/v2/sales', data=data, timeout=5).json()["sales"] response = requests.get('https://api.gumroad.com/v2/sales', data=data, timeout=5).json()["sales"]
if len(response) == 0: return {"error": "Email not found"}, 404 if len(response) == 0: abort(404, "Email not found")
response = [x for x in response if x['variants_and_quantity']] response = [x for x in response if x['variants_and_quantity']]
response = response[0] response = response[0]
tier = tiers[response["variants_and_quantity"]] tier = tiers[response["variants_and_quantity"]]
if v.patron == tier: return {"error": f"{patron} rewards already claimed"}, 400 if v.patron == tier: abort(400, f"{patron} rewards already claimed")
procoins = procoins_li[tier] - procoins_li[v.patron] procoins = procoins_li[tier] - procoins_li[v.patron]
if procoins < 0: return {"error": f"{patron} rewards already claimed"}, 400 if procoins < 0: abort(400, f"{patron} rewards already claimed")
existing = g.db.query(User.id).filter(User.email == v.email, User.is_activated == True, User.patron >= tier).first() existing = g.db.query(User.id).filter(User.email == v.email, User.is_activated == True, User.patron >= tier).first()
if existing: return {"error": f"{patron} rewards already claimed on another account"}, 400 if existing: abort(400, f"{patron} rewards already claimed on another account")
v.patron = tier v.patron = tier
if v.discord_id: add_role(v, f"{tier}") if v.discord_id: add_role(v, f"{tier}")
@ -513,7 +513,7 @@ def settings_log_out_others(v):
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required @auth_required
def settings_images_profile(v): def settings_images_profile(v):
if request.headers.get("cf-ipcountry") == "T1": return {"error":"Image uploads are not allowed through TOR."}, 403 if request.headers.get("cf-ipcountry") == "T1": abort(403, "Image uploads are not allowed through TOR.")
file = request.files["profile"] file = request.files["profile"]
@ -549,9 +549,7 @@ def settings_images_profile(v):
@auth_required @auth_required
@feature_required('USERS_PROFILE_BANNER') @feature_required('USERS_PROFILE_BANNER')
def settings_images_banner(v): def settings_images_banner(v):
if request.headers.get("cf-ipcountry") == "T1": abort(403, "Image uploads are not allowed through TOR.")
if request.headers.get("cf-ipcountry") == "T1": return {"error":"Image uploads are not allowed through TOR."}, 403
file = request.files["banner"] file = request.files["banner"]
@ -586,12 +584,12 @@ def settings_css_get(v):
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required @auth_required
def settings_css(v): def settings_css(v):
if v.agendaposter: return {"error": "Agendapostered users can't edit css!"}, 400 if v.agendaposter: abort(400, "Agendapostered users can't edit CSS!")
css = request.values.get("css").strip().replace('\\', '').strip()[:4000] css = request.values.get("css").strip().replace('\\', '').strip()[:4000]
if '</style' in css.lower(): if '</style' in css.lower():
return {"error": "Please message @Aevann if you get this error"}, 400 abort(400, "Please message @Aevann if you get this error")
v.css = css v.css = css
g.db.add(v) g.db.add(v)
@ -625,21 +623,16 @@ def settings_profilecss(v):
def settings_block_user(v): def settings_block_user(v):
user = get_user(request.values.get("username"), graceful=True) user = get_user(request.values.get("username"), graceful=True)
if not user: return {"error": "This user doesn't exist."}, 404 if not user: abort(404, "This user doesn't exist.")
if user.unblockable: if user.unblockable:
if not v.shadowbanned: if not v.shadowbanned:
send_notification(user.id, f"@{v.username} has tried to block you and failed because of your unblockable status!") send_notification(user.id, f"@{v.username} has tried to block you and failed because of your unblockable status!")
return {"error": "This user is unblockable."}, 403 abort(403, "This user is unblockable.")
if user.id == v.id: if user.id == v.id: abort(400, "You can't block yourself")
return {"error": "You can't block yourself."}, 409 if user.id == AUTOJANNY_ID: abort(403, "You can't block this user")
if v.has_blocked(user): abort(409, f"You have already blocked @{user.username}")
if v.has_blocked(user):
return {"error": f"You have already blocked @{user.username}."}, 409
if user.id == AUTOJANNY_ID:
return {"error": "You can't block this user."}, 409
new_block = UserBlock(user_id=v.id, new_block = UserBlock(user_id=v.id,
target_id=user.id, target_id=user.id,
@ -660,13 +653,9 @@ def settings_block_user(v):
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@auth_required @auth_required
def settings_unblock_user(v): def settings_unblock_user(v):
user = get_user(request.values.get("username")) user = get_user(request.values.get("username"))
x = v.has_blocked(user) x = v.has_blocked(user)
if not x: abort(409, "You can't unblock someone you haven't blocked")
if not x: abort(409)
g.db.delete(x) g.db.delete(x)
if not v.shadowbanned and user.admin_level >= PERMS['USER_BLOCKS_VISIBLE']: if not v.shadowbanned and user.admin_level >= PERMS['USER_BLOCKS_VISIBLE']:

View File

@ -245,7 +245,7 @@ def add_mod(v, sub):
user = get_user(user, v=v, include_shadowbanned=False) user = get_user(user, v=v, include_shadowbanned=False)
if sub in ('furry','vampire','racist','femboy') and not v.client and not user.house.lower().startswith(sub): if sub in ('furry','vampire','racist','femboy') and not v.client and not user.house.lower().startswith(sub):
return {"error": f"@{user.username} needs to be a member of House {sub.capitalize()} to be added as a mod there!"}, 400 abort(403, f"@{user.username} needs to be a member of House {sub.capitalize()} to be added as a mod there!")
existing = g.db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none() existing = g.db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none()
@ -470,7 +470,7 @@ def get_sub_css(sub):
@limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@is_not_permabanned @is_not_permabanned
def sub_banner(v, sub): def sub_banner(v, sub):
if request.headers.get("cf-ipcountry") == "T1": return {"error":"Image uploads are not allowed through TOR."}, 403 if request.headers.get("cf-ipcountry") == "T1": abort(403, "Image uploads are not allowed through TOR.")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
@ -503,7 +503,7 @@ def sub_banner(v, sub):
@limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@is_not_permabanned @is_not_permabanned
def sub_sidebar(v, sub): def sub_sidebar(v, sub):
if request.headers.get("cf-ipcountry") == "T1": return {"error":"Image uploads are not allowed through TOR."}, 403 if request.headers.get("cf-ipcountry") == "T1": abort(403, "Image uploads are not allowed through TOR.")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
@ -535,7 +535,7 @@ def sub_sidebar(v, sub):
@limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @limiter.limit("1/second;10/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}')
@is_not_permabanned @is_not_permabanned
def sub_marsey(v, sub): def sub_marsey(v, sub):
if request.headers.get("cf-ipcountry") == "T1": return {"error":"Image uploads are not allowed through TOR."}, 403 if request.headers.get("cf-ipcountry") == "T1": abort(403, "Image uploads are not allowed through TOR.")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)

View File

@ -264,9 +264,9 @@ def transfer_coins(v, username):
amount = int(amount) if amount.isdigit() else None amount = int(amount) if amount.isdigit() else None
reason = request.values.get("reason", "").strip() reason = request.values.get("reason", "").strip()
if amount is None or amount <= 0: return {"error": "Invalid amount of coins."}, 400 if amount is None or amount <= 0: abort(400, "Invalid amount of coins.")
if v.coins < amount: return {"error": "You don't have enough coins."}, 400 if v.coins < amount: abort(400, "You don't have enough coins.")
if amount < 100: return {"error": "You have to gift at least 100 coins."}, 400 if amount < 100: abort(400, "You have to gift at least 100 coins.")
if not v.patron and not receiver.patron and not v.alts_patron and not receiver.alts_patron: tax = math.ceil(amount*0.03) if not v.patron and not receiver.patron and not v.alts_patron and not receiver.alts_patron: tax = math.ceil(amount*0.03)
else: tax = 0 else: tax = 0
@ -291,8 +291,7 @@ def transfer_coins(v, username):
g.db.add(v) g.db.add(v)
return {"message": f"{amount-tax} coins have been transferred to @{receiver.username}"}, 200 return {"message": f"{amount-tax} coins have been transferred to @{receiver.username}"}, 200
abort(400, "You can't transfer coins to yourself!")
return {"message": "You can't transfer coins to yourself!"}, 400
@app.post("/@<username>/transfer_bux") @app.post("/@<username>/transfer_bux")
@ -307,9 +306,9 @@ def transfer_bux(v, username):
amount = int(amount) if amount.isdigit() else None amount = int(amount) if amount.isdigit() else None
reason = request.values.get("reason", "").strip() reason = request.values.get("reason", "").strip()
if not amount or amount < 0: return {"error": "Invalid amount of marseybux."}, 400 if not amount or amount < 0: abort(400, "Invalid amount of marseybux.")
if v.procoins < amount: return {"error": "You don't have enough marseybux"}, 400 if v.procoins < amount: abort(400, "You don't have enough marseybux")
if amount < 100: return {"error": "You have to gift at least 100 marseybux."}, 400 if amount < 100: abort(400, "You have to gift at least 100 marseybux.")
v.procoins -= amount v.procoins -= amount
@ -331,7 +330,7 @@ def transfer_bux(v, username):
g.db.add(v) g.db.add(v)
return {"message": f"{amount} marseybux have been transferred to @{receiver.username}"}, 200 return {"message": f"{amount} marseybux have been transferred to @{receiver.username}"}, 200
return {"message": "You can't transfer marseybux to yourself!"}, 400 abort(400, "You can't transfer marseybux to yourslef!")
@app.get("/leaderboard") @app.get("/leaderboard")
@ -500,16 +499,16 @@ def message2(v, username):
user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False) user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False)
if hasattr(user, 'is_blocking') and user.is_blocking: if hasattr(user, 'is_blocking') and user.is_blocking:
return {"error": "You're blocking this user."}, 403 abort(403, "You're blocking this user.")
if v.admin_level <= PERMS['MESSAGE_BLOCKED_USERS'] and hasattr(user, 'is_blocked') and user.is_blocked: if v.admin_level <= PERMS['MESSAGE_BLOCKED_USERS'] and hasattr(user, 'is_blocked') and user.is_blocked:
return {"error": "This user is blocking you."}, 403 abort(403, "This user is blocking you.")
message = request.values.get("message", "").strip()[:10000].strip() message = request.values.get("message", "").strip()[:10000].strip()
if not message: return {"error": "Message is empty!"}, 400 if not message: abort(400, "Message is empty!")
if 'linkedin.com' in message: return {"error": "This domain 'linkedin.com' is banned."}, 403 if 'linkedin.com' in message: abort(403, "This domain 'linkedin.com' is banned.")
body_html = sanitize(message) body_html = sanitize(message)
@ -519,7 +518,7 @@ def message2(v, username):
Comment.body_html == body_html, Comment.body_html == body_html,
).first() ).first()
if existing: return {"error": "Message already exists."}, 403 if existing: abort(403, "Message already exists.")
c = Comment(author_id=v.id, c = Comment(author_id=v.id,
parent_submission=None, parent_submission=None,
@ -573,18 +572,18 @@ def messagereply(v):
body = request.values.get("body", "").strip().replace('','') body = request.values.get("body", "").strip().replace('','')
body = body.replace('\r\n', '\n')[:COMMENT_BODY_LENGTH_LIMIT] body = body.replace('\r\n', '\n')[:COMMENT_BODY_LENGTH_LIMIT]
if not body and not request.files.get("file"): return {"error": "Message is empty!"}, 400 if not body and not request.files.get("file"): abort(400, "Message is empty!")
if 'linkedin.com' in body: return {"error": "this domain 'linkedin.com' is banned"}, 400 if 'linkedin.com' in body: abort(400, "this domain 'linkedin.com' is banned")
id = int(request.values.get("parent_id")) id = int(request.values.get("parent_id"))
parent = get_comment(id, v=v) parent = get_comment(id, v=v)
user_id = parent.author.id user_id = parent.author.id
if v.is_suspended_permanently and parent.sentto != 2: if v.is_suspended_permanently and parent.sentto != 2:
return {"error": "You are permabanned and may not reply to messages."}, 400 abort(400, "You are permabanned and may not reply to messages.")
elif v.is_muted and parent.sentto == 2: elif v.is_muted and parent.sentto == 2:
return {"error": "You are forbidden from replying to modmail."}, 400 abort(400, "You are forbidden from replying to modmail.")
if parent.sentto == 2: user_id = None if parent.sentto == 2: user_id = None
elif v.id == user_id: user_id = parent.sentto elif v.id == user_id: user_id = parent.sentto
@ -791,14 +790,14 @@ def u_username(username, v=None):
if u.is_private and (not v or (v.id != u.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye)): if u.is_private and (not v or (v.id != u.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye)):
if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"): if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"):
return {"error": "This userpage is private"}, 403 abort(403, "This userpage is private")
return render_template("userpage_private.html", u=u, v=v) return render_template("userpage_private.html", u=u, v=v)
if v and hasattr(u, 'is_blocking') and u.is_blocking: if v and hasattr(u, 'is_blocking') and u.is_blocking:
if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"): if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"):
return {"error": f"You are blocking @{u.username}."}, 403 abort(403, f"You are blocking @{u.username}.")
return render_template("userpage_blocking.html", u=u, v=v) return render_template("userpage_blocking.html", u=u, v=v)
@ -877,12 +876,12 @@ def u_username_comments(username, v=None):
if u.is_private and (not v or (v.id != u.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye)): if u.is_private and (not v or (v.id != u.id and v.admin_level < PERMS['VIEW_PRIVATE_PROFILES'] and not v.eye)):
if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"): if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"):
return {"error": "This userpage is private"}, 403 abort(403, "This userpage is private")
return render_template("userpage_private.html", u=u, v=v) return render_template("userpage_private.html", u=u, v=v)
if v and hasattr(u, 'is_blocking') and u.is_blocking: if v and hasattr(u, 'is_blocking') and u.is_blocking:
if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"): if request.headers.get("Authorization") or request.headers.get("xhr") or request.path.endswith(".json"):
return {"error": f"You are blocking @{u.username}."}, 403 abort(403, f"You are blocking @{u.username}.")
return render_template("userpage_blocking.html", u=u, v=v) return render_template("userpage_blocking.html", u=u, v=v)
try: page = max(int(request.values.get("page", "1")), 1) try: page = max(int(request.values.get("page", "1")), 1)
@ -933,9 +932,9 @@ def u_username_info(username, v=None):
user=get_user(username, v=v, include_blocks=True, include_shadowbanned=False) user=get_user(username, v=v, include_blocks=True, include_shadowbanned=False)
if hasattr(user, 'is_blocking') and user.is_blocking: if hasattr(user, 'is_blocking') and user.is_blocking:
return {"error": "You're blocking this user."}, 401 abort(401, "You're blocking this user.")
elif hasattr(user, 'is_blocked') and user.is_blocked: elif hasattr(user, 'is_blocked') and user.is_blocked:
return {"error": "This user is blocking you."}, 403 abort(403, "This user is blocking you.")
return user.json return user.json
@ -946,9 +945,9 @@ def u_user_id_info(id, v=None):
user=get_account(id, v=v, include_blocks=True, include_shadowbanned=False) user=get_account(id, v=v, include_blocks=True, include_shadowbanned=False)
if hasattr(user, 'is_blocking') and user.is_blocking: if hasattr(user, 'is_blocking') and user.is_blocking:
return {"error": "You're blocking this user."}, 401 abort(403, "You're blocking this user.")
elif hasattr(user, 'is_blocked') and user.is_blocked: elif hasattr(user, 'is_blocked') and user.is_blocked:
return {"error": "This user is blocking you."}, 403 abort(403, "This user is blocking you.")
return user.json return user.json
@ -961,10 +960,10 @@ def follow_user(username, v):
target = get_user(username, v=v, include_shadowbanned=False) target = get_user(username, v=v, include_shadowbanned=False)
if target.id==v.id: if target.id==v.id:
return {"error": "You can't follow yourself!"}, 400 abort(400, "You can't follow yourself!")
if target.is_nofollow: if target.is_nofollow:
return {"error": "This user has disallowed other users from following them!"}, 403 abort(403, "This user has disallowed other users from following them!")
if g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none(): if g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none():
return {"message": f"@{target.username} has been followed!"} return {"message": f"@{target.username} has been followed!"}
@ -993,7 +992,7 @@ def unfollow_user(username, v):
if target.fish: if target.fish:
if not v.shadowbanned: if not v.shadowbanned:
send_notification(target.id, f"@{v.username} has tried to unfollow you and failed because of your fish award!") send_notification(target.id, f"@{v.username} has tried to unfollow you and failed because of your fish award!")
return {"error": "You can't unfollow this user!"}, 400 abort(400, "You can't unfollow this user!")
follow = g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none() follow = g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none()
@ -1223,15 +1222,15 @@ kofi_tiers={
@auth_required @auth_required
def settings_kofi(v): def settings_kofi(v):
if not (v.email and v.is_activated): if not (v.email and v.is_activated):
return {"error": f"You must have a verified email to verify {patron} status and claim your rewards!"}, 400 abort(400, f"You must have a verified email to verify {patron} status and claim your rewards!")
transaction = g.db.query(Transaction).filter_by(email=v.email).order_by(Transaction.created_utc.desc()).first() transaction = g.db.query(Transaction).filter_by(email=v.email).order_by(Transaction.created_utc.desc()).first()
if not transaction: if not transaction:
return {"error": "Email not found"}, 404 abort(404, "Email not found")
if transaction.claimed: if transaction.claimed:
return {"error": f"{patron} rewards already claimed"}, 400 abort(400, f"{patron} rewards already claimed")
tier = kofi_tiers[transaction.amount] tier = kofi_tiers[transaction.amount]

View File

@ -49,7 +49,7 @@ def vote_info_get(v, link):
@is_not_permabanned @is_not_permabanned
def vote_post(post_id, new, v): def vote_post(post_id, new, v):
if new == "-1" and DISABLE_DOWNVOTES: return {"error": "forbidden."}, 403 if new == "-1" and DISABLE_DOWNVOTES: abort(403)
if new not in ["-1", "0", "1"]: abort(400) if new not in ["-1", "0", "1"]: abort(400)
@ -126,7 +126,7 @@ def vote_post(post_id, new, v):
@is_not_permabanned @is_not_permabanned
def vote_comment(comment_id, new, v): def vote_comment(comment_id, new, v):
if new == "-1" and DISABLE_DOWNVOTES: return {"error": "forbidden."}, 403 if new == "-1" and DISABLE_DOWNVOTES: abort(403, "forbidden.")
if new not in ["-1", "0", "1"]: abort(400) if new not in ["-1", "0", "1"]: abort(400)

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>400 Bad Request</title>
{% endblock %}
{% block pagetype %}error-400{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseybrainlet:" loading="lazy" src="/e/marseybrainlet.webp">
<pre></pre>
<h1 class="h5">400 Bad Request</h1>
<p class="text-muted mb-5">That request was bad and you should feel bad.</p>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,24 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>401 Not Authorized</title>
{% endblock %}
{% block pagetype %}error-401{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseydead:" loading="lazy" src="/e/marseydead.webp">
<pre></pre>
<h1 class="h5">401 Not Authorized</h1>
<p class="text-muted mb-5">What you're trying to do requires an account. I think. The original error message said something about a castle and I hated that.</p>
<div><a href="/signup" class="btn btn-primary mb-2">Create an account</a></div>
<div><a href="/login" class="text-muted text-small">Or sign in</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>403 Forbidden</title>
{% endblock %}
{% block pagetype %}error-403{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseytroll:" loading="lazy" src="/e/marseytroll.webp">
<pre></pre>
<h1 class="h5">403 Forbidden</h1>
<p class="text-muted mb-5">{{description}}</p>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>404 Page Not Found</title>
{% endblock %}
{% block pagetype %}error-404{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyconfused" loading="lazy" src="/e/marseyconfused.webp">
<pre></pre>
<h1 class="h5">404 Page Not Found</h1>
<p class="text-muted mb-5">Someone typed something wrong and it was probably you, please do better.</p>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>405 Method Not Allowed</title>
{% endblock %}
{% block pagetype %}error-405{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyretard:" loading="lazy" src="/e/marseyretard.webp">
<pre></pre>
<h1 class="h5">405 Method Not Allowed</h1>
<p class="text-muted mb-5">idk how anyone gets this error but if you see this, remember to follow @carpathianflorist<BR>the original error text here talked about internet gremlins and wtf</p>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,21 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>Too many pings</title>
{% endblock %}
{% block pagetype %}Too many pings{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyrage" loading="lazy" src="/e/marseyrage.webp">
<pre></pre>
<h1 class="h5">Too many pings</h1>
<p class="text-muted mb-5">Max limit is 5 for comments and 50 for posts</p>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>Max image/audio size is 8 MB (16 MB for paypigs)</title>
{% endblock %}
{% block pagetype %}error-413{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyretard:" loading="lazy" src="/e/marseychonker2.webp">
<pre></pre>
<h1 class="h5">Max image/audio size is 8 MB (16 MB for paypigs)</h1>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>Max video size is 32 MB (64 MB for paypigs)</title>
{% endblock %}
{% block pagetype %}error-414{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyretard:" loading="lazy" src="/e/marseychonker2.webp">
<pre></pre>
<h1 class="h5">Max video size is 32 MB (64 MB for paypigs)</h1>
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>415 Unsupported Media Type</title>
{% endblock %}
{% block pagetype %}error-415{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseydetective:" loading="lazy" src="/e/marseydetective.webp">
<pre></pre>
<h1 class="h5">415 Unsupported Media Type</h1>
<p class="text-muted mb-5">Please upload only Image, Video, or Audio files!</p>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>WEBM videos are not allowed</title>
{% endblock %}
{% block pagetype %}error-418{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseytea:" loading="lazy" src="/e/marseytea.webp">
<pre></pre>
<h1 class="h5">WEBM videos are not allowed</h1>
<div><a href="/" class="btn btn-primary">Please convert your video to MP4 and re-upload it!</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>429 Too Many Requests</title>
{% endblock %}
{% block pagetype %}error-429{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
<img alt=":#marseyrentfree:" loading="lazy" src="/e/marseyrentfree.webp">
<pre></pre>
<h1 class="h5">429 Too Many Requests</h1>
<p class="text-muted mb-5">go spam somewhere else nerd</p>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,31 +0,0 @@
{% extends "default.html" %}
{% block title %}
<title>500 Internal Server Error</title>
{% endblock %}
{% block pagetype %}error-500{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
{% if SITE_NAME == 'PCM' %}
<img alt="wholesome" loading="lazy" src="/i/wholesome.webp">
{% else %}
<img alt=":#marseycarp3:" loading="lazy" src="/e/marseycarp3.webp">
{% endif %}
<pre></pre>
<h1 class="h5">500 Internal Server Error</h1>
<p class="text-muted mb-5">
{% if SITE_NAME == 'PCM' %}
Hiiiii it's <b>nigger</b>! I think this error means that there's a <b>nigger</b> error. And I think that means something took too long to load so it decided to be a <b>nigger</b>. If you keep seeing this on the same page but not other pages, then something its probably a <b>niggerfaggot</b>. It may not be called a <b>nigger</b>, but that sounds right to me. Anyway, ping me and I'll whine to someone smarter to fix it. Don't bother them. Thanks ily &lt;3
{% else %}
Hiiiii it's carp! I think this error means that there's a timeout error. And I think that means something took too long to load so it decided not to work at all. If you keep seeing this on the same page <I>but not other pages</I>, then something is probably wrong with that specific function. It may not be called a function, but that sounds right to me. Anyway, ping me and I'll whine to someone smarter to fix it. Don't bother them. Thanks ily &lt;3
{% endif %}
</p>
<div><a href="/" class="btn btn-primary">Go to the frontpage</a></div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "default.html" %}
{% block title %}
<title>{{code}} {{title}}</title>
{% endblock %}
{% block pagetype %}error-{{code}}{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-10 col-md-5">
<div class="text-center px-3 my-8">
{% if img -%}
<img alt=":#{{img}}:" loading="lazy" src="/e/{{img}}.webp">
{%- endif %}
<pre></pre>
<h1 class="h5">{{code}} {{title}}</h1>
<p class="text-muted error-description">{{msg|safe}}</p>
{% if details -%}
<blockquote class="error-details mb-5">{{details|safe}}</blockquote>
{%- endif %}
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
</div>
</div>
</div>
{% endblock %}