Initial commit
This commit is contained in:
42
serverside/helpers/config.py
Normal file
42
serverside/helpers/config.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import configparser
|
||||
from pathlib import Path
|
||||
#from serverside.consts import BASE_DIR
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||
CONFIG_PATH = BASE_DIR / "configuration.ini"
|
||||
|
||||
_config = configparser.ConfigParser()
|
||||
_config.read(CONFIG_PATH)
|
||||
|
||||
def get(section: str, key: str, fallback=None):
|
||||
try:
|
||||
return _config.get(section, key)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError):
|
||||
return fallback
|
||||
|
||||
def get_int(section: str, key: str, fallback=None):
|
||||
try:
|
||||
return _config.getint(section, key)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
|
||||
return fallback
|
||||
|
||||
def get_float(section: str, key: str, fallback=None):
|
||||
try:
|
||||
return _config.getfloat(section, key)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
|
||||
return fallback
|
||||
|
||||
def get_bool(section: str, key: str, fallback=None):
|
||||
try:
|
||||
return _config.getboolean(section, key)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
|
||||
return fallback
|
||||
|
||||
def sections():
|
||||
return _config.sections()
|
||||
|
||||
def options(section: str):
|
||||
try:
|
||||
return _config.options(section)
|
||||
except configparser.NoSectionError:
|
||||
return []
|
||||
25
serverside/helpers/logger.py
Normal file
25
serverside/helpers/logger.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from serverside.helpers.config import get
|
||||
#from serverside.consts import LOG_FILE
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||
LOG_FILE = BASE_DIR / get("paths", "log_file_name", fallback="nudestealer_log.log")
|
||||
|
||||
def setup_logger(name: str = "nudestealer") -> logging.Logger:
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if not logger.handlers:
|
||||
file_handler = logging.FileHandler(LOG_FILE, encoding="utf-8")
|
||||
file_handler.setLevel(logging.DEBUG)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
logger.propagate = False
|
||||
|
||||
return logger
|
||||
33
serverside/helpers/middleware.py
Normal file
33
serverside/helpers/middleware.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import time
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
LIMIT = 60
|
||||
WINDOW = 60
|
||||
BLOCK_TIME = 5*60
|
||||
|
||||
ip_store = {}
|
||||
|
||||
class RateLimitMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request, call_next):
|
||||
ip = request.client.host
|
||||
now = time.time()
|
||||
entry = ip_store.get(ip, {"count": 0, "first_request": now, "blocked_until": None})
|
||||
|
||||
if entry["blocked_until"] and now < entry["blocked_until"]:
|
||||
return JSONResponse({"error": "Too many requests. Try again later."}, status_code=429)
|
||||
|
||||
if now - entry["first_request"] > WINDOW:
|
||||
entry["count"] = 0
|
||||
entry["first_request"] = now
|
||||
|
||||
entry["count"] += 1
|
||||
|
||||
if entry["count"] > LIMIT:
|
||||
entry["blocked_until"] = now + BLOCK_TIME
|
||||
ip_store[ip] = entry
|
||||
return JSONResponse({"error": "Rate limit exceeded. Blocked for 5 minutes."}, status_code=429)
|
||||
|
||||
ip_store[ip] = entry
|
||||
response = await call_next(request)
|
||||
return response
|
||||
Reference in New Issue
Block a user