Rework error system a bit to remove a bunch of duplicated code (#434)
This commit is contained in:
parent
08602b4279
commit
0c632d73b7
28 changed files with 197 additions and 350 deletions
|
@ -161,10 +161,10 @@ def before_request():
|
|||
app.config['SETTINGS'] = json.load(f)
|
||||
|
||||
if request.host != app.config["SERVER_NAME"]:
|
||||
return {"error": "Unauthorized host provided."}, 401
|
||||
return {"error": "Unauthorized host provided."}, 403
|
||||
|
||||
if not app.config['SETTINGS']['Bots'] and request.headers.get("Authorization"):
|
||||
abort(503)
|
||||
abort(403, "Bots are currently not allowed")
|
||||
|
||||
g.db = db_session()
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ function post_toast3(t, url, button1, button2) {
|
|||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
|
||||
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
setTimeout(() => {
|
||||
|
@ -148,6 +149,7 @@ function delete_commentModal(id) {
|
|||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
|
||||
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
};
|
||||
|
@ -185,6 +187,7 @@ function post_reply(id){
|
|||
}
|
||||
else {
|
||||
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"];
|
||||
else document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
|
@ -227,6 +230,7 @@ function comment_edit(id){
|
|||
}
|
||||
else {
|
||||
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"];
|
||||
else document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
|
@ -314,6 +318,7 @@ function post_comment(fullname,id,level = 1){
|
|||
}
|
||||
else {
|
||||
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"];
|
||||
else document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
|
@ -396,6 +401,7 @@ function handle_action(type, cid, thing) {
|
|||
}
|
||||
else {
|
||||
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"];
|
||||
else document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ function delete_postModal(id) {
|
|||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
|
||||
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,6 +108,7 @@ function post_toast(t, url, reload, data) {
|
|||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
|
||||
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
setTimeout(() => {
|
||||
|
|
|
@ -30,6 +30,7 @@ function post_toast2(t, url, button1, button2) {
|
|||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = "Error, please try again later."
|
||||
if (data && data["error"]) document.getElementById('toast-post-error-text').innerText = data["error"];
|
||||
if (data && data["details"]) document.getElementById('toast-post-error-text').innerText = data["details"];
|
||||
bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error')).show();
|
||||
}
|
||||
setTimeout(() => {
|
||||
|
|
|
@ -169,7 +169,8 @@ function submitFormAjax(e) {
|
|||
let data=JSON.parse(xhr.response);
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error'));
|
||||
myToast.show();
|
||||
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"];
|
||||
} catch(e) {
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success'));
|
||||
myToast.hide();
|
||||
|
|
|
@ -42,14 +42,40 @@ PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()
|
|||
DEFAULT_COLOR = environ.get("DEFAULT_COLOR", "fff").strip()
|
||||
COLORS = {'ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','eb4963','ff0000','f39731','30409f','3e98a7','e4432d','7b9ae4','ec72de','7f8fa6', 'f8db58','8cdbe6', DEFAULT_COLOR}
|
||||
|
||||
ERROR_MESSAGES = {
|
||||
400: "That request was bad and you should feel bad",
|
||||
401: "You need an account for this. Please make one!",
|
||||
403: "You don't have access to this page.",
|
||||
404: "That page doesn't exist. If you got here from a link on the website, please report this issue. Thanks!",
|
||||
405: "Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!",
|
||||
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.",
|
||||
413: "Max file size is 8 MB",
|
||||
422: "Something is wrong about your request. If you keep getting this unexpectedly, please report it!",
|
||||
429: "Are you hammering the site? Stop that, yo.",
|
||||
500: "Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!",
|
||||
}
|
||||
|
||||
LOGGEDIN_ACTIVE_TIME = 15 * 60
|
||||
|
||||
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.",
|
||||
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.",
|
||||
415: "The server does not support the media type transmitted in the request.",
|
||||
422: "The request was well-formed but was unable to be followed due to semantic errors.",
|
||||
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.",
|
||||
}
|
||||
|
||||
IMAGE_FORMATS = ['png','gif','jpg','jpeg','webp']
|
||||
VIDEO_FORMATS = ['mp4','webm','mov','avi','mkv','flv','m4v','3gp']
|
||||
AUDIO_FORMATS = ['mp3','wav','ogg','aac','m4a','flac']
|
||||
NO_TITLE_EXTENSIONS = IMAGE_FORMATS + VIDEO_FORMATS + AUDIO_FORMATS
|
||||
|
||||
|
||||
AWARDS = {
|
||||
"lootbox": {
|
||||
"kind": "lootbox",
|
||||
|
|
|
@ -118,7 +118,7 @@ def is_not_permabanned(f):
|
|||
check_ban_evade(v)
|
||||
|
||||
if v.is_suspended_permanently:
|
||||
return {"error": "Forbidden: you are permabanned."}, 403
|
||||
abort(403, "You are permanently banned")
|
||||
|
||||
return make_response(f(*args, v=v, **kwargs))
|
||||
|
||||
|
|
|
@ -279,7 +279,8 @@ def club_allow(v, username):
|
|||
|
||||
if not u: abort(404)
|
||||
|
||||
if u.admin_level >= v.admin_level: return {"error": "noob"}
|
||||
if u.admin_level >= v.admin_level:
|
||||
abort(403, "Can't target users with admin level higher than you")
|
||||
|
||||
u.club_allowed = True
|
||||
g.db.add(u)
|
||||
|
@ -307,7 +308,8 @@ def club_ban(v, username):
|
|||
|
||||
if not u: abort(404)
|
||||
|
||||
if u.admin_level >= v.admin_level: return {"error": "noob"}
|
||||
if u.admin_level >= v.admin_level:
|
||||
abort(403, "Can't target users with admin level higher than you")
|
||||
|
||||
u.club_allowed = False
|
||||
|
||||
|
@ -502,7 +504,7 @@ def change_settings(v, setting):
|
|||
site_settings[setting] = int(new_value)
|
||||
else:
|
||||
# 422ing for any other types for now, feel free to add some more types if needed
|
||||
abort(422)
|
||||
abort(422, "Not a valid config value type")
|
||||
else:
|
||||
site_settings[setting] = not site_settings[setting]
|
||||
if site_settings[setting]: word = 'enabled'
|
||||
|
@ -555,7 +557,7 @@ def purge_cache(v):
|
|||
g.db.add(ma)
|
||||
|
||||
if response == "<Response [200]>": return {"message": "Cache purged!"}
|
||||
return {"error": "Failed to purge cache."}
|
||||
abort(500, "Failed to purge cache.")
|
||||
|
||||
|
||||
@app.post("/admin/under_attack")
|
||||
|
@ -574,7 +576,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":"medium"}', timeout=5))
|
||||
if response == "<Response [200]>": return {"message": "Under attack mode disabled!"}
|
||||
return {"error": "Failed to disable under attack mode."}
|
||||
abort(500, "Failed to disable under attack mode.")
|
||||
else:
|
||||
ma = ModAction(
|
||||
kind="enable_under_attack",
|
||||
|
@ -585,7 +587,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))
|
||||
if response == "<Response [200]>": return {"message": "Under attack mode enabled!"}
|
||||
return {"error": "Failed to enable under attack mode."}
|
||||
abort(500, "Failed to enable under attack mode.")
|
||||
|
||||
@app.get("/admin/badge_grant")
|
||||
@limiter.exempt
|
||||
|
@ -1307,7 +1309,7 @@ def sticky_post(post_id, v):
|
|||
if v.admin_level > 1:
|
||||
post.stickied = v.username
|
||||
post.stickied_utc = int(time.time()) + 3600
|
||||
else: return {"error": "Can't exceed 3 pinned posts limit!"}, 403
|
||||
else: abort(403, "Can't exceed 3 pinned posts limit!")
|
||||
else: post.stickied = v.username
|
||||
g.db.add(post)
|
||||
|
||||
|
@ -1332,7 +1334,7 @@ def unsticky_post(post_id, v):
|
|||
|
||||
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
|
||||
if post and post.stickied:
|
||||
if post.stickied.endswith('(pin award)'): return {"error": "Can't unpin award pins!"}, 403
|
||||
if post.stickied.endswith('(pin award)'): abort(403, "Can't unpin award pins!")
|
||||
|
||||
post.stickied = None
|
||||
post.stickied_utc = None
|
||||
|
@ -1386,7 +1388,7 @@ def unsticky_comment(cid, v):
|
|||
comment = get_comment(cid, v=v)
|
||||
|
||||
if comment.is_pinned:
|
||||
if comment.is_pinned.endswith("(pin award)"): return {"error": "Can't unpin award pins!"}, 403
|
||||
if comment.is_pinned.endswith("(pin award)"): abort(403, "Can't unpin award pins!")
|
||||
|
||||
comment.is_pinned = None
|
||||
g.db.add(comment)
|
||||
|
|
|
@ -36,10 +36,10 @@ def buy(v, award):
|
|||
abort(404) # disable entirely pending possible future use of coins
|
||||
|
||||
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 < 2:
|
||||
return {"error": "Only admins can buy that award."}, 403
|
||||
abort(403, "Only admins can buy that award.")
|
||||
|
||||
AWARDS = deepcopy(AWARDS2)
|
||||
|
||||
|
@ -49,11 +49,11 @@ def buy(v, award):
|
|||
price = int(og_price * v.discount)
|
||||
|
||||
if request.values.get("mb"):
|
||||
if v.procoins < price: return {"error": "Not enough marseybux."}, 400
|
||||
if award == "grass": return {"error": "You can't buy the grass award with marseybux."}, 403
|
||||
if v.procoins < price: abort(400, "Not enough marseybux.")
|
||||
if award == "grass": abort(403, "You can't buy the grass award with marseybux.")
|
||||
v.procoins -= price
|
||||
else:
|
||||
if v.coins < price: return {"error": "Not enough coins."}, 400
|
||||
if v.coins < price: abort(400, "Not enough coins.")
|
||||
v.coins -= price
|
||||
v.coins_spent += price
|
||||
if v.coins_spent >= 1000000 and not v.has_badge(73):
|
||||
|
@ -129,7 +129,7 @@ def award_post(pid, v):
|
|||
kind = request.values.get("kind", "").strip()
|
||||
|
||||
if kind not in AWARDS:
|
||||
return {"error": "That award doesn't exist."}, 404
|
||||
abort(404, "That award doesn't exist.")
|
||||
|
||||
post_award = g.db.query(AwardRelationship).filter(
|
||||
AwardRelationship.kind == kind,
|
||||
|
@ -139,12 +139,12 @@ def award_post(pid, v):
|
|||
).first()
|
||||
|
||||
if not post_award:
|
||||
return {"error": "You don't have that award."}, 404
|
||||
abort(404, "You don't have that award.")
|
||||
|
||||
post = g.db.query(Submission).filter_by(id=pid).one_or_none()
|
||||
|
||||
if not post:
|
||||
return {"error": "That post doesn't exist."}, 404
|
||||
abort(404, "That post doesn't exist.")
|
||||
|
||||
post_award.submission_id = post.id
|
||||
g.db.add(post_award)
|
||||
|
@ -154,7 +154,7 @@ def award_post(pid, v):
|
|||
author = post.author
|
||||
|
||||
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 v.id != author.id:
|
||||
msg = f"@{v.username} has given your [post]({post.shortlink}) the {AWARDS[kind]['title']} Award!"
|
||||
|
@ -231,7 +231,7 @@ def award_comment(cid, v):
|
|||
kind = request.values.get("kind", "").strip()
|
||||
|
||||
if kind not in AWARDS:
|
||||
return {"error": "That award doesn't exist."}, 404
|
||||
abort(404, "That award doesn't exist.")
|
||||
|
||||
comment_award = g.db.query(AwardRelationship).filter(
|
||||
AwardRelationship.kind == kind,
|
||||
|
@ -241,12 +241,12 @@ def award_comment(cid, v):
|
|||
).first()
|
||||
|
||||
if not comment_award:
|
||||
return {"error": "You don't have that award."}, 404
|
||||
abort(404, "You don't have that award.")
|
||||
|
||||
c = g.db.query(Comment).filter_by(id=cid).one_or_none()
|
||||
|
||||
if not c:
|
||||
return {"error": "That comment doesn't exist."}, 404
|
||||
abort(404, "That comment doesn't exist.")
|
||||
|
||||
comment_award.comment_id = c.id
|
||||
g.db.add(comment_award)
|
||||
|
@ -261,7 +261,7 @@ def award_comment(cid, v):
|
|||
send_repeatable_notification(author.id, msg)
|
||||
|
||||
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 == "ban":
|
||||
link = f"[this comment]({c.shortlink})"
|
||||
|
@ -372,7 +372,7 @@ def admin_userawards_post(v):
|
|||
for key, value in notify_awards.items():
|
||||
note += f"{value} {AWARDS[key]['title']}, "
|
||||
|
||||
if len(note) > 256: return {"error": "You're giving too many awards at the same time!"}
|
||||
if len(note) > 256: abort(400, "You're giving too many awards at the same time!")
|
||||
|
||||
ma=ModAction(
|
||||
kind="grant_awards",
|
||||
|
|
|
@ -144,7 +144,7 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
|
|||
@limiter.limit("1/second;20/minute;200/hour;1000/day")
|
||||
@auth_required
|
||||
def api_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_fullname = request.values.get("parent_fullname").strip()
|
||||
|
||||
|
@ -166,11 +166,11 @@ def api_comment(v):
|
|||
if not parent_post: abort(404) # don't allow sending comments to the ether
|
||||
level = 1 if isinstance(parent, Submission) else parent.level + 1
|
||||
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}")
|
||||
|
||||
body = request.values.get("body", "").strip()[:10000]
|
||||
|
||||
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!")
|
||||
|
||||
if request.files.get("file") and request.headers.get("cf-ipcountry") != "T1":
|
||||
files = request.files.getlist('file')[:4]
|
||||
|
@ -180,7 +180,7 @@ def api_comment(v):
|
|||
file.save(oldname)
|
||||
image = process_image(oldname)
|
||||
if image == "":
|
||||
return {"error":"Image upload failed"}
|
||||
abort(500, "Image upload failed")
|
||||
|
||||
if app.config['MULTIMEDIA_EMBEDDING_ENABLED']:
|
||||
body += f"\n\n"
|
||||
|
@ -190,18 +190,18 @@ def api_comment(v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
if app.config['MULTIMEDIA_EMBEDDING_ENABLED']:
|
||||
body += f"\n\n{url}"
|
||||
else:
|
||||
body += f'\n\n<a href="{url}">{url}</a>'
|
||||
else: return {"error": "Image/Video files only"}, 400
|
||||
else: abort(400, "Image/Video files only")
|
||||
|
||||
body_html = sanitize(body, comment=True)
|
||||
|
||||
|
@ -214,10 +214,10 @@ def api_comment(v):
|
|||
).one_or_none()
|
||||
|
||||
if existing:
|
||||
return {"error": f"You already made that comment: /comment/{existing.id}"}, 409
|
||||
abort(409, f"You already made that comment: /comment/{existing.id}")
|
||||
|
||||
if parent.author.any_block_exists(v) and v.admin_level < 2:
|
||||
return {"error": "You can't reply to users who have blocked you, or users you have blocked."}, 403
|
||||
abort(403, "You can't reply to users who have blocked you, or users you have blocked.")
|
||||
|
||||
is_bot = bool(request.headers.get("Authorization"))
|
||||
|
||||
|
@ -257,7 +257,7 @@ def api_comment(v):
|
|||
)
|
||||
g.db.add(ma)
|
||||
|
||||
return {"error": "Too much spam!"}, 403
|
||||
abort(403, "Too much spam!")
|
||||
|
||||
if len(body_html) > 20000: abort(400)
|
||||
|
||||
|
@ -369,7 +369,7 @@ def edit_comment(cid, v):
|
|||
body = request.values.get("body", "").strip()[:10000]
|
||||
|
||||
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":
|
||||
body_html = sanitize(body, edit=True)
|
||||
|
@ -406,7 +406,7 @@ def edit_comment(cid, v):
|
|||
comment.ban_reason = "AutoJanny"
|
||||
g.db.add(comment)
|
||||
|
||||
return {"error": "Too much spam!"}, 403
|
||||
abort(403, "Too much spam!")
|
||||
# End Spam Checking
|
||||
|
||||
if request.files.get("file") and request.headers.get("cf-ipcountry") != "T1":
|
||||
|
@ -421,15 +421,15 @@ def edit_comment(cid, v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
body += f"\n\n{url}"
|
||||
else: return {"error": "Image/Video files only"}, 400
|
||||
else: abort(400, "Image/Video files only")
|
||||
|
||||
body_html = sanitize(body, edit=True)
|
||||
|
||||
|
@ -526,7 +526,7 @@ def unpin_comment(cid, v):
|
|||
if v.id != comment.post.author_id: abort(403)
|
||||
|
||||
if not comment.is_pinned.endswith(" (OP)"):
|
||||
return {"error": "You can only unpin comments you have pinned!"}
|
||||
abort(403, "You can only unpin comments you have pinned!")
|
||||
|
||||
comment.is_pinned = None
|
||||
g.db.add(comment)
|
||||
|
|
|
@ -1,70 +1,41 @@
|
|||
from files.helpers.wrappers import *
|
||||
from flask import *
|
||||
from flask import request, session
|
||||
from urllib.parse import quote, urlencode
|
||||
import time
|
||||
from files.__main__ import app, limiter
|
||||
|
||||
from files.__main__ import app
|
||||
from http.client import responses
|
||||
|
||||
|
||||
@app.errorhandler(400)
|
||||
def error_400(e):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "400 Bad Request"}, 400
|
||||
else: return render_template('errors/400.html', err=True), 400
|
||||
@app.errorhandler(401)
|
||||
@app.errorhandler(403)
|
||||
@app.errorhandler(404)
|
||||
@app.errorhandler(405)
|
||||
@app.errorhandler(413)
|
||||
@app.errorhandler(422)
|
||||
@app.errorhandler(429)
|
||||
def error(e):
|
||||
title = responses.get(e.code, "Internal Server Error")
|
||||
description = ERROR_MESSAGES.get(e.code, e.code)
|
||||
details = None if e.description == WERKZEUG_ERROR_DESCRIPTIONS.get(e.code, e.code) else e.description
|
||||
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"):
|
||||
return {"code": e.code, "description": description, "details": details, "error": title}, e.code
|
||||
|
||||
return render_template('errors/error.html', err=True, code=e.code, error=title, description=description, details=details), e.code
|
||||
|
||||
@app.errorhandler(401)
|
||||
def error_401(e):
|
||||
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "401 Not Authorized"}, 401
|
||||
else:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return error(e)
|
||||
path = request.path
|
||||
qs = urlencode(dict(request.values))
|
||||
argval = quote(f"{path}?{qs}", safe='')
|
||||
return redirect(f"/login?redirect={argval}")
|
||||
|
||||
@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 don't have access to this page."
|
||||
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):
|
||||
return {"error": "Max file size is 8 MB (16 MB for paypigs)"}, 413
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"):
|
||||
return {"error": "Max file size is 8 MB (16 MB for paypigs)"}, 413
|
||||
else: return render_template('errors/413.html', err=True), 413
|
||||
|
||||
@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)
|
||||
def error_500(e):
|
||||
g.db.rollback()
|
||||
|
||||
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
|
||||
|
||||
return error(e)
|
||||
|
||||
@app.post("/allow_nsfw")
|
||||
def allow_nsfw():
|
||||
|
|
|
@ -179,7 +179,7 @@ def logout(v):
|
|||
@auth_desired
|
||||
def sign_up_get(v):
|
||||
if not app.config['SETTINGS']['Signups']:
|
||||
return {"error": "New account registration is currently closed. Please come back later."}, 403
|
||||
abort(403, "New account registration is currently closed. Please come back later.")
|
||||
|
||||
if v: return redirect(SITE_FULL)
|
||||
|
||||
|
@ -225,7 +225,7 @@ def sign_up_get(v):
|
|||
@auth_desired
|
||||
def sign_up_post(v):
|
||||
if not app.config['SETTINGS']['Signups']:
|
||||
return {"error": "New account registration is currently closed. Please come back later."}, 403
|
||||
abort(403, "New account registration is currently closed. Please come back later.")
|
||||
|
||||
if v: abort(403)
|
||||
|
||||
|
@ -254,7 +254,6 @@ def sign_up_post(v):
|
|||
username = username.strip()
|
||||
|
||||
def signup_error(error):
|
||||
|
||||
args = {"error": error}
|
||||
if request.values.get("referred_by"):
|
||||
user = g.db.query(User).filter_by(id=request.values.get("referred_by")).one_or_none()
|
||||
|
|
|
@ -38,20 +38,19 @@ MAX_TITLE_LENGTH = 500
|
|||
MAX_URL_LENGTH = 2048
|
||||
MAX_BODY_LENGTH = 20000
|
||||
|
||||
# Get request value `val` and ensure it is within length constraints
|
||||
# : Returns an either tuple (good_value, error)
|
||||
# : TODO it may make sense to do more sanitisation here
|
||||
def guarded_value(val, min_len, max_len):
|
||||
|
||||
def guarded_value(val, min_len, max_len) -> str:
|
||||
'''
|
||||
Get request value `val` and ensure it is within length constraints
|
||||
Requires a request context and either aborts early or returns a good value
|
||||
'''
|
||||
raw = request.values.get(val, '').strip()
|
||||
raw = raw.replace('\u200e', '')
|
||||
|
||||
if len(raw) < min_len:
|
||||
return (None, ({"error": f"Minimum length for {val} is {min_len}"}, 403))
|
||||
|
||||
if len(raw) > max_len:
|
||||
return (None, ({"error": f"Maximum length for {val} is {max_len}"}, 403))
|
||||
|
||||
return (raw, None)
|
||||
if len(raw) < min_len: abort(400, f"Minimum length for {val} is {min_len}")
|
||||
if len(raw) > max_len: abort(400, f"Maximum length for {val} is {max_len}")
|
||||
# TODO: it may make sense to do more sanitisation here
|
||||
return raw
|
||||
|
||||
@app.post("/toggle_club/<pid>")
|
||||
@auth_required
|
||||
|
@ -130,7 +129,7 @@ def post_id(pid, anything=None, v=None, sub=None):
|
|||
post = get_post(pid, v=v)
|
||||
|
||||
if post.over_18 and not (v and v.over_18) and session.get('over_18', 0) < int(time.time()):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error":"Must be 18+ to view"}, 451
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, "Must be 18+ to view")
|
||||
return render_template("errors/nsfw.html", v=v)
|
||||
|
||||
if v: defaultsortingcomments = v.defaultsortingcomments
|
||||
|
@ -441,11 +440,8 @@ def edit_post(pid, v):
|
|||
|
||||
if p.author_id != v.id and not (v.admin_level > 1 and v.admin_level > 2): abort(403)
|
||||
|
||||
title, err = guarded_value("title", 1, MAX_TITLE_LENGTH)
|
||||
if err: return err
|
||||
|
||||
body, err = guarded_value("body", 0, MAX_BODY_LENGTH)
|
||||
if err: return err
|
||||
title = guarded_value("title", 1, MAX_TITLE_LENGTH)
|
||||
body = guarded_value("body", 0, MAX_BODY_LENGTH)
|
||||
|
||||
if title != p.title:
|
||||
p.title = title
|
||||
|
@ -467,24 +463,24 @@ def edit_post(pid, v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
if app.config['MULTIMEDIA_EMBEDDING_ENABLED']:
|
||||
body += f"\n\n"
|
||||
else:
|
||||
body += f'\n\n<a href="{url}">{url}</a>'
|
||||
else: return {"error": "Image/Video files only"}, 400
|
||||
else: abort(400, "Image/Video files only")
|
||||
|
||||
body_html = sanitize(body, edit=True)
|
||||
|
||||
p.body = body
|
||||
|
||||
if len(body_html) > 40000: return {"error":"Submission body_html too long! (max 40k characters)"}, 400
|
||||
if len(body_html) > 40000: abort(400, "Submission body_html too long! (max 40k characters)")
|
||||
|
||||
p.body_html = body_html
|
||||
|
||||
|
@ -711,19 +707,14 @@ def api_is_repost():
|
|||
def submit_post(v, sub=None):
|
||||
|
||||
def error(error):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": error}, 403
|
||||
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()]
|
||||
return render_template("submit.html", SUBS=SUBS, v=v, error=error, title=title, url=url, body=body), 400
|
||||
|
||||
title, err = guarded_value("title", 1, MAX_TITLE_LENGTH)
|
||||
if err: return error(err[0]["error"])
|
||||
|
||||
url, err = guarded_value("url", 0, MAX_URL_LENGTH)
|
||||
if err: return error(err[0]["error"])
|
||||
|
||||
body, err = guarded_value("body", 0, MAX_BODY_LENGTH)
|
||||
if err: return error(err[0]["error"])
|
||||
title = guarded_value("title", 1, MAX_TITLE_LENGTH)
|
||||
url = guarded_value("url", 0, MAX_URL_LENGTH)
|
||||
body = guarded_value("body", 0, MAX_BODY_LENGTH)
|
||||
|
||||
sub = request.values.get("sub")
|
||||
if sub: sub = sub.replace('/h/','').replace('s/','')
|
||||
|
@ -1125,10 +1116,8 @@ def unsave_post(pid, v):
|
|||
@app.post("/pin/<post_id>")
|
||||
@auth_required
|
||||
def api_pin_post(post_id, v):
|
||||
|
||||
post = g.db.query(Submission).filter_by(id=post_id).one_or_none()
|
||||
if post:
|
||||
if v.id != post.author_id: return {"error": "Only the post author's can do that!"}
|
||||
post = get_post(post_id)
|
||||
if v.id != post.author_id: abort(403, "Only the post author's can do that!")
|
||||
post.is_pinned = not post.is_pinned
|
||||
g.db.add(post)
|
||||
|
||||
|
@ -1137,7 +1126,6 @@ def api_pin_post(post_id, v):
|
|||
g.db.commit()
|
||||
if post.is_pinned: return {"message": "Post pinned!"}
|
||||
else: return {"message": "Post unpinned!"}
|
||||
return {"error": "Post not found!"}
|
||||
|
||||
@app.get("/submit/title")
|
||||
@limiter.limit("6/minute")
|
||||
|
@ -1148,7 +1136,6 @@ def get_post_title(v):
|
|||
if not url or '\\' in url: abort(400)
|
||||
url = url.strip()
|
||||
if not url.startswith('http'): abort(400)
|
||||
|
||||
checking_url = url.lower().split('?')[0].split('%3F')[0]
|
||||
if any((checking_url.endswith(f'.{x}') for x in NO_TITLE_EXTENSIONS)):
|
||||
abort(400)
|
||||
|
|
|
@ -69,10 +69,9 @@ def searchposts(v):
|
|||
if 'author' in criteria:
|
||||
posts = posts.filter(Submission.ghost == False)
|
||||
author = get_user(criteria['author'])
|
||||
if not author: return {"error": "User not found"}
|
||||
if author.is_private and (not v or (author.id != v.id and v.admin_level < 2)):
|
||||
if request.headers.get("Authorization"):
|
||||
return {"error": f"@{author.username}'s profile is private; You can't use the 'author' syntax on them"}
|
||||
abort(403, f"@{author.username}'s profile is private; You can't use the 'author' syntax on them")
|
||||
return render_template("search.html",
|
||||
v=v,
|
||||
query=query,
|
||||
|
@ -195,10 +194,9 @@ def searchcomments(v):
|
|||
if 'author' in criteria:
|
||||
comments = comments.filter(Comment.ghost == False)
|
||||
author = get_user(criteria['author'])
|
||||
if not author: return {"error": "User not found"}
|
||||
if author.is_private and (not v or (author.id != v.id and v.admin_level < 2)):
|
||||
if request.headers.get("Authorization"):
|
||||
return {"error": f"@{author.username}'s profile is private; You can't use the 'author' syntax on them"}
|
||||
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.")
|
||||
|
||||
|
|
|
@ -177,16 +177,16 @@ def settings_profile_post(v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
bio += f"\n\n{url}"
|
||||
else:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "Image/Video files only"}, 400
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(400, "Image/Video files only")
|
||||
return render_template("settings_profile.html", v=v, error="Image/Video files only."), 400
|
||||
|
||||
bio_html = sanitize(bio)
|
||||
|
@ -240,7 +240,7 @@ def settings_profile_post(v):
|
|||
if theme:
|
||||
if theme in THEMES:
|
||||
if theme == "transparent" and not v.background:
|
||||
return {"error": "You need to set a background to use the transparent theme!"}
|
||||
abort(400, "You need to set a background to use the transparent theme!")
|
||||
v.theme = theme
|
||||
if theme == "win98": v.themecolor = "30409f"
|
||||
updated = True
|
||||
|
@ -266,7 +266,7 @@ def settings_profile_post(v):
|
|||
return {"message": "Your settings have been updated."}
|
||||
|
||||
else:
|
||||
return {"error": "You didn't change anything."}, 400
|
||||
abort(400, "You didn't change anything.")
|
||||
|
||||
|
||||
@app.post("/settings/filters")
|
||||
|
@ -453,7 +453,7 @@ def settings_log_out_others(v):
|
|||
@limiter.limit("1/second;30/minute;200/hour;1000/day")
|
||||
@auth_required
|
||||
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"]
|
||||
|
||||
|
@ -488,7 +488,7 @@ def settings_images_profile(v):
|
|||
@limiter.limit("1/second;30/minute;200/hour;1000/day")
|
||||
@auth_required
|
||||
def settings_images_banner(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["banner"]
|
||||
|
||||
|
@ -552,16 +552,16 @@ def settings_block_user(v):
|
|||
|
||||
user = get_user(request.values.get("username"), graceful=True)
|
||||
|
||||
if not user: return {"error": "That user doesn't exist."}, 404
|
||||
if not user: abort(404, "That user doesn't exist.")
|
||||
|
||||
if user.id == v.id:
|
||||
return {"error": "You can't block yourself."}, 409
|
||||
abort(409, "You can't block yourself.")
|
||||
|
||||
if v.is_blocking(user):
|
||||
return {"error": f"You have already blocked @{user.username}."}, 409
|
||||
abort(409, f"You have already blocked @{user.username}.")
|
||||
|
||||
if user.id == NOTIFICATIONS_ID:
|
||||
return {"error": "You can't block this user."}, 409
|
||||
abort(409, "You can't block this user.")
|
||||
|
||||
new_block = UserBlock(user_id=v.id,
|
||||
target_id=user.id,
|
||||
|
|
|
@ -310,15 +310,15 @@ def submit_contact(v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
html += f"<p>{url}</p>"
|
||||
else: return {"error": "Image/Video files only"}, 400
|
||||
else: abort(400, "Image/Video files only")
|
||||
|
||||
new_comment = Comment(author_id=v.id if v else NOTIFICATIONS_ID,
|
||||
parent_submission=None,
|
||||
|
|
|
@ -74,12 +74,6 @@ def unexile(v, sub, uid):
|
|||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"message": "User unexiled successfully!"}
|
||||
return redirect(f'/h/{sub}/exilees')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@app.post("/h/<sub>/block")
|
||||
@auth_required
|
||||
def block_sub(v, sub):
|
||||
|
@ -87,7 +81,7 @@ def block_sub(v, sub):
|
|||
if not sub: abort(404)
|
||||
sub = sub.name
|
||||
|
||||
if v.mods(sub): return {"error": "You can't block subs you mod!"}
|
||||
if v.mods(sub): abort(409, "You can't block subs you mod!")
|
||||
|
||||
existing = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
|
||||
|
||||
|
@ -337,7 +331,7 @@ def get_sub_css(sub):
|
|||
@limiter.limit("1/second;10/day")
|
||||
@is_not_permabanned
|
||||
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 = g.db.query(Sub).filter_by(name=sub.lower().strip()).one_or_none()
|
||||
if not sub: abort(404)
|
||||
|
@ -364,7 +358,7 @@ def sub_banner(v, sub):
|
|||
@limiter.limit("1/second;10/day")
|
||||
@is_not_permabanned
|
||||
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 = g.db.query(Sub).filter_by(name=sub.lower().strip()).one_or_none()
|
||||
if not sub: abort(404)
|
||||
|
|
|
@ -347,15 +347,15 @@ def transfer_coins(v, username):
|
|||
|
||||
receiver = g.db.query(User).filter_by(username=username).one_or_none()
|
||||
|
||||
if receiver is None: return {"error": "That user doesn't exist."}, 404
|
||||
if receiver is None: abort(404, "That user doesn't exist.")
|
||||
|
||||
if receiver.id != v.id:
|
||||
amount = request.values.get("amount", "").strip()
|
||||
amount = int(amount) if amount.isdigit() else None
|
||||
|
||||
if amount is None or amount <= 0: return {"error": "Invalid amount of coins."}, 400
|
||||
if v.coins < amount: return {"error": "You don't have enough coins."}, 400
|
||||
if amount < 100: return {"error": "You have to gift at least 100 coins."}, 400
|
||||
if amount is None or amount <= 0: abort(400, "Invalid amount of coins.")
|
||||
if v.coins < amount: abort(400, "You don't have enough coins.")
|
||||
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)
|
||||
else: tax = 0
|
||||
|
@ -383,15 +383,15 @@ def transfer_bux(v, username):
|
|||
|
||||
receiver = g.db.query(User).filter_by(username=username).one_or_none()
|
||||
|
||||
if not receiver: return {"error": "That user doesn't exist."}, 404
|
||||
if not receiver: abort(404, "That user doesn't exist.")
|
||||
|
||||
if receiver.id != v.id:
|
||||
amount = request.values.get("amount", "").strip()
|
||||
amount = int(amount) if amount.isdigit() else None
|
||||
|
||||
if not amount or amount < 0: return {"error": "Invalid amount of marseybux."}, 400
|
||||
if v.procoins < amount: return {"error": "You don't have enough marseybux"}, 400
|
||||
if amount < 100: return {"error": "You have to gift at least 100 marseybux."}, 400
|
||||
if not amount or amount < 0: abort(400, "Invalid amount of marseybux.")
|
||||
if v.procoins < amount: abort(400, "You don't have enough marseybux")
|
||||
if amount < 100: abort(400, "You have to gift at least 100 marseybux.")
|
||||
|
||||
log_message = f"@{v.username} has transferred {amount} Marseybux to @{receiver.username}"
|
||||
send_repeatable_notification(GIFT_NOTIF_ID, log_message)
|
||||
|
@ -537,18 +537,18 @@ def reportbugs(v):
|
|||
@auth_required
|
||||
def message2(v, username):
|
||||
if v.is_suspended_permanently:
|
||||
return {"error": "You have been permabanned and cannot send messages; " + \
|
||||
"contact modmail if you think this decision was incorrect."}, 403
|
||||
abort(403, "You have been permabanned and cannot send messages; " + \
|
||||
"contact modmail if you think this decision was incorrect.")
|
||||
|
||||
user = get_user(username, v=v)
|
||||
if hasattr(user, 'is_blocking') and user.is_blocking: return {"error": "You're blocking this user."}, 403
|
||||
if hasattr(user, 'is_blocking') and user.is_blocking: abort(403, "You're blocking this user.")
|
||||
|
||||
if v.admin_level <= 1 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()
|
||||
|
||||
if not message: return {"error": "Message is empty!"}
|
||||
if not message: abort(400, "Message is empty!")
|
||||
|
||||
body_html = sanitize(message)
|
||||
|
||||
|
@ -557,7 +557,7 @@ def message2(v, username):
|
|||
Comment.body_html == body_html,
|
||||
).one_or_none()
|
||||
|
||||
if existing: return {"error": "Message already exists."}, 403
|
||||
if existing: abort(403, "Message already exists.")
|
||||
|
||||
c = Comment(author_id=v.id,
|
||||
parent_submission=None,
|
||||
|
@ -595,7 +595,7 @@ def messagereply(v):
|
|||
|
||||
message = request.values.get("body", "").strip()[:10000].strip()
|
||||
|
||||
if not message and not request.files.get("file"): return {"error": "Message is empty!"}
|
||||
if not message and not request.files.get("file"): abort(400, "Message is empty!")
|
||||
|
||||
id = int(request.values.get("parent_id"))
|
||||
parent = get_comment(id, v=v)
|
||||
|
@ -617,15 +617,15 @@ def messagereply(v):
|
|||
file.save("video.mp4")
|
||||
with open("video.mp4", 'rb') as f:
|
||||
try: req = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)], timeout=5).json()['data']
|
||||
except requests.Timeout: return {"error": "Video upload timed out, please try again!"}
|
||||
except requests.Timeout: abort(500, "Video upload timed out, please try again!")
|
||||
try: url = req['link']
|
||||
except:
|
||||
error = req['error']
|
||||
if error == 'File exceeds max duration': error += ' (60 seconds)'
|
||||
return {"error": error}, 400
|
||||
abort(400, error)
|
||||
if url.endswith('.'): url += 'mp4'
|
||||
body_html += f"<p>{url}</p>"
|
||||
else: return {"error": "Image/Video files only"}, 400
|
||||
else: abort(400, "Image/Video files only")
|
||||
|
||||
|
||||
c = Comment(author_id=v.id,
|
||||
|
@ -781,7 +781,7 @@ def u_username(username, v=None):
|
|||
return redirect(SITE_FULL + request.full_path.replace(username, u.username)[:-1])
|
||||
|
||||
if u.reserved:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": f"That username is reserved for: {u.reserved}"}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, f"That username is reserved for: {u.reserved}")
|
||||
return render_template("userpage_reserved.html", u=u, v=v)
|
||||
|
||||
if v and v.id != u.id and (u.patron or u.admin_level > 1):
|
||||
|
@ -795,17 +795,17 @@ def u_username(username, v=None):
|
|||
|
||||
|
||||
if u.is_private and (not v or (v.id != u.id and v.admin_level < 2)):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "That userpage is private"}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, "That userpage is private")
|
||||
return render_template("userpage_private.html", u=u, v=v)
|
||||
|
||||
|
||||
if v and hasattr(u, 'is_blocking') and u.is_blocking:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": f"You are blocking @{u.username}."}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, f"You are blocking @{u.username}.")
|
||||
return render_template("userpage_blocking.html", u=u, v=v)
|
||||
|
||||
|
||||
if v and v.admin_level < 2 and hasattr(u, 'is_blocked') and u.is_blocked:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "This person is blocking you."}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, "This person is blocking you.")
|
||||
return render_template("userpage_blocked.html", u=u, v=v)
|
||||
|
||||
|
||||
|
@ -866,22 +866,22 @@ def u_username_comments(username, v=None):
|
|||
u = user
|
||||
|
||||
if u.reserved:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": f"That username is reserved for: {u.reserved}"}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, f"That username is reserved for: {u.reserved}")
|
||||
return render_template("userpage_reserved.html",
|
||||
u=u,
|
||||
v=v)
|
||||
|
||||
|
||||
if u.is_private and (not v or (v.id != u.id and v.admin_level < 2)):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "That userpage is private"}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, "That userpage is private")
|
||||
return render_template("userpage_private.html", u=u, v=v)
|
||||
|
||||
if v and hasattr(u, 'is_blocking') and u.is_blocking:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": f"You are blocking @{u.username}."}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, f"You are blocking @{u.username}.")
|
||||
return render_template("userpage_blocking.html", u=u, v=v)
|
||||
|
||||
if v and v.admin_level < 2 and hasattr(u, 'is_blocked') and u.is_blocked:
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "This person is blocking you."}
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): abort(403, "This person is blocking you.")
|
||||
return render_template("userpage_blocked.html", u=u, v=v)
|
||||
|
||||
|
||||
|
@ -949,9 +949,9 @@ def u_username_info(username, v=None):
|
|||
user=get_user(username, v=v)
|
||||
|
||||
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:
|
||||
return {"error": "This user is blocking you."}, 403
|
||||
abort(403, "This user is blocking you.")
|
||||
|
||||
return user.json
|
||||
|
||||
|
@ -962,9 +962,9 @@ def u_user_id_info(id, v=None):
|
|||
user=get_account(id, v=v)
|
||||
|
||||
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:
|
||||
return {"error": "This user is blocking you."}, 403
|
||||
abort(403, "This user is blocking you.")
|
||||
|
||||
return user.json
|
||||
|
||||
|
@ -975,7 +975,7 @@ def follow_user(username, v):
|
|||
|
||||
target = get_user(username)
|
||||
|
||||
if target.id==v.id: return {"error": "You can't follow yourself!"}, 400
|
||||
if target.id==v.id: abort(400, "You can't follow yourself!")
|
||||
|
||||
if g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none(): return {"message": "User followed!"}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ def api_vote_post(post_id, new, v):
|
|||
if request.headers.get("Authorization"): abort(403)
|
||||
|
||||
# make sure new is valid
|
||||
if new == "-1" and environ.get('DISABLE_DOWNVOTES') == '1': return {"error": "forbidden."}, 403
|
||||
if new == "-1" and environ.get('DISABLE_DOWNVOTES') == '1': abort(403, "forbidden.")
|
||||
if new not in ["-1", "0", "1"]: abort(400)
|
||||
new = int(new)
|
||||
|
||||
|
@ -128,7 +128,7 @@ def api_vote_comment(comment_id, new, v):
|
|||
if request.headers.get("Authorization"): abort(403)
|
||||
|
||||
# make sure new is valid
|
||||
if new == "-1" and environ.get('DISABLE_DOWNVOTES') == '1': return {"error": "forbidden."}, 403
|
||||
if new == "-1" and environ.get('DISABLE_DOWNVOTES') == '1': abort(403, "forbidden.")
|
||||
if new not in ["-1", "0", "1"]: abort(400)
|
||||
new = int(new)
|
||||
|
||||
|
|
|
@ -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">
|
||||
<h1>400</h1>
|
||||
<h5>Bad Request</h5>
|
||||
<p class="text-muted mb-5">That request was bad and you should feel bad</p>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,21 +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">
|
||||
<h1>401</h1>
|
||||
<h5>Not Authorized</h5>
|
||||
<p class="text-muted mb-5">You need an account for this. Please make one!</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 %}
|
|
@ -1,20 +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">
|
||||
<h1>404</h1>
|
||||
<h5>Page Not Found</h5>
|
||||
<p class="text-muted mb-5">That page doesn't exist. If you got here from a link on the website, please report this issue. Thanks!</p>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,20 +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">
|
||||
<h1>405</h1>
|
||||
<h5>Method Not Allowed</h5>
|
||||
<p class="text-muted mb-5">Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!</p>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,20 +0,0 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>Max file size is 8 MB</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">
|
||||
<h1>413</h1>
|
||||
<h5>Payload Too Large</h5>
|
||||
<p class="text-muted mb-5">Max file size is 8 MB</p>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,19 +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">
|
||||
<h1>429</h1>
|
||||
<h5>Too Many Requests</h5>
|
||||
<p class="text-muted mb-5">Are you hammering the site? Stop that, yo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,20 +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">
|
||||
<h1>500</h1>
|
||||
<h5>Internal Server Error</h5>
|
||||
<p class="text-muted mb-5">Something went wrong and it's probably my fault. If you can do it reliably, or it's causing problems for you, please report it!</p>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,18 +1,18 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>403 Forbidden</title>
|
||||
<title>{{code}} {{error}}</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block pagetype %}error-403{% 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">
|
||||
<h1>403</h1>
|
||||
<h5>Forbidden</h5>
|
||||
<h1>{{code}}</h1>
|
||||
<h5>{{error}}</h5>
|
||||
<p class="text-muted mb-5">{{description}}</p>
|
||||
{% if details -%}
|
||||
<blockquote class="error-details mb-5 py-2">{{details|safe}}</blockquote>
|
||||
{%- endif %}
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue