From ff67e30949d6bc54fa8bb07c1dfb09eaeae51423 Mon Sep 17 00:00:00 2001 From: Aevann Date: Thu, 13 Jul 2023 16:50:46 +0300 Subject: [PATCH] dont count failed requests towards ratelimit --- files/__main__.py | 1 + files/routes/admin.py | 232 +++++++++++++++--------------- files/routes/asset_submissions.py | 48 +++---- files/routes/awards.py | 16 +-- files/routes/casino.py | 48 +++---- files/routes/chat.py | 8 +- files/routes/comments.py | 38 ++--- files/routes/errors.py | 2 +- files/routes/feeds.py | 2 +- files/routes/front.py | 14 +- files/routes/giphy.py | 4 +- files/routes/groups.py | 28 ++-- files/routes/hats.py | 20 +-- files/routes/login.py | 41 ++---- files/routes/lottery.py | 16 +-- files/routes/mail.py | 8 +- files/routes/notifications.py | 32 ++--- files/routes/oauth.py | 52 +++---- files/routes/polls.py | 16 +-- files/routes/posts.py | 66 ++++----- files/routes/push_notifs.py | 4 +- files/routes/reporting.py | 16 +-- files/routes/search.py | 16 +-- files/routes/settings.py | 120 ++++++++-------- files/routes/special.py | 4 +- files/routes/static.py | 86 +++++------ files/routes/subs.py | 138 +++++++++--------- files/routes/users.py | 202 +++++++++++++------------- files/routes/votes.py | 12 +- 29 files changed, 640 insertions(+), 650 deletions(-) diff --git a/files/__main__.py b/files/__main__.py index 0fe0b861a..d13cbbe8f 100644 --- a/files/__main__.py +++ b/files/__main__.py @@ -65,6 +65,7 @@ limiter = Limiter( default_limits=[DEFAULT_RATELIMIT], application_limits=["10/second;200/minute;5000/hour;10000/day"], storage_uri=app.config["CACHE_REDIS_URL"], + default_limits_deduct_when=lambda response: response.status_code < 400, ) const_initialize() diff --git a/files/routes/admin.py b/files/routes/admin.py index 8b8ccd156..7a487231a 100644 --- a/files/routes/admin.py +++ b/files/routes/admin.py @@ -27,8 +27,8 @@ from files.routes.routehelpers import get_alt_graph, get_alt_graph_ids from .front import frontlist, comment_idlist @app.get('/admin/loggedin') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['VIEW_ACTIVE_USERS']) def loggedin_list(v): ids = [x for x,val in cache.get('loggedin').items() if time.time()-val < LOGGEDIN_ACTIVE_TIME] @@ -36,16 +36,16 @@ def loggedin_list(v): return render_template("admin/loggedin.html", v=v, users=users) @app.get('/admin/loggedout') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['VIEW_ACTIVE_USERS']) def loggedout_list(v): users = sorted([val[1] for x,val in cache.get('loggedout').items() if time.time()-val[0] < LOGGEDIN_ACTIVE_TIME]) return render_template("admin/loggedout.html", v=v, users=users) @app.get('/admin/dm_media') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['ENABLE_DM_MEDIA']) def dm_media(v): with open(f"{LOG_DIRECTORY}/dm_media.log", "r", encoding="utf-8") as f: @@ -65,8 +65,8 @@ def dm_media(v): return render_template("admin/dm_media.html", v=v, items=items, total=total, page=page) @app.get('/admin/edit_rules') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['EDIT_RULES']) def edit_rules_get(v): try: @@ -80,8 +80,8 @@ def edit_rules_get(v): @app.post('/admin/edit_rules') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("30/minute;200/hour;1000/day") -@limiter.limit("30/minute;200/hour;1000/day", key_func=get_ID) +@limiter.limit("30/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("30/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['EDIT_RULES']) def edit_rules_post(v): rules = request.values.get('rules', '').strip() @@ -100,8 +100,8 @@ def edit_rules_post(v): @app.post("/@/make_admin") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['ADMIN_ADD']) def make_admin(v:User, username): user = get_user(username) @@ -124,8 +124,8 @@ def make_admin(v:User, username): @app.post("/@/remove_admin") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['ADMIN_REMOVE']) def remove_admin(v:User, username): if SITE == 'devrama.net': @@ -154,8 +154,8 @@ def remove_admin(v:User, username): @app.post("/distribute//") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_BETS_DISTRIBUTE']) def distribute(v:User, kind, option_id): autojanny = get_account(AUTOJANNY_ID) @@ -224,8 +224,8 @@ def distribute(v:User, kind, option_id): @app.post("/@/revert_actions") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['ADMIN_ACTIONS_REVERT']) def revert_actions(v:User, username): revertee = get_user(username) @@ -278,8 +278,8 @@ def revert_actions(v:User, username): return {"message": f"@{revertee.username}'s admin actions have been reverted!"} @app.get("/admin/shadowbanned") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_SHADOWBAN']) def shadowbanned(v): users = g.db.query(User).filter( @@ -301,8 +301,8 @@ def shadowbanned(v): @app.get("/admin/image_posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def image_posts_listing(v): @@ -327,8 +327,8 @@ def image_posts_listing(v): @app.get("/admin/reported/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def reported_posts(v): page = get_page() @@ -350,8 +350,8 @@ def reported_posts(v): @app.get("/admin/reported/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def reported_comments(v): page = get_page() @@ -376,8 +376,8 @@ def reported_comments(v): standalone=True) @app.get("/admin") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['ADMIN_HOME_VISIBLE']) def admin_home(v): return render_template("admin/admin_home.html", v=v) @@ -385,8 +385,8 @@ def admin_home(v): @app.post("/admin/site_settings/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['SITE_SETTINGS']) def change_settings(v:User, setting): if setting not in get_settings().keys(): @@ -415,8 +415,8 @@ def change_settings(v:User, setting): @app.post("/admin/clear_cloudflare_cache") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['SITE_CACHE_PURGE_CDN']) def clear_cloudflare_cache(v): if not clear_entire_cache(): @@ -440,8 +440,8 @@ def admin_badges_grantable_list(v): @app.get("/admin/badge_grant") @app.get("/admin/badge_remove") @feature_required('BADGES') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BADGES']) def badge_grant_get(v): grant = request.url.endswith("grant") @@ -454,8 +454,8 @@ def badge_grant_get(v): @feature_required('BADGES') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BADGES']) def badge_grant_post(v): badges = admin_badges_grantable_list(v) @@ -526,8 +526,8 @@ def badge_grant_post(v): @feature_required('BADGES') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BADGES']) def badge_remove_post(v): badges = admin_badges_grantable_list(v) @@ -562,8 +562,8 @@ def badge_remove_post(v): @app.get("/admin/alt_votes") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['VIEW_ALT_VOTES']) def alt_votes_get(v): u1 = request.values.get("u1") @@ -669,8 +669,8 @@ def alt_votes_get(v): @app.get("/admin/alts/") @app.get("/@/alts/") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_LINK']) def admin_view_alts(v:User, username=None): u = get_user(username or request.values.get('username'), graceful=True) @@ -679,8 +679,8 @@ def admin_view_alts(v:User, username=None): @app.post('/@/alts/') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_LINK']) def admin_add_alt(v:User, username): user1 = get_user(username) @@ -716,8 +716,8 @@ def admin_add_alt(v:User, username): @app.post('/@/alts//deleted') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_LINK']) def admin_delink_relink_alt(v:User, username, other): user1 = get_user(username) @@ -745,8 +745,8 @@ def admin_delink_relink_alt(v:User, username, other): @app.get("/admin/removed/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def admin_removed(v): page = get_page() @@ -769,8 +769,8 @@ def admin_removed(v): @app.get("/admin/removed/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def admin_removed_comments(v): page = get_page() @@ -795,8 +795,8 @@ def admin_removed_comments(v): @app.post("/unchud_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_CHUD']) def unchud(fullname, v): @@ -838,8 +838,8 @@ def unchud(fullname, v): @app.post("/shadowban/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_SHADOWBAN']) def shadowban(user_id, v): user = get_account(user_id) @@ -875,8 +875,8 @@ def shadowban(user_id, v): @app.post("/unshadowban/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_SHADOWBAN']) def unshadowban(user_id, v): user = get_account(user_id) @@ -904,8 +904,8 @@ def unshadowban(user_id, v): @app.post("/admin/title_change/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_TITLE_CHANGE']) def admin_title_change(user_id, v): @@ -952,8 +952,8 @@ def admin_title_change(user_id, v): @app.post("/ban_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BAN']) def ban_user(fullname, v): @@ -1047,8 +1047,8 @@ def ban_user(fullname, v): @app.post("/chud_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_CHUD']) def chud(fullname, v): @@ -1152,8 +1152,8 @@ def chud(fullname, v): @app.post("/unban_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BAN']) def unban_user(fullname, v): @@ -1201,8 +1201,8 @@ def unban_user(fullname, v): @app.post("/mute_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BAN']) def mute_user(v:User, user_id): user = get_account(user_id) @@ -1224,8 +1224,8 @@ def mute_user(v:User, user_id): @app.post("/unmute_user/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BAN']) def unmute_user(v:User, user_id): user = get_account(user_id) @@ -1245,8 +1245,8 @@ def unmute_user(v:User, user_id): @app.post("/admin/progstack/post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['PROGSTACK']) def progstack_post(post_id, v): post = get_post(post_id) @@ -1267,8 +1267,8 @@ def progstack_post(post_id, v): @app.post("/admin/unprogstack/post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['PROGSTACK']) def unprogstack_post(post_id, v): post = get_post(post_id) @@ -1287,8 +1287,8 @@ def unprogstack_post(post_id, v): @app.post("/admin/progstack/comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['PROGSTACK']) def progstack_comment(comment_id, v): comment = get_comment(comment_id) @@ -1309,8 +1309,8 @@ def progstack_comment(comment_id, v): @app.post("/admin/unprogstack/comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['PROGSTACK']) def unprogstack_comment(comment_id, v): comment = get_comment(comment_id) @@ -1329,8 +1329,8 @@ def unprogstack_comment(comment_id, v): @app.post("/remove_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def remove_post(post_id, v): post = get_post(post_id) @@ -1360,8 +1360,8 @@ def remove_post(post_id, v): @app.post("/approve_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def approve_post(post_id, v): post = get_post(post_id) @@ -1394,8 +1394,8 @@ def approve_post(post_id, v): @app.post("/distinguish/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_DISTINGUISH']) def distinguish_post(post_id, v): post = get_post(post_id) @@ -1425,8 +1425,8 @@ def distinguish_post(post_id, v): @feature_required('PINS') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def sticky_post(post_id, v): post = get_post(post_id) @@ -1472,8 +1472,8 @@ def sticky_post(post_id, v): @app.post("/unsticky/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def unsticky_post(post_id, v): post = get_post(post_id) @@ -1504,8 +1504,8 @@ def unsticky_post(post_id, v): @app.post("/sticky_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def sticky_comment(cid, v): comment = get_comment(cid, v=v) @@ -1543,8 +1543,8 @@ def sticky_comment(cid, v): @app.post("/unsticky_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def unsticky_comment(cid, v): comment = get_comment(cid, v=v) @@ -1578,8 +1578,8 @@ def unsticky_comment(cid, v): @app.post("/remove_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def remove_comment(c_id, v): comment = get_comment(c_id) @@ -1601,8 +1601,8 @@ def remove_comment(c_id, v): @app.post("/approve_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def approve_comment(c_id, v): comment = get_comment(c_id) @@ -1630,8 +1630,8 @@ def approve_comment(c_id, v): @app.post("/distinguish_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_DISTINGUISH']) def admin_distinguish_comment(c_id, v): comment = get_comment(c_id, v=v) @@ -1657,8 +1657,8 @@ def admin_distinguish_comment(c_id, v): else: return {"message": "Comment undistinguished!"} @app.get("/admin/banned_domains/") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['DOMAINS_BAN']) def admin_banned_domains(v): banned_domains = g.db.query(BannedDomain) \ @@ -1669,8 +1669,8 @@ def admin_banned_domains(v): @app.post("/admin/ban_domain") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['DOMAINS_BAN']) def ban_domain(v): @@ -1703,8 +1703,8 @@ def ban_domain(v): @app.post("/admin/unban_domain/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['DOMAINS_BAN']) def unban_domain(v:User, domain): existing = g.db.get(BannedDomain, domain) @@ -1725,8 +1725,8 @@ def unban_domain(v:User, domain): @app.post("/admin/nuke_user") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def admin_nuke_user(v): @@ -1761,8 +1761,8 @@ def admin_nuke_user(v): @app.post("/admin/unnuke_user") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def admin_nunuke_user(v): @@ -1798,8 +1798,8 @@ def admin_nunuke_user(v): @app.post("/blacklist/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BLACKLIST']) def blacklist_user(user_id, v): user = get_account(user_id) @@ -1821,8 +1821,8 @@ def blacklist_user(user_id, v): @app.post("/unblacklist/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BLACKLIST']) def unblacklist_user(user_id, v): user = get_account(user_id) @@ -1843,8 +1843,8 @@ def unblacklist_user(user_id, v): return {"message": f"@{user.username} has been unblacklisted from restricted holes!"} @app.get('/admin/delete_media') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['DELETE_MEDIA']) def delete_media_get(v): return render_template("admin/delete_media.html", v=v) @@ -1852,8 +1852,8 @@ def delete_media_get(v): @app.post("/admin/delete_media") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("50/day") -@limiter.limit("50/day", key_func=get_ID) +@limiter.limit("50/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("50/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['DELETE_MEDIA']) def delete_media_post(v): @@ -1887,8 +1887,8 @@ def delete_media_post(v): @app.post("/admin/reset_password/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_RESET_PASSWORD']) def admin_reset_password(user_id, v): user = get_account(user_id) diff --git a/files/routes/asset_submissions.py b/files/routes/asset_submissions.py index c53533bf5..b710731d2 100644 --- a/files/routes/asset_submissions.py +++ b/files/routes/asset_submissions.py @@ -19,8 +19,8 @@ def submit_marseys_redirect(): return redirect("/submit/emojis") @app.get("/submit/emojis") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_emojis(v:User): if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_EMOJIS']: @@ -40,8 +40,8 @@ def submit_emojis(v:User): @app.post("/submit/emojis") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_emoji(v:User): file = request.files["image"] @@ -119,8 +119,8 @@ def verify_permissions_and_get_asset(cls, asset_type:str, v:User, name:str, make @app.post("/admin/approve/emoji/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']) def approve_emoji(v, name): emoji = verify_permissions_and_get_asset(Emoji, "emoji", v, name, True) @@ -259,15 +259,15 @@ def remove_asset(cls, type_name:str, v:User, name:str) -> dict[str, str]: @app.post("/remove/emoji/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def remove_emoji(v:User, name): return remove_asset(Emoji, "emoji", v, name) @app.get("/submit/hats") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_hats(v:User): if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = g.db.query(HatDef).filter(HatDef.submitter_id != None) @@ -280,8 +280,8 @@ def submit_hats(v:User): @app.post("/submit/hats") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_hat(v:User): name = request.values.get('name', '').strip() @@ -339,8 +339,8 @@ def submit_hat(v:User): @app.post("/admin/approve/hat/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("120/minute;200/hour;1000/day") -@limiter.limit("120/minute;200/hour;1000/day", key_func=get_ID) +@limiter.limit("120/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("120/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']) def approve_hat(v, name): hat = verify_permissions_and_get_asset(HatDef, "hat", v, name, False) @@ -412,15 +412,15 @@ def approve_hat(v, name): @app.post("/remove/hat/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def remove_hat(v:User, name): return remove_asset(HatDef, 'hat', v, name) @app.get("/admin/update/emojis") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['UPDATE_ASSETS']) def update_emojis(v): return render_template("admin/update_assets.html", v=v, type="Emoji") @@ -429,8 +429,8 @@ def update_emojis(v): @app.post("/admin/update/emojis") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['UPDATE_ASSETS']) def update_emoji(v): file = request.files["image"] @@ -501,8 +501,8 @@ def update_emoji(v): return render_template("admin/update_assets.html", v=v, msg=f"'{name}' updated successfully!", name=name, tags=tags, kind=kind, type="Emoji") @app.get("/admin/update/hats") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['UPDATE_ASSETS']) def update_hats(v): return render_template("admin/update_assets.html", v=v, type="Hat") @@ -511,8 +511,8 @@ def update_hats(v): @app.post("/admin/update/hats") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['UPDATE_ASSETS']) def update_hat(v): file = request.files["image"] diff --git a/files/routes/awards.py b/files/routes/awards.py index 612057c5f..d720ceadf 100644 --- a/files/routes/awards.py +++ b/files/routes/awards.py @@ -23,15 +23,15 @@ from files.__main__ import app, cache, limiter from .front import frontlist @app.get("/shop") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def shop_awards(v:User): return redirect('/shop/awards') @app.get("/shop/awards") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def shop(v:User): AWARDS = deepcopy(AWARDS_ENABLED) @@ -57,8 +57,8 @@ def shop(v:User): @app.post("/buy/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("100/minute;200/hour;1000/day") -@limiter.limit("100/minute;200/hour;1000/day", key_func=get_ID) +@limiter.limit("100/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("100/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def buy(v:User, award): if award == 'ghost': @@ -137,8 +137,8 @@ def buy(v:User, award): @app.post("/award//") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def award_thing(v, thing_type, id): kind = request.values.get("kind", "").strip() diff --git a/files/routes/casino.py b/files/routes/casino.py index 4fcd5d8ad..8ba66eb01 100644 --- a/files/routes/casino.py +++ b/files/routes/casino.py @@ -12,8 +12,8 @@ from files.routes.wrappers import * from files.__main__ import app, limiter @app.get("/casino") -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def casino(v:User): if v.rehab: @@ -23,8 +23,8 @@ def casino(v:User): @app.get("/casino/") -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def casino_game_page(v:User, game): if v.rehab: @@ -53,8 +53,8 @@ def casino_game_page(v:User, game): @app.get("/casino//feed") -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def casino_game_feed(v:User, game): if v.rehab: @@ -68,8 +68,8 @@ def casino_game_feed(v:User, game): # Lottershe @app.get("/lottershe") -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def lottershe(v:User): if v.rehab: @@ -82,8 +82,8 @@ def lottershe(v:User): @app.post("/casino/slots") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def pull_slots(v:User): if v.rehab: @@ -116,8 +116,8 @@ def pull_slots(v:User): @app.post("/casino/twentyone/deal") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blackjack_deal_to_player(v:User): if v.rehab: @@ -138,8 +138,8 @@ def blackjack_deal_to_player(v:User): @app.post("/casino/twentyone/hit") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blackjack_player_hit(v:User): if v.rehab: @@ -156,8 +156,8 @@ def blackjack_player_hit(v:User): @app.post("/casino/twentyone/stay") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blackjack_player_stay(v:User): if v.rehab: @@ -174,8 +174,8 @@ def blackjack_player_stay(v:User): @app.post("/casino/twentyone/double-down") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blackjack_player_doubled_down(v:User): if v.rehab: @@ -192,8 +192,8 @@ def blackjack_player_doubled_down(v:User): @app.post("/casino/twentyone/buy-insurance") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blackjack_player_bought_insurance(v:User): if v.rehab: @@ -208,8 +208,8 @@ def blackjack_player_bought_insurance(v:User): # Roulette @app.get("/casino/roulette/bets") -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def roulette_get_bets(v:User): if v.rehab: @@ -223,8 +223,8 @@ def roulette_get_bets(v:User): @app.post("/casino/roulette/place-bet") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(CASINO_RATELIMIT) -@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(CASINO_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def roulette_player_placed_bet(v:User): if v.rehab: diff --git a/files/routes/chat.py b/files/routes/chat.py index b15e0cfe6..4a2c8d24c 100644 --- a/files/routes/chat.py +++ b/files/routes/chat.py @@ -30,8 +30,8 @@ muted = cache.get(f'muted') or {} messages = cache.get(f'messages') or {} @app.get("/chat") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def chat(v): if not v.admin_level and TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM: @@ -43,8 +43,8 @@ def chat(v): return render_template("chat.html", v=v, messages=messages) @app.get("/old_chat") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def old_chat(v): if not v.admin_level and TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM: diff --git a/files/routes/comments.py b/files/routes/comments.py index ab5c1785c..b37b8bd6d 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -27,7 +27,7 @@ from files.__main__ import app, cache, limiter @app.get("/post///") @app.get("/h//comment/") @app.get("/h//post///") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired_with_logingate def post_pid_comment_cid(cid, v, pid=None, anything=None, sub=None): @@ -84,8 +84,8 @@ def post_pid_comment_cid(cid, v, pid=None, anything=None, sub=None): @app.post("/comment") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("20/minute;200/hour;1000/day") -@limiter.limit("20/minute;200/hour;1000/day", key_func=get_ID) +@limiter.limit("20/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("20/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def comment(v:User): if v.is_suspended: abort(403, "You can't perform this action while banned!") @@ -401,8 +401,8 @@ def comment(v:User): @app.post("/delete/comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def delete_comment(cid, v): if v.id == 253: abort(403) @@ -424,8 +424,8 @@ def delete_comment(cid, v): @app.post("/undelete/comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def undelete_comment(cid, v): c = get_comment(cid, v=v) @@ -446,8 +446,8 @@ def undelete_comment(cid, v): @feature_required('PINS') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def pin_comment(cid, v): @@ -472,8 +472,8 @@ def pin_comment(cid, v): @app.post("/unpin_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unpin_comment(cid, v): @@ -497,8 +497,8 @@ def unpin_comment(cid, v): @app.post("/save_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def save_comment(cid, v): @@ -516,8 +516,8 @@ def save_comment(cid, v): @app.post("/unsave_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unsave_comment(cid, v): @@ -555,8 +555,8 @@ def diff_words(answer, guess): @feature_required('NSFW_MARKING') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def toggle_comment_nsfw(cid, v): comment = get_comment(cid) @@ -593,8 +593,8 @@ def toggle_comment_nsfw(cid, v): @app.post("/edit_comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/minute;100/hour;200/day") -@limiter.limit("10/minute;100/hour;200/day", key_func=get_ID) +@limiter.limit("10/minute;100/hour;200/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/minute;100/hour;200/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def edit_comment(cid, v): c = get_comment(cid, v=v) diff --git a/files/routes/errors.py b/files/routes/errors.py index 21f38641c..1e483d893 100644 --- a/files/routes/errors.py +++ b/files/routes/errors.py @@ -62,7 +62,7 @@ def error_500(e): @app.post("/allow_nsfw") @limiter.limit('1/second', scope=rpath) -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def allow_nsfw(): session["over_18_cookies"] = int(time.time()) + 3600 redir = request.values.get("redir", "/") diff --git a/files/routes/feeds.py b/files/routes/feeds.py index 1c9af1b55..ca391c7a7 100644 --- a/files/routes/feeds.py +++ b/files/routes/feeds.py @@ -11,7 +11,7 @@ from files.__main__ import app @app.get('/rss') @app.get('/feed') @app.get('/rss//') -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def feeds_user(sort='hot', t='all'): page = get_page() diff --git a/files/routes/front.py b/files/routes/front.py index acbbae997..353a5e9d2 100644 --- a/files/routes/front.py +++ b/files/routes/front.py @@ -13,7 +13,7 @@ from files.__main__ import app, cache, limiter, redis_instance @app.get("/") @app.get("/h/") -@limiter.limit("30/minute;5000/hour;10000/day") +@limiter.limit("30/minute;5000/hour;10000/day", deduct_when=lambda response: response.status_code < 400) @auth_desired_with_logingate def front_all(v, sub=None): if sub: @@ -175,8 +175,8 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words=' @app.get("/random_post") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def random_post(v:User): @@ -189,8 +189,8 @@ def random_post(v:User): @app.get("/random_user") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def random_user(v:User): u = g.db.query(User.username).filter(User.song != None).order_by(func.random()).first() @@ -230,8 +230,8 @@ def comment_idlist(v=None, page=1, sort="new", t="day", gt=0, lt=0): return [x.id for x in comments], total @app.get("/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def all_comments(v:User): page = get_page() diff --git a/files/routes/giphy.py b/files/routes/giphy.py index 2f80d4fd2..7e70b5540 100644 --- a/files/routes/giphy.py +++ b/files/routes/giphy.py @@ -7,8 +7,8 @@ from files.__main__ import app @app.get("/giphy") @app.get("/giphy") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def giphy(v, path=None): diff --git a/files/routes/groups.py b/files/routes/groups.py index 55787dca9..f2342be1c 100644 --- a/files/routes/groups.py +++ b/files/routes/groups.py @@ -8,8 +8,8 @@ from files.routes.wrappers import * from files.__main__ import app, limiter @app.get("/ping_groups") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def ping_groups(v:User): groups = g.db.query(Group).order_by(Group.created_utc).all() @@ -18,8 +18,8 @@ def ping_groups(v:User): @app.post("/create_group") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def create_group(v): name = request.values.get('name') @@ -62,8 +62,8 @@ def create_group(v): @app.post("/!/apply") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def join_group(v:User, group_name): group_name = group_name.strip().lower() @@ -81,8 +81,8 @@ def join_group(v:User, group_name): @app.post("/!/leave") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def leave_group(v:User, group_name): group_name = group_name.strip().lower() @@ -110,8 +110,8 @@ def leave_group(v:User, group_name): @app.get("/!") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def memberships(v:User, group_name): group_name = group_name.strip().lower() @@ -134,8 +134,8 @@ def memberships(v:User, group_name): @app.post("/!//approve") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def group_approve(v:User, group_name, user_id): group_name = group_name.strip().lower() @@ -160,8 +160,8 @@ def group_approve(v:User, group_name, user_id): @app.post("/!//reject") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def group_reject(v:User, group_name, user_id): group_name = group_name.strip().lower() diff --git a/files/routes/hats.py b/files/routes/hats.py index 6608798ba..876a34e7a 100644 --- a/files/routes/hats.py +++ b/files/routes/hats.py @@ -8,8 +8,8 @@ from files.routes.wrappers import * from files.__main__ import app, limiter @app.get("/shop/hats") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def hats(v:User): owned_hat_ids = [x.hat_id for x in v.owned_hats] @@ -70,8 +70,8 @@ def hats(v:User): @app.post("/buy_hat/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit('100/minute;1000/3 days') -@limiter.limit('100/minute;1000/3 days', key_func=get_ID) +@limiter.limit('100/minute;1000/3 days', deduct_when=lambda response: response.status_code < 400) +@limiter.limit('100/minute;1000/3 days', deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def buy_hat(v:User, hat_id): try: hat_id = int(hat_id) @@ -117,8 +117,8 @@ def buy_hat(v:User, hat_id): @app.post("/equip_hat/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def equip_hat(v:User, hat_id): try: hat_id = int(hat_id) @@ -135,8 +135,8 @@ def equip_hat(v:User, hat_id): @app.post("/unequip_hat/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unequip_hat(v:User, hat_id): try: hat_id = int(hat_id) @@ -151,8 +151,8 @@ def unequip_hat(v:User, hat_id): return {"message": f"'{hat.name}' unequipped!"} @app.get("/hat_owners/") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def hat_owners(v:User, hat_id): try: hat_id = int(hat_id) diff --git a/files/routes/login.py b/files/routes/login.py index c91dc168d..97954c36e 100644 --- a/files/routes/login.py +++ b/files/routes/login.py @@ -21,7 +21,7 @@ from files.routes.wrappers import * NO_LOGIN_REDIRECT_URLS = ("/login", "/logout", "/signup", "/forgot", "/reset", "/reset_2fa", "/lost_2fa") @app.get("/login") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def login_get(v:Optional[User]): redir = request.values.get("redirect", "").strip().rstrip('?').lower() @@ -31,21 +31,12 @@ def login_get(v:Optional[User]): return redirect('/') return render_template("login/login.html", failed=False, redirect=redir), 401 -def login_deduct_when(resp): - if not g: - return False - elif not hasattr(g, 'login_failed'): - return False - return g.login_failed - @app.post("/login") @limiter.limit('1/second', scope=rpath) -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit("6/minute;10/day", deduct_when=lambda response: response.status_code < 400) @auth_desired -@limiter.limit("6/minute;10/day", deduct_when=login_deduct_when) def login_post(v:Optional[User]): if v: abort(400) - g.login_failed = True username = request.values.get("username") @@ -76,7 +67,6 @@ def login_post(v:Optional[User]): if account.mfa_secret or session.get("GLOBAL"): now = int(time.time()) hash = generate_hash(f"{account.id}+{now}+2fachallenge") - g.login_failed = False return render_template("login/login_2fa.html", v=account, time=now, @@ -109,7 +99,6 @@ def login_post(v:Optional[User]): else: abort(400) - g.login_failed = False on_login(account) if redir and is_site_url(redir) and redir not in NO_LOGIN_REDIRECT_URLS: @@ -133,8 +122,8 @@ def on_login(account, redir=None): @app.get("/me") @app.get("/@me") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def me(v:User): if v.client: return v.json @@ -144,8 +133,8 @@ def me(v:User): @app.post("/logout") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def logout(v): loggedin = cache.get('loggedin') or {} @@ -155,7 +144,7 @@ def logout(v): return {"message": "Logout successful!"} @app.get("/signup") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def sign_up_get(v:Optional[User]): if not get_setting('signups'): @@ -204,7 +193,7 @@ def sign_up_get(v:Optional[User]): @app.post("/signup") @limiter.limit('1/second', scope=rpath) -@limiter.limit("10/day") +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400) @auth_desired def sign_up_post(v:Optional[User]): if not get_setting('signups'): @@ -372,14 +361,14 @@ def sign_up_post(v:Optional[User]): @app.get("/forgot") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def get_forgot(): return render_template("login/forgot_password.html") @app.post("/forgot") @limiter.limit('1/second', scope=rpath) -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def post_forgot(): username = request.values.get("username") @@ -415,7 +404,7 @@ def post_forgot(): @app.get("/reset") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def get_reset(): user_id = request.values.get("id") timestamp = 0 @@ -445,7 +434,7 @@ def get_reset(): @app.post("/reset") @limiter.limit('1/second', scope=rpath) -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def post_reset(v:Optional[User]): if v: return redirect('/') @@ -484,7 +473,7 @@ def post_reset(v:Optional[User]): message="Login normally to access your account.") @app.get("/lost_2fa") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def lost_2fa(v:Optional[User]): if v and not v.mfa_secret: abort(400, "You don't have two-factor authentication enabled") @@ -492,7 +481,7 @@ def lost_2fa(v:Optional[User]): @app.post("/lost_2fa") @limiter.limit('1/second', scope=rpath) -@limiter.limit("6/minute;200/hour;1000/day") +@limiter.limit("6/minute;200/hour;1000/day", deduct_when=lambda response: response.status_code < 400) def lost_2fa_post(): username=request.values.get("username") user=get_user(username, graceful=True) @@ -530,7 +519,7 @@ def lost_2fa_post(): message="If the username, password, and email match, we will send you an email. Check your spam folder if you can't find it."), 202 @app.get("/reset_2fa") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def reset_2fa(): now=int(time.time()) t = request.values.get("t") diff --git a/files/routes/lottery.py b/files/routes/lottery.py index 12641e491..f7ac1d944 100644 --- a/files/routes/lottery.py +++ b/files/routes/lottery.py @@ -9,8 +9,8 @@ from files.__main__ import app, limiter @app.post("/lottery/start") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['LOTTERY_ADMIN']) def lottery_start(v): start_new_lottery_session() @@ -20,8 +20,8 @@ def lottery_start(v): @app.post("/lottery/buy") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("100/minute;500/hour;1000/day") -@limiter.limit("100/minute;500/hour;1000/day", key_func=get_ID) +@limiter.limit("100/minute;500/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("100/minute;500/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def lottery_buy(v:User): try: quantity = int(request.values.get("quantity")) @@ -38,8 +38,8 @@ def lottery_buy(v:User): @app.get("/lottery/active") -@limiter.limit("100/minute;500/hour;1000/day") -@limiter.limit("100/minute;500/hour;1000/day", key_func=get_ID) +@limiter.limit("100/minute;500/hour;1000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("100/minute;500/hour;1000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def lottery_active(v:User): lottery, participants = get_active_lottery_stats() @@ -47,8 +47,8 @@ def lottery_active(v:User): return {"message": "", "stats": {"user": v.lottery_stats, "lottery": lottery, "participants": participants}} @app.get("/admin/lottery/participants") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['LOTTERY_VIEW_PARTICIPANTS']) def lottery_admin(v): participants = get_users_participating_in_lottery() diff --git a/files/routes/mail.py b/files/routes/mail.py index 62a1aa16c..92c737ed5 100644 --- a/files/routes/mail.py +++ b/files/routes/mail.py @@ -12,8 +12,8 @@ from files.__main__ import app, limiter @app.post("/verify_email") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def verify_email(v): if v.is_activated: @@ -24,8 +24,8 @@ def verify_email(v): @app.get("/activate") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def activate(v:User): email = request.values.get("email", "").strip().lower() diff --git a/files/routes/notifications.py b/files/routes/notifications.py index abe976744..685042b64 100644 --- a/files/routes/notifications.py +++ b/files/routes/notifications.py @@ -14,8 +14,8 @@ from files.__main__ import app @app.post("/clear") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def clear(v): notifs = g.db.query(Notification).join(Notification.comment).filter( @@ -35,8 +35,8 @@ def clear(v): @app.get("/unread") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unread(v): listing = g.db.query(Notification, Comment).join(Notification.comment).filter( @@ -54,8 +54,8 @@ def unread(v): @app.get("/notifications/modmail") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['VIEW_MODMAIL']) def notifications_modmail(v): page = get_page() @@ -84,8 +84,8 @@ def notifications_modmail(v): @app.get("/notifications/messages") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def notifications_messages(v:User): page = get_page() @@ -159,8 +159,8 @@ def notifications_messages(v:User): @app.get("/notifications/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def notifications_posts(v:User): page = get_page() @@ -206,8 +206,8 @@ def notifications_posts(v:User): @app.get("/notifications/modactions") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def notifications_modactions(v:User): page = get_page() @@ -253,8 +253,8 @@ def notifications_modactions(v:User): @app.get("/notifications/reddit") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def notifications_reddit(v:User): page = get_page() @@ -292,8 +292,8 @@ def notifications_reddit(v:User): @app.get("/notifications") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def notifications(v:User): page = get_page() diff --git a/files/routes/oauth.py b/files/routes/oauth.py index dd9371444..fc290cf94 100644 --- a/files/routes/oauth.py +++ b/files/routes/oauth.py @@ -8,8 +8,8 @@ from files.routes.wrappers import * from files.__main__ import app, limiter @app.get("/authorize") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def authorize_prompt(v:User): client_id = request.values.get("client_id") @@ -20,8 +20,8 @@ def authorize_prompt(v:User): @app.post("/authorize") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def authorize(v): client_id = request.values.get("client_id") @@ -42,8 +42,8 @@ def authorize(v): @app.post("/rescind/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def rescind(v, aid): @@ -56,8 +56,8 @@ def rescind(v, aid): @app.post("/api_keys") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def request_api_keys(v): new_app = OauthApp( @@ -99,8 +99,8 @@ def request_api_keys(v): @app.post("/delete_app/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def delete_oauth_app(v, aid): try: @@ -124,8 +124,8 @@ def delete_oauth_app(v, aid): @app.post("/edit_app/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def edit_oauth_app(v, aid): try: @@ -150,8 +150,8 @@ def edit_oauth_app(v, aid): @app.post("/admin/app/approve/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_app_approve(v, aid): @@ -189,8 +189,8 @@ def admin_app_approve(v, aid): @app.post("/admin/app/revoke/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_app_revoke(v, aid): @@ -217,8 +217,8 @@ def admin_app_revoke(v, aid): @app.post("/admin/app/reject/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_app_reject(v, aid): @@ -244,8 +244,8 @@ def admin_app_reject(v, aid): @app.get("/admin/app//posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_app_id_posts(v, aid): oauth = g.db.get(OauthApp, aid) @@ -265,8 +265,8 @@ def admin_app_id_posts(v, aid): ) @app.get("/admin/app//comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_app_id_comments(v, aid): @@ -290,8 +290,8 @@ def admin_app_id_comments(v, aid): @app.get("/admin/apps") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['APPS_MODERATION']) def admin_apps_list(v): @@ -307,8 +307,8 @@ def admin_apps_list(v): @app.post("/reroll/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def reroll_oauth_tokens(aid, v): diff --git a/files/routes/polls.py b/files/routes/polls.py index 8bd6ca76d..5c12b52a3 100644 --- a/files/routes/polls.py +++ b/files/routes/polls.py @@ -8,8 +8,8 @@ from files.__main__ import app @app.post("/vote/post/option/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def vote_option(option_id, v): try: @@ -59,8 +59,8 @@ def vote_option(option_id, v): @app.post("/vote/comment/option/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def vote_option_comment(option_id, v): try: @@ -113,8 +113,8 @@ def vote_option_comment(option_id, v): @app.get("/votes/post/option/") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def option_votes(option_id, v): try: @@ -148,8 +148,8 @@ def option_votes(option_id, v): @app.get("/votes/comment/option/") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def option_votes_comment(option_id, v): try: diff --git a/files/routes/posts.py b/files/routes/posts.py index 8cd5a4e0c..98c5851ce 100644 --- a/files/routes/posts.py +++ b/files/routes/posts.py @@ -33,8 +33,8 @@ from files.__main__ import app, limiter, redis_instance @app.post("/publish/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def publish(pid, v): p = get_post(pid) @@ -68,8 +68,8 @@ def publish(pid, v): @app.get("/submit") @app.get("/h//submit") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_get(v:User, sub=None): sub = get_sub_by_name(sub, graceful=True) @@ -83,7 +83,7 @@ def submit_get(v:User, sub=None): @app.get("/post//") @app.get("/h//post/") @app.get("/h//post//") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired_with_logingate def post_id(pid, v, anything=None, sub=None): p = get_post(pid, v=v) @@ -192,7 +192,7 @@ def post_id(pid, v, anything=None, sub=None): return result @app.get("/view_more///") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired_with_logingate def view_more(v, pid, sort, offset): p = get_post(pid, v=v) @@ -245,7 +245,7 @@ def view_more(v, pid, sort, offset): @app.get("/more_comments/") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired_with_logingate def more_comments(v, cid): try: cid = int(cid) @@ -397,8 +397,8 @@ def thumbnail_thread(pid:int, vid:int): @app.post("/is_repost") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def is_repost(v): not_a_repost = {'permalink': ''} @@ -448,8 +448,8 @@ def is_repost(v): @app.post("/h//submit") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(POST_RATELIMIT) -@limiter.limit(POST_RATELIMIT, key_func=get_ID) +@limiter.limit(POST_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(POST_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_post(v:User, sub=None): url = request.values.get("url", "").strip() @@ -742,8 +742,8 @@ def submit_post(v:User, sub=None): @app.post("/delete_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def delete_post_pid(pid, v): p = get_post(pid) @@ -770,8 +770,8 @@ def delete_post_pid(pid, v): @app.post("/undelete_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def undelete_post_pid(pid, v): p = get_post(pid) @@ -794,8 +794,8 @@ def undelete_post_pid(pid, v): @feature_required('NSFW_MARKING') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def mark_post_nsfw(pid, v): p = get_post(pid) @@ -833,8 +833,8 @@ def mark_post_nsfw(pid, v): @feature_required('NSFW_MARKING') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unmark_post_nsfw(pid, v): p = get_post(pid) @@ -871,8 +871,8 @@ def unmark_post_nsfw(pid, v): @app.post("/save_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def save_post(pid, v): @@ -890,8 +890,8 @@ def save_post(pid, v): @app.post("/unsave_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unsave_post(pid, v): @@ -908,8 +908,8 @@ def unsave_post(pid, v): @app.post("/pin/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def pin_post(post_id, v): p = get_post(post_id) @@ -923,8 +923,8 @@ def pin_post(post_id, v): return abort(404, "Post not found!") @app.put("/post//new") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def set_new_sort(post_id:int, v:User): p = get_post(post_id) @@ -945,8 +945,8 @@ def set_new_sort(post_id:int, v:User): @app.delete("/post//new") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unset_new_sort(post_id:int, v:User): p = get_post(post_id) @@ -969,8 +969,8 @@ def unset_new_sort(post_id:int, v:User): extensions = IMAGE_FORMATS + VIDEO_FORMATS + AUDIO_FORMATS @app.get("/submit/title") -@limiter.limit("3/minute") -@limiter.limit("3/minute", key_func=get_ID) +@limiter.limit("3/minute", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("3/minute", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def get_post_title(v): POST_TITLE_TIMEOUT = 5 @@ -1003,8 +1003,8 @@ def get_post_title(v): @app.post("/edit_post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/minute;100/hour;200/day") -@limiter.limit("10/minute;100/hour;200/day", key_func=get_ID) +@limiter.limit("10/minute;100/hour;200/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/minute;100/hour;200/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def edit_post(pid, v): p = get_post(pid) diff --git a/files/routes/push_notifs.py b/files/routes/push_notifs.py index fae3e009c..013acdc57 100644 --- a/files/routes/push_notifs.py +++ b/files/routes/push_notifs.py @@ -6,8 +6,8 @@ from files.classes.push_subscriptions import PushSubscription @app.post("/push_subscribe") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def push_subscribe(v): subscription_json = request.values.get("subscription_json") diff --git a/files/routes/reporting.py b/files/routes/reporting.py index 60cea9dae..8b632b999 100644 --- a/files/routes/reporting.py +++ b/files/routes/reporting.py @@ -14,8 +14,8 @@ from files.__main__ import app, limiter, cache @app.post("/report/post/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def report_post(pid, v): if v.is_muted: abort(403, "You are forbidden from making reports!") @@ -77,8 +77,8 @@ def report_post(pid, v): @app.post("/report/comment/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def report_comment(cid, v): if v.is_muted: abort(403, "You are forbidden from making reports!") @@ -109,8 +109,8 @@ def report_comment(cid, v): @app.post('/del_report/post//') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("100/minute;300/hour;2000/day") -@limiter.limit("100/minute;300/hour;2000/day", key_func=get_ID) +@limiter.limit("100/minute;300/hour;2000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("100/minute;300/hour;2000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['REPORTS_REMOVE']) def remove_report_post(v, pid, uid): try: @@ -135,8 +135,8 @@ def remove_report_post(v, pid, uid): @app.post('/del_report/comment//') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("100/minute;300/hour;2000/day") -@limiter.limit("100/minute;300/hour;2000/day", key_func=get_ID) +@limiter.limit("100/minute;300/hour;2000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("100/minute;300/hour;2000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['REPORTS_REMOVE']) def remove_report_comment(v, cid, uid): try: diff --git a/files/routes/search.py b/files/routes/search.py index e82420b3c..2afdfa7ec 100644 --- a/files/routes/search.py +++ b/files/routes/search.py @@ -46,8 +46,8 @@ def searchparse(text): return criteria @app.get("/search/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def searchposts(v:User): query = request.values.get("q", '').strip() @@ -182,8 +182,8 @@ def searchposts(v:User): ) @app.get("/search/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def searchcomments(v:User): query = request.values.get("q", '').strip() @@ -286,8 +286,8 @@ def searchcomments(v:User): @app.get("/search/messages") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def searchmessages(v:User): query = request.values.get("q", '').strip() @@ -377,8 +377,8 @@ def searchmessages(v:User): return render_template("search_comments.html", v=v, query=query, page=page, comments=comments, sort=sort, t=t, total=total, standalone=True, render_replies=True) @app.get("/search/users") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def searchusers(v:User): query = request.values.get("q", '').strip() diff --git a/files/routes/settings.py b/files/routes/settings.py index 15edaf75d..3ec9c3408 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -25,22 +25,22 @@ from files.__main__ import app, cache, limiter @app.get("/settings") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings(v:User): return redirect("/settings/personal") @app.get("/settings/personal") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_personal(v:User): return render_template("settings/personal.html", v=v, error=get_error(), msg=get_msg()) @app.delete('/settings/background') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def remove_background(v): if v.background: @@ -53,8 +53,8 @@ def remove_background(v): @app.post('/settings/custom_background') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upload_custom_background(v): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -79,8 +79,8 @@ def upload_custom_background(v): @app.post('/settings/profile_background') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upload_profile_background(v): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -100,8 +100,8 @@ def upload_profile_background(v): return redirect(f'/@{v.username}') @app.delete('/settings/profile_background') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def delete_profile_background(v): if v.profile_background: @@ -112,8 +112,8 @@ def delete_profile_background(v): @app.post("/settings/personal") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_personal_post(v): if v.id == 253 and request.values.get("private"): @@ -393,8 +393,8 @@ def settings_personal_post(v): @app.post("/settings/filters") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def filters(v:User): filters=request.values.get("filters")[:1000].strip() @@ -423,8 +423,8 @@ def set_color(v:User, attr:str, color:Optional[str]): @app.post("/settings/namecolor") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def namecolor(v): return set_color(v, "namecolor", request.values.get("namecolor")) @@ -432,8 +432,8 @@ def namecolor(v): @app.post("/settings/themecolor") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def themecolor(v): return set_color(v, "themecolor", request.values.get("themecolor")) @@ -441,8 +441,8 @@ def themecolor(v): @app.post("/settings/titlecolor") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def titlecolor(v): return set_color(v, "titlecolor", request.values.get("titlecolor")) @@ -450,8 +450,8 @@ def titlecolor(v): @app.post("/settings/verifiedcolor") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def verifiedcolor(v): if not v.verified: abort(403, "You don't have a checkmark") @@ -460,8 +460,8 @@ def verifiedcolor(v): @app.post("/settings/security") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_security_post(v): if request.values.get("new_password"): @@ -536,8 +536,8 @@ def settings_security_post(v): @app.post("/settings/log_out_all_others") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_log_out_others(v): submitted_password = request.values.get("password", "").strip() @@ -554,8 +554,8 @@ def settings_log_out_others(v): @app.post("/settings/images/profile") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_images_profile(v): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -596,8 +596,8 @@ def settings_images_profile(v): @feature_required('USERS_PROFILE_BANNER') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_images_banner(v): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -617,8 +617,8 @@ def settings_images_banner(v): return redirect("/settings/personal?msg=Banner successfully updated!") @app.get("/settings/css") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_css_get(v:User): return render_template("settings/css.html", v=v, msg=get_msg(), profilecss=v.profilecss) @@ -626,8 +626,8 @@ def settings_css_get(v:User): @app.post("/settings/css") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_css(v): if v.chud: abort(400, "Chuded users can't edit CSS!") @@ -640,8 +640,8 @@ def settings_css(v): @app.post("/settings/profilecss") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_profilecss(v): profilecss = request.values.get("profilecss", v.profilecss).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT] @@ -653,8 +653,8 @@ def settings_profilecss(v): return redirect("/settings/css?msg=Profile CSS successfully updated!") @app.get("/settings/security") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_security(v:User): return render_template("settings/security.html", @@ -673,8 +673,8 @@ def settings_blocks(v:User): @app.post("/settings/block") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("20/day") -@limiter.limit("20/day", key_func=get_ID) +@limiter.limit("20/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("20/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_block_user(v): user = get_user(request.values.get("username"), graceful=True) @@ -703,8 +703,8 @@ def settings_block_user(v): @app.post("/settings/unblock") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_unblock_user(v): user = get_user(request.values.get("username")) @@ -717,15 +717,15 @@ def settings_unblock_user(v): return {"message": f"@{user.username} unblocked successfully!"} @app.get("/settings/apps") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_apps(v:User): return render_template("settings/apps.html", v=v) @app.get("/settings/advanced") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_advanced_get(v:User): return render_template("settings/advanced.html", v=v, msg=get_msg(), error=get_error()) @@ -733,8 +733,8 @@ def settings_advanced_get(v:User): @app.post("/settings/name_change") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def settings_name_change(v): if v.namechanged: abort(403) @@ -778,8 +778,8 @@ def settings_name_change(v): @feature_required('USERS_PROFILE_SONG') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/day") -@limiter.limit("10/day", key_func=get_ID) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_song_change_mp3(v): file = request.files['file'] @@ -844,8 +844,8 @@ def _change_song_youtube(vid, id): @feature_required('USERS_PROFILE_SONG') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/day") -@limiter.limit("10/day", key_func=get_ID) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_song_change(v): song=request.values.get("song").strip() @@ -897,8 +897,8 @@ def settings_song_change(v): @app.post("/settings/title_change") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_title_change(v): if v.flairchanged: abort(403) @@ -928,8 +928,8 @@ def settings_title_change(v): @feature_required('PRONOUNS') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_pronouns_change(v): pronouns = sanitize_settings_text(request.values.get("pronouns")) @@ -956,8 +956,8 @@ def settings_pronouns_change(v): @app.post("/settings/checkmark_text") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_checkmark_text(v): if not v.verified: abort(403) diff --git a/files/routes/special.py b/files/routes/special.py index 67e49057b..c81e97c69 100644 --- a/files/routes/special.py +++ b/files/routes/special.py @@ -83,8 +83,8 @@ def _special_leaderboard_get(): @app.get('/events/worldcup2022/leaderboard') @app.get('/special/worldcup2022/leaderboard') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def get_leaderboard(v): if SITE_NAME != 'rDrama': diff --git a/files/routes/static.py b/files/routes/static.py index f217b0c27..4c04a88db 100644 --- a/files/routes/static.py +++ b/files/routes/static.py @@ -19,13 +19,13 @@ from files.__main__ import app, cache, limiter @app.get("/r/drama/comments//") @app.get("/r/Drama/comments/<int:id>/<title>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def rdrama(id, title): id = ''.join(f'{x}/' for x in id) return redirect(f'/archives/drama/comments/{id}{title}.html') @app.get("/r/<subreddit>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def subreddit(subreddit, v): reddit = v.reddit if v else "old.reddit.com" @@ -33,7 +33,7 @@ def subreddit(subreddit, v): @app.get("/reddit/<subreddit>/comments/<path:path>") @app.get("/r/<subreddit>/comments/<path:path>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def reddit_post(subreddit, v, path): post_id = path.rsplit("/", 1)[0].replace('/', '') @@ -54,8 +54,8 @@ def marseys_redirect(): return redirect("/emojis") @app.get("/emojis") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def emoji_list(v:User): emojis = get_emoji_list() @@ -94,8 +94,8 @@ def get_emojis(): return collected @app.get("/emojis_json") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def emojis(v): return get_emojis() @@ -103,15 +103,15 @@ def emojis(v): @app.get('/sidebar') -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def sidebar(v:Optional[User]): return render_template('sidebar.html', v=v) @app.get("/stats") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def participation_stats(v:User): stats = cache.get('stats') or {} @@ -119,28 +119,28 @@ def participation_stats(v:User): return render_template("stats.html", v=v, title="Content Statistics", data=stats) @app.get("/chart") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def chart(): return redirect('/weekly_chart') @app.get("/weekly_chart") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def weekly_chart(v:User): return send_file(statshelper.chart_path(kind="weekly", site=SITE)) @app.get("/daily_chart") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def daily_chart(v:User): return send_file(statshelper.chart_path(kind="daily", site=SITE)) @app.get("/admin/patrons") @app.get("/admin/paypigs") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['VIEW_PATRONS']) def patrons(v): ids = [x[0] for x in g.db.query(User.id).filter(User.lifetimedonated > 0).order_by(User.email, User.truescore.desc()).distinct(User.email)] @@ -150,8 +150,8 @@ def patrons(v): @app.get("/admins") @app.get("/badmins") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def admins(v:User): admins = g.db.query(User).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.admin_level.desc(), User.truescore.desc()).all() @@ -159,8 +159,8 @@ def admins(v:User): @app.get("/log") @app.get("/modlog") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def log(v:User): @@ -206,8 +206,8 @@ def log(v:User): return render_template("log.html", v=v, admins=admins, types=types, admin=admin, type=kind, actions=actions, total=total, page=page, single_user_url='admin') @app.get("/log/<int:id>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def log_item(id, v): try: id = int(id) @@ -232,8 +232,8 @@ def log_item(id, v): return render_template("log.html", v=v, actions=[action], total=1, page=1, action=action, admins=admins, types=types, single_user_url='admin') @app.get("/directory") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def static_megathread_index(v:User): if SITE_NAME != 'rDrama': @@ -246,8 +246,8 @@ def static_megathread_index(v:User): return render_template("megathread_index.html", v=v, emojis_hash=emojis_hash, emojis_count=emojis_count, emojis_size=emojis_size) @app.get("/api") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def api(v): return render_template("api.html", v=v) @@ -258,7 +258,7 @@ def api(v): @app.get("/press") @app.get("/media") @app.get("/admin/chat") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def contact(v:Optional[User]): return render_template("contact.html", v=v, msg=get_msg()) @@ -266,8 +266,8 @@ def contact(v:Optional[User]): @app.post("/contact") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("1/minute;10/day") -@limiter.limit("1/minute;10/day", key_func=get_ID) +@limiter.limit("1/minute;10/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("1/minute;10/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def submit_contact(v): body = request.values.get("message") @@ -330,16 +330,16 @@ def badge_list(site, can_view_patron_badges): @app.get("/badges") @feature_required('BADGES') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def badges(v:User): badges, counts = badge_list(SITE, v.admin_level >= PERMS['VIEW_PATRONS']) return render_template("badges.html", v=v, badges=badges, counts=counts) @app.get("/blocks") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @admin_level_required(PERMS['USER_BLOCKS_VISIBLE']) def blocks(v): blocks=g.db.query(UserBlock).all() @@ -355,28 +355,28 @@ def blocks(v): return render_template("blocks.html", v=v, users=users, targets=targets) @app.get("/formatting") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def formatting(v:User): return render_template("formatting.html", v=v) @app.get("/app") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def mobile_app(v:Optional[User]): return render_template("app.html", v=v) @app.post("/dismiss_mobile_tip") @limiter.limit('1/second', scope=rpath) -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def dismiss_mobile_tip(): session["tooltip_dismissed"] = int(time.time()) return "", 204 @app.get("/transfers/<int:id>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def transfers_id(id, v): @@ -390,8 +390,8 @@ def transfers_id(id, v): return render_template("transfers.html", v=v, page=1, comments=[transfer], standalone=True, total=1) @app.get("/transfers") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def transfers(v:User): @@ -409,7 +409,7 @@ def transfers(v:User): @app.get('/donate') -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_desired def donate(v): if v and (v.shadowbanned or v.chud == 1 or v.is_permabanned): diff --git a/files/routes/subs.py b/files/routes/subs.py index f30c436e0..6dc6af4e8 100644 --- a/files/routes/subs.py +++ b/files/routes/subs.py @@ -10,8 +10,8 @@ from files.__main__ import app, cache, limiter @app.post("/exile/post/<int:pid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def exile_post(v:User, pid): if v.shadowbanned: abort(500) @@ -45,8 +45,8 @@ def exile_post(v:User, pid): @app.post("/exile/comment/<int:cid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def exile_comment(v:User, cid): if v.shadowbanned: abort(500) @@ -80,8 +80,8 @@ def exile_comment(v:User, cid): @app.post("/h/<sub>/unexile/<int:uid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def unexile(v:User, sub, uid): u = get_account(uid) @@ -112,8 +112,8 @@ def unexile(v:User, sub, uid): @app.post("/h/<sub>/block") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def block_sub(v:User, sub): sub = get_sub_by_name(sub).name @@ -127,8 +127,8 @@ def block_sub(v:User, sub): @app.post("/h/<sub>/unblock") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unblock_sub(v:User, sub): sub = get_sub_by_name(sub) @@ -146,8 +146,8 @@ def unblock_sub(v:User, sub): @app.post("/h/<sub>/subscribe") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def subscribe_sub(v:User, sub): sub = get_sub_by_name(sub).name @@ -161,8 +161,8 @@ def subscribe_sub(v:User, sub): @app.post("/h/<sub>/unsubscribe") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unsubscribe_sub(v:User, sub): sub = get_sub_by_name(sub).name @@ -175,8 +175,8 @@ def unsubscribe_sub(v:User, sub): @app.post("/h/<sub>/follow") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def follow_sub(v:User, sub): sub = get_sub_by_name(sub) @@ -193,8 +193,8 @@ def follow_sub(v:User, sub): @app.post("/h/<sub>/unfollow") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unfollow_sub(v:User, sub): sub = get_sub_by_name(sub) @@ -206,8 +206,8 @@ def unfollow_sub(v:User, sub): return {"message": f"/h/{sub} unfollowed successfully!"} @app.get("/h/<sub>/mods") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def mods(v:User, sub): sub = get_sub_by_name(sub) @@ -219,8 +219,8 @@ def mods(v:User, sub): @app.get("/h/<sub>/exilees") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def sub_exilees(v:User, sub): sub = get_sub_by_name(sub) @@ -234,8 +234,8 @@ def sub_exilees(v:User, sub): @app.get("/h/<sub>/blockers") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def sub_blockers(v:User, sub): sub = get_sub_by_name(sub) @@ -250,8 +250,8 @@ def sub_blockers(v:User, sub): @app.get("/h/<sub>/followers") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def sub_followers(v:User, sub): sub = get_sub_by_name(sub) @@ -268,8 +268,8 @@ def sub_followers(v:User, sub): @app.post("/h/<sub>/add_mod") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("30/day") -@limiter.limit("30/day", key_func=get_ID) +@limiter.limit("30/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("30/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def add_mod(v:User, sub): if SITE_NAME == 'WPD': abort(403) @@ -308,8 +308,8 @@ def add_mod(v:User, sub): @app.post("/h/<sub>/remove_mod") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def remove_mod(v:User, sub): sub = get_sub_by_name(sub).name @@ -349,8 +349,8 @@ def remove_mod(v:User, sub): return {"message": f"@{user.username} has been removed as a mod!"} @app.get("/create_hole") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def create_sub(v): if not v.can_create_hole: @@ -361,8 +361,8 @@ def create_sub(v): @app.post("/create_hole") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def create_sub2(v): if not v.can_create_hole: @@ -401,8 +401,8 @@ def create_sub2(v): @app.post("/kick/<int:pid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def kick(v:User, pid): post = get_post(pid) @@ -434,8 +434,8 @@ def kick(v:User, pid): return {"message": f"Post kicked from /h/{old} successfully!"} @app.get('/h/<sub>/settings') -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def sub_settings(v:User, sub): sub = get_sub_by_name(sub) @@ -446,8 +446,8 @@ def sub_settings(v:User, sub): @app.post('/h/<sub>/sidebar') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def post_sub_sidebar(v:User, sub): sub = get_sub_by_name(sub) @@ -473,8 +473,8 @@ def post_sub_sidebar(v:User, sub): @app.post('/h/<sub>/css') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def post_sub_css(v:User, sub): sub = get_sub_by_name(sub) @@ -505,7 +505,7 @@ def post_sub_css(v:User, sub): return redirect(f'/h/{sub}/settings') @app.get("/h/<sub>/css") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def get_sub_css(sub): sub = g.db.query(Sub.css).filter_by(name=sub.strip().lower()).one_or_none() if not sub: abort(404) @@ -516,8 +516,8 @@ def get_sub_css(sub): @app.post("/h/<sub>/settings/banners/") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("50/day") -@limiter.limit("50/day", key_func=get_ID) +@limiter.limit("50/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("50/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def upload_sub_banner(v:User, sub:str): if g.is_tor: abort(403, "Image uploads are not allowed through Tor") @@ -546,8 +546,8 @@ def upload_sub_banner(v:User, sub:str): return redirect(f'/h/{sub}/settings') @app.delete("/h/<sub>/settings/banners/<int:index>") -@limiter.limit("1/second;30/day") -@limiter.limit("1/second;30/day", key_func=get_ID) +@limiter.limit("1/second;30/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("1/second;30/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def delete_sub_banner(v:User, sub:str, index:int): sub = get_sub_by_name(sub) @@ -577,8 +577,8 @@ def delete_sub_banner(v:User, sub:str, index:int): return {"message": f"Deleted banner {index} from /h/{sub} successfully"} @app.delete("/h/<sub>/settings/banners/") -@limiter.limit("1/10 second;30/day") -@limiter.limit("1/10 second;30/day", key_func=get_ID) +@limiter.limit("1/10 second;30/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("1/10 second;30/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def delete_all_sub_banners(v:User, sub:str): sub = get_sub_by_name(sub) @@ -605,8 +605,8 @@ def delete_all_sub_banners(v:User, sub:str): @app.post("/h/<sub>/sidebar_image") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/day") -@limiter.limit("10/day", key_func=get_ID) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def sub_sidebar(v:User, sub): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -638,8 +638,8 @@ def sub_sidebar(v:User, sub): @app.post("/h/<sub>/marsey_image") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/day") -@limiter.limit("10/day", key_func=get_ID) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def sub_marsey(v:User, sub): if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") @@ -670,8 +670,8 @@ def sub_marsey(v:User, sub): @app.get("/flairs") @app.get("/holes") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def subs(v:User): subs = g.db.query(Sub, func.count(Post.sub)).outerjoin(Post, Sub.name == Post.sub).group_by(Sub.name).order_by(func.count(Post.sub).desc()).all() @@ -681,8 +681,8 @@ def subs(v:User): @app.post("/hole_pin/<int:pid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def hole_pin(v:User, pid): p = get_post(pid) @@ -717,8 +717,8 @@ def hole_pin(v:User, pid): @app.post("/hole_unpin/<int:pid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def hole_unpin(v:User, pid): p = get_post(pid) @@ -750,8 +750,8 @@ def hole_unpin(v:User, pid): @app.post('/h/<sub>/stealth') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def sub_stealth(v:User, sub): sub = get_sub_by_name(sub) @@ -786,8 +786,8 @@ def sub_stealth(v:User, sub): @feature_required('PINS') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def mod_pin(cid, v): @@ -817,8 +817,8 @@ def mod_pin(cid, v): @app.post("/unmod_pin/<int:cid>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def mod_unpin(cid, v): @@ -846,8 +846,8 @@ def mod_unpin(cid, v): @app.get("/h/<sub>/log") @app.get("/h/<sub>/modlog") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def hole_log(v:User, sub): sub = get_sub_by_name(sub) @@ -887,8 +887,8 @@ def hole_log(v:User, sub): return render_template("log.html", v=v, admins=mods, types=types, admin=mod, type=kind, actions=actions, total=total, page=page, sub=sub, single_user_url='mod') @app.get("/h/<sub>/log/<int:id>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def hole_log_item(id, v, sub): sub = get_sub_by_name(sub) diff --git a/files/routes/users.py b/files/routes/users.py index 8a7a55dcb..e88208d2d 100644 --- a/files/routes/users.py +++ b/files/routes/users.py @@ -62,32 +62,32 @@ def upvoters_downvoters(v, username, uid, cls, vote_cls, vote_dir, template, sta return render_template(template, total=total, listing=listing, page=page, v=v, standalone=standalone) @app.get("/@<username>/upvoters/<int:uid>/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoters_posts(v:User, username, uid): return upvoters_downvoters(v, username, uid, Post, Vote, 1, "userpage/voted_posts.html", None) @app.get("/@<username>/upvoters/<int:uid>/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoters_comments(v:User, username, uid): return upvoters_downvoters(v, username, uid, Comment, CommentVote, 1, "userpage/voted_comments.html", True) @app.get("/@<username>/downvoters/<int:uid>/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoters_posts(v:User, username, uid): return upvoters_downvoters(v, username, uid, Post, Vote, -1, "userpage/voted_posts.html", None) @app.get("/@<username>/downvoters/<int:uid>/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoters_comments(v:User, username, uid): return upvoters_downvoters(v, username, uid, Comment, CommentVote, -1, "userpage/voted_comments.html", True) @@ -128,32 +128,32 @@ def upvoting_downvoting(v, username, uid, cls, vote_cls, vote_dir, template, sta return render_template(template, total=total, listing=listing, page=page, v=v, standalone=standalone) @app.get("/@<username>/upvoting/<int:uid>/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoting_posts(v:User, username, uid): return upvoting_downvoting(v, username, uid, Post, Vote, 1, "userpage/voted_posts.html", None) @app.get("/@<username>/upvoting/<int:uid>/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoting_comments(v:User, username, uid): return upvoting_downvoting(v, username, uid, Comment, CommentVote, 1, "userpage/voted_comments.html", True) @app.get("/@<username>/downvoting/<int:uid>/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoting_posts(v:User, username, uid): return upvoting_downvoting(v, username, uid, Post, Vote, -1, "userpage/voted_posts.html", None) @app.get("/@<username>/downvoting/<int:uid>/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoting_comments(v:User, username, uid): return upvoting_downvoting(v, username, uid, Comment, CommentVote, -1, "userpage/voted_comments.html", True) @@ -188,23 +188,23 @@ def user_voted(v, username, cls, vote_cls, template, standalone): return render_template(template, total=total, listing=listing, page=page, v=v, standalone=standalone) @app.get("/@<username>/voted/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def user_voted_posts(v:User, username): return user_voted(v, username, Post, Vote, "userpage/voted_posts.html", None) @app.get("/@<username>/voted/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def user_voted_comments(v:User, username): return user_voted(v, username, Comment, CommentVote, "userpage/voted_comments.html", True) @app.get("/banned") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def banned(v:User): users = g.db.query(User).filter( @@ -216,8 +216,8 @@ def banned(v:User): return render_template("banned.html", v=v, users=users) @app.get("/grassed") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def grassed(v:User): users = g.db.query(User).filter( @@ -229,8 +229,8 @@ def grassed(v:User): return render_template("grassed.html", v=v, users=users) @app.get("/chuds") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def chuds(v:User): users = g.db.query(User).filter( @@ -296,29 +296,29 @@ def all_upvoters_downvoters(v:User, username:str, vote_dir:int, is_who_simps_hat return render_template("userpage/voters.html", v=v, users=users, pos=pos, name=vote_name, name2=name2, page=page, total_items=total_items, total=total) @app.get("/@<username>/upvoters") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoters(v:User, username:str): return all_upvoters_downvoters(v, username, 1, False) @app.get("/@<username>/downvoters") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoters(v:User, username:str): return all_upvoters_downvoters(v, username, -1, False) @app.get("/@<username>/upvoting") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def upvoting(v:User, username:str): return all_upvoters_downvoters(v, username, 1, True) @app.get("/@<username>/downvoting") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def downvoting(v:User, username:str): return all_upvoters_downvoters(v, username, -1, True) @@ -327,8 +327,8 @@ def downvoting(v:User, username:str): @feature_required('USERS_SUICIDE') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("5/day") -@limiter.limit("5/day", key_func=get_ID) +@limiter.limit("5/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("5/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def suicide(v:User, username:str): user = get_user(username) @@ -339,8 +339,8 @@ def suicide(v:User, username:str): @app.get("/@<username>/coins") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def get_coins(v:User, username:str): user = get_user(username, v=v) @@ -391,8 +391,8 @@ def transfer_currency(v:User, username:str, currency_name:Literal['coins', 'mars @app.post("/@<username>/transfer_coins") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def transfer_coins(v:User, username:str): return transfer_currency(v, username, 'coins', True) @@ -401,15 +401,15 @@ def transfer_coins(v:User, username:str): @feature_required('MARSEYBUX') @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def transfer_bux(v:User, username:str): return transfer_currency(v, username, 'marseybux', False) @app.get("/leaderboard") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required @cache.memoize() def leaderboard(v:User): @@ -443,7 +443,7 @@ def leaderboard(v:User): return render_template("leaderboard.html", v=v, leaderboards=leaderboards) @app.get("/<int:id>/css") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def get_css(id): try: id = int(id) except: abort(404) @@ -467,7 +467,7 @@ def get_css(id): return resp @app.get("/<int:id>/profilecss") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def get_profilecss(id): try: id = int(id) except: abort(404) @@ -489,7 +489,7 @@ def get_profilecss(id): return resp @app.get("/@<username>/song") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def usersong(username:str): user = get_user(username) if not user.song: @@ -503,8 +503,8 @@ def usersong(username:str): @app.post("/subscribe/<int:post_id>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def subscribe(v, post_id): existing = g.db.query(Subscription).filter_by(user_id=v.id, post_id=post_id).one_or_none() @@ -517,8 +517,8 @@ def subscribe(v, post_id): @app.post("/unsubscribe/<int:post_id>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unsubscribe(v, post_id): existing = g.db.query(Subscription).filter_by(user_id=v.id, post_id=post_id).one_or_none() @@ -531,8 +531,8 @@ def unsubscribe(v, post_id): @app.post("/id/<int:id>/message") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("10/minute;20/hour;50/day") -@limiter.limit("10/minute;20/hour;50/day", key_func=get_ID) +@limiter.limit("10/minute;20/hour;50/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("10/minute;20/hour;50/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def message2(v, username=None, id=None): if id: @@ -600,8 +600,8 @@ def message2(v, username=None, id=None): @app.post("/reply") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("6/minute;50/hour;200/day") -@limiter.limit("6/minute;50/hour;200/day", key_func=get_ID) +@limiter.limit("6/minute;50/hour;200/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("6/minute;50/hour;200/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def messagereply(v:User): body = sanitize_raw_body(request.values.get("body"), False) @@ -694,8 +694,8 @@ def messagereply(v:User): return {"comment": render_template("comments.html", v=v, comments=[c])} @app.get("/2faqr/<secret>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def mfa_qr(v:User, secret:str): x = pyotp.TOTP(secret) @@ -714,7 +714,7 @@ def mfa_qr(v:User, secret:str): @app.get("/is_available/<name>") -@limiter.limit("100/day") +@limiter.limit("100/day", deduct_when=lambda response: response.status_code < 400) def is_available(name:str): name=name.strip() @@ -739,8 +739,8 @@ def is_available(name:str): @app.get("/id/<int:id>") @app.route("/id/<int:id>/<path:path>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def user_id(v, id, path=''): user = get_account(id) @@ -749,15 +749,15 @@ def user_id(v, id, path=''): return redirect(f'/@{user.username}') @app.get("/u/<username>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def redditor_moment_redirect(v:User, username:str): return redirect(f"/@{username}") @app.get("/@<username>/blockers") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blockers(v:User, username:str): u = get_user(username, v=v) @@ -775,8 +775,8 @@ def blockers(v:User, username:str): return render_template("userpage/blockers.html", v=v, u=u, users=users, page=page, total=total) @app.get("/@<username>/blocking") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def blocking(v:User, username:str): u = get_user(username, v=v) @@ -794,8 +794,8 @@ def blocking(v:User, username:str): return render_template("userpage/blocking.html", v=v, u=u, users=users, page=page, total=total) @app.get("/@<username>/followers") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def followers(v:User, username:str): u = get_user(username, v=v) @@ -816,8 +816,8 @@ def followers(v:User, username:str): return render_template("userpage/followers.html", v=v, u=u, users=users, page=page, total=total) @app.get("/@<username>/following") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def following(v:User, username:str): u = get_user(username, v=v) @@ -837,8 +837,8 @@ def following(v:User, username:str): return render_template("userpage/following.html", v=v, u=u, users=users, page=page, total=total) @app.get("/@<username>/views") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def visitors(v:User, username:str): u = get_user(username, v=v) @@ -863,7 +863,7 @@ def userpagelisting(user:User, v=None, page:int=1, sort="new", t="all"): return [x.id for x in posts], total @app.get("/@<username>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_required def u_username_wall(v:Optional[User], username:str): u = get_user(username, v=v, include_blocks=True) @@ -911,7 +911,7 @@ def u_username_wall(v:Optional[User], username:str): @app.get("/@<username>/wall/comment/<int:cid>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_required def u_username_wall_comment(v:User, username:str, cid): comment = get_comment(cid, v=v) @@ -960,7 +960,7 @@ def u_username_wall_comment(v:User, username:str, cid): @app.get("/@<username>/posts") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_required def u_username(v:Optional[User], username:str): u = get_user(username, v=v, include_blocks=True) @@ -1031,7 +1031,7 @@ def u_username(v:Optional[User], username:str): @app.get("/@<username>/comments") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @auth_required def u_username_comments(username, v): u = get_user(username, v=v, include_blocks=True) @@ -1095,8 +1095,8 @@ def u_username_comments(username, v): @app.get("/@<username>/info") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def u_username_info(username, v): @@ -1110,8 +1110,8 @@ def u_username_info(username, v): return user.json @app.get("/<int:id>/info") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def u_user_id_info(id, v): @@ -1127,8 +1127,8 @@ def u_user_id_info(id, v): @app.post("/follow/<username>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def follow_user(username, v): @@ -1155,8 +1155,8 @@ def follow_user(username, v): @app.post("/unfollow/<username>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def unfollow_user(username, v): @@ -1188,8 +1188,8 @@ def unfollow_user(username, v): @app.post("/remove_follow/<username>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def remove_follow(username, v): target = get_user(username) @@ -1257,8 +1257,8 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone return render_template(template, u=v, v=v, listing=listing, page=page, total=total, standalone=standalone) @app.get("/@<username>/saved/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def saved_posts(v:User, username): page = get_page() @@ -1266,8 +1266,8 @@ def saved_posts(v:User, username): return get_saves_and_subscribes(v, "userpage/posts.html", SaveRelationship, page, False) @app.get("/@<username>/saved/comments") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def saved_comments(v:User, username): page = get_page() @@ -1275,8 +1275,8 @@ def saved_comments(v:User, username): return get_saves_and_subscribes(v, "userpage/comments.html", CommentSaveRelationship, page, True) @app.get("/@<username>/subscribed/posts") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def subscribed_posts(v:User, username): page = get_page() @@ -1286,8 +1286,8 @@ def subscribed_posts(v:User, username): @app.post("/fp/<fp>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def fp(v:User, fp): if session.get("GLOBAL"): @@ -1310,7 +1310,7 @@ def fp(v:User, fp): return '', 204 @app.post("/toggle_pins/<sort>") -@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) def toggle_pins(sort): if sort == 'hot': default = True else: default = False @@ -1324,8 +1324,8 @@ def toggle_pins(sort): @app.get("/badge_owners/<int:bid>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def bid_list(v:User, bid): @@ -1489,8 +1489,8 @@ def gumroad(): @app.post("/settings/claim_rewards") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def settings_claim_rewards(v:User): if not (v.email and v.is_activated): @@ -1506,8 +1506,8 @@ def settings_claim_rewards(v:User): return {"message": f"{patron} rewards claimed!"} @app.get("/users") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def users_list(v): diff --git a/files/routes/votes.py b/files/routes/votes.py index 802d83305..da7987c24 100644 --- a/files/routes/votes.py +++ b/files/routes/votes.py @@ -9,8 +9,8 @@ from files.routes.routehelpers import get_alt_graph from math import floor @app.get("/votes/<link>") -@limiter.limit(DEFAULT_RATELIMIT) -@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) +@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def vote_info_get(v, link): try: @@ -195,8 +195,8 @@ def vote_post_comment(target_id, new, v, cls, vote_cls): @app.post("/vote/post/<int:post_id>/<new>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("60/minute;1000/hour;2000/day") -@limiter.limit("60/minute;1000/hour;2000/day", key_func=get_ID) +@limiter.limit("60/minute;1000/hour;2000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("60/minute;1000/hour;2000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def vote_post(post_id, new, v): return vote_post_comment(post_id, new, v, Post, Vote) @@ -204,8 +204,8 @@ def vote_post(post_id, new, v): @app.post("/vote/comment/<int:comment_id>/<new>") @limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath, key_func=get_ID) -@limiter.limit("60/minute;1000/hour;2000/day") -@limiter.limit("60/minute;1000/hour;2000/day", key_func=get_ID) +@limiter.limit("60/minute;1000/hour;2000/day", deduct_when=lambda response: response.status_code < 400) +@limiter.limit("60/minute;1000/hour;2000/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @is_not_permabanned def vote_comment(comment_id, new, v): return vote_post_comment(comment_id, new, v, Comment, CommentVote)