diff --git a/ai_blocker/middleware.py b/ai_blocker/middleware.py new file mode 100644 index 0000000..2d5eb5a --- /dev/null +++ b/ai_blocker/middleware.py @@ -0,0 +1,35 @@ +import importlib +from asgiref.sync import iscoroutinefunction, markcoroutinefunction + +from django.conf import settings +from django.http import HttpResponse + + +def load_backing_class(path: str): + mod_name, _, cls_name = path.rpartition(".") + module = importlib.import_module(mod_name) + return getattr(module, cls_name) + + +class AiBlockerMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + if iscoroutinefunction(self.get_response): + markcoroutinefunction(self) + + self.backing_class = getattr(getattr(settings, "AI_BLOCKER_CONF"), "backing_class", "ai_blocker.ualist_backers.ConfigBackedUAList") + Backer = load_backing_class(self.backing_class) + self.backer = Backer() + + async def __call__(self, request): + ua = request.headers.get("User-Agent", "") + + blocked_headers = self.backer.get_ua_list() + + if ua in blocked_headers: + return HttpResponse(status=403) + + response = self.get_response(request) + # Add code here to process the response after the view has been run. + return response \ No newline at end of file diff --git a/ai_blocker/ualist_backers.py b/ai_blocker/ualist_backers.py new file mode 100644 index 0000000..46019c9 --- /dev/null +++ b/ai_blocker/ualist_backers.py @@ -0,0 +1,16 @@ +from abc import ABC, abstractmethod + +from django.conf import settings + + +class UAList(ABC): + + @abstractmethod + def get_ua_list(self) -> list[str]: + raise NotImplemented + + + +class ConfigBackedUAList(UAList): + def get_ua_list(self) -> list[str]: + return list(getattr(getattr(settings, "AI_BLOCKER_CONF"), "ua_list", [])) \ No newline at end of file