set $session_secret %ANTIBOT_SESSION_SECRET%;
set $session_check_addr on;

access_by_lua_block {

local use_lets_encrypt		= %USE_LETS_ENCRYPT%
local use_whitelist_ip		= %USE_WHITELIST_IP%
local use_whitelist_reverse	= %USE_WHITELIST_REVERSE%
local use_user_agent		= %USE_USER_AGENT%
local use_referrer		= %USE_REFERRER%
local use_country		= %USE_COUNTRY%
local use_blacklist_ip		= %USE_BLACKLIST_IP%
local use_blacklist_reverse	= %USE_BLACKLIST_REVERSE%
local use_dnsbl			= %USE_DNSBL%
local use_crowdsec		= %USE_CROWDSEC%
local use_antibot_cookie	= %USE_ANTIBOT_COOKIE%
local use_antibot_javascript	= %USE_ANTIBOT_JAVASCRIPT%
local use_antibot_captcha	= %USE_ANTIBOT_CAPTCHA%
local use_antibot_recaptcha	= %USE_ANTIBOT_RECAPTCHA%

-- include LUA code
local whitelist		= require "whitelist"
local blacklist		= require "blacklist"
local dnsbl		= require "dnsbl"
local cookie		= require "cookie"
local javascript	= require "javascript"
local captcha		= require "captcha"
local recaptcha		= require "recaptcha"

-- user variables
local antibot_uri		= "%ANTIBOT_URI%"
local whitelist_user_agent	= {%WHITELIST_USER_AGENT%}
local whitelist_uri		= {%WHITELIST_URI%}

-- check if already in whitelist cache
if use_whitelist_ip and whitelist.ip_cached_ok() then
	ngx.exit(ngx.OK)
end
if use_whitelist_reverse and whitelist.reverse_cached_ok() then
	ngx.exit(ngx.OK)
end

-- check if already in blacklist cache
if use_blacklist_ip and blacklist.ip_cached_ko() then
	ngx.exit(ngx.HTTP_FORBIDDEN)
end
if use_blacklist_reverse and blacklist.reverse_cached_ko() then
	ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- check if already in dnsbl cache
if use_dnsbl and dnsbl.cached_ko() then
	ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- check if IP is whitelisted (only if not in cache)
if use_whitelist_ip and not whitelist.ip_cached() then
	if whitelist.check_ip() then
		ngx.exit(ngx.OK)
	end
end

-- check if reverse is whitelisted (only if not in cache)
if use_whitelist_reverse and not whitelist.reverse_cached() then
	if whitelist.check_reverse() then
		ngx.exit(ngx.OK)
	end
end

-- check if URI is whitelisted
for k, v in pairs(whitelist_uri) do
	if ngx.var.request_uri == v then
		ngx.log(ngx.NOTICE, "[WHITELIST] URI " .. v .. " is whitelisted")
		ngx.exit(ngx.OK)
	end
end

-- check if it's certbot
if use_lets_encrypt and string.match(ngx.var.request_uri, "^/.well-known/acme-challenge/") then
	ngx.exit(ngx.OK)
end

-- check if IP is blacklisted (only if not in cache)
if use_blacklist_ip and not blacklist.ip_cached() then
	if blacklist.check_ip() then
		ngx.exit(ngx.HTTP_FORBIDDEN)
	end
end

-- check if reverse is blacklisted (only if not in cache)
if use_blacklist_reverse and not blacklist.reverse_cached() then
	if blacklist.check_reverse() then
		ngx.exit(ngx.HTTP_FORBIDDEN)
	end
end

-- check if user-agent is allowed
if use_user_agent and ngx.var.bad_user_agent == "yes" then
	local block = false
	for k, v in pairs(whitelist_user_agent) do
		if string.match(ngx.var.http_user_agent, v) then
			ngx.log(ngx.NOTICE, "[ALLOW] User-Agent " .. ngx.var.http_user_agent .. " is whitelisted")
			block = false
			break
		end
	end
	if block then
		ngx.log(ngx.NOTICE, "[BLOCK] User-Agent " .. ngx.var.http_user_agent .. " is blacklisted")
		ngx.exit(ngx.HTTP_FORBIDDEN)
	end
end

-- check if referrer is allowed
if use_referrer and ngx.var.bad_referrer == "yes" then
	ngx.log(ngx.NOTICE, "[BLOCK] Referrer " .. ngx.var.http_referer .. " is blacklisted")
	ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- check if country is allowed
if use_country and ngx.var.allowed_country == "no" then
	ngx.log(ngx.NOTICE, "[BLOCK] Country of " .. ngx.var.remote_addr .. " is blacklisted")
	ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- check if IP is in DNSBLs (only if not in cache)
if use_dnsbl and not dnsbl.cached() then
	if dnsbl.check() then
		ngx.exit(ngx.HTTP_FORBIDDEN)
	end
end

-- check if IP is in CrowdSec DB
if use_crowdsec then
	local ok, err = require "crowdsec.CrowdSec".allowIp(ngx.var.remote_addr)
	if ok == nil then
		ngx.log(ngx.ERR, "[Crowdsec] " .. err)
	end
	if not ok then
		ngx.log(ngx.NOTICE, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "'")
		ngx.exit(ngx.HTTP_FORBIDDEN)
	end
end

-- cookie check
if use_antibot_cookie then
	if not cookie.is_set("uri") then
		if ngx.var.request_uri ~= antibot_uri then
			cookie.set({uri = ngx.var.request_uri})
			return ngx.redirect(antibot_uri)
		end
		ngx.log(ngx.NOTICE, "[ANTIBOT] cookie fail for " .. ngx.var.remote_addr)
		return ngx.exit(ngx.HTTP_FORBIDDEN)
	else
		if ngx.var.request_uri == antibot_uri then
			return ngx.redirect(cookie.get("uri"))
		end
	end
end

-- javascript check
if use_antibot_javascript then
	if not cookie.is_set("javascript") then
		if ngx.var.request_uri ~= antibot_uri then
			cookie.set({uri = ngx.var.request_uri, challenge = javascript.get_challenge()})
			return ngx.redirect(antibot_uri)
		end
	end
end

-- captcha check
if use_antibot_captcha then
	if not cookie.is_set("captcha") then
		if ngx.var.request_uri ~= antibot_uri then
			cookie.set({uri = ngx.var.request_uri})
			return ngx.redirect(antibot_uri)
		end
	end
end

-- recaptcha check
if use_antibot_recaptcha then
	if not cookie.is_set("recaptcha") then
		if ngx.var.request_uri ~= antibot_uri then
			cookie.set({uri = ngx.var.request_uri})
			return ngx.redirect(antibot_uri)
		end
	end
end

ngx.exit(ngx.OK)

}

%INCLUDE_ANTIBOT_JAVASCRIPT%

%INCLUDE_ANTIBOT_CAPTCHA%

%INCLUDE_ANTIBOT_RECAPTCHA%
