# frozen_string_literal: true require 'zlib' module BetterRateLimitable def rate_limit(limit, time, error) return if Rails.env.test? return if current_user&.staff? # Staff skip the rate limit, mainly Floorb who uses his own shitty API for mass-imports and things. data = [ current_user&.id, request.remote_ip, params[:controller], params[:action] ] key = "rl-v2-#{Zlib.crc32(data.join)}" amt = $redis.incr key response.headers['X-RL'] = limit.to_s response.headers['X-RL-Remain'] = (limit - amt).to_s response.headers['X-RL-Reset'] = (Time.current.utc + $redis.ttl(key)) # The goal here is to bump the expiry to (now + time) only if we're over the limit. if amt > limit $redis.expire key, time.to_i respond_to do |format| format.json { render json: { error: error }, status: :too_many_requests } format.any { redirect_back flash: { notice: error } } end elsif amt == 1 # We just set it, make it expire appropriately $redis.expire key, time.to_i end end end