""" Django settings for core project. Generated by 'django-admin startproject' using Django 5.2.6. For more information on this file, see https://docs.djangoproject.com/en/5.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/5.2/ref/settings/ """ import os import socket from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get( "SECRET_KEY", "django-insecure-y315h5v5t^1c^rqqcpk1y&!7+f8%8rj3$3bh2k!xoco8x@a+kr" ) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.environ.get("DEBUG", "False").lower() == "true" ALLOWED_HOSTS = os.environ.get( "ALLOWED_HOSTS", "localhost,127.0.0.1,django,nginx" ).split(",") # Site domain configuration SITE_DOMAIN = os.environ.get("SITE_DOMAIN", "localhost:8080") # Groups configuration # Parse comma-separated groups from environment variable # Groups can have spaces and capital letters (e.g., "Emacs,Org Social,Elisp") # Slugs are auto-generated (lowercase, spaces become hyphens) def slugify_group(name): """Convert group name to slug (lowercase, spaces to hyphens).""" return name.strip().lower().replace(" ", "-") GROUPS_ENV = os.environ.get("GROUPS", "") if GROUPS_ENV.strip(): # Parse group names (can have spaces and capitals) group_names = [group.strip() for group in GROUPS_ENV.split(",") if group.strip()] # Create mappings between slugs and names GROUPS_MAP = {slugify_group(name): name for name in group_names} ENABLED_GROUPS = list(GROUPS_MAP.keys()) # List of slugs for backward compatibility else: GROUPS_MAP = {} ENABLED_GROUPS = [] # Application definition INSTALLED_APPS = [ "django.contrib.contenttypes", "rest_framework", "django_filters", "huey.contrib.djhuey", "app.public.apps.PublicConfig", "app.feeds.apps.FeedsConfig", "app.feedcontent.apps.FeedcontentConfig", "app.polls.apps.PollsConfig", "app.replies.apps.RepliesConfig", "app.mentions.apps.MentionsConfig", "app.reactions.apps.ReactionsConfig", "app.repliesto.apps.RepliesToConfig", "app.notifications.apps.NotificationsConfig", "app.search.apps.SearchConfig", "app.groups.apps.GroupsConfig", "app.rss.apps.RssConfig", "app.boosts.apps.BoostsConfig", "app.interactions.apps.InteractionsConfig", "app.sse_notifications.apps.SseNotificationsConfig", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "app.feeds.cors_middleware.CORSMiddleware", # Add CORS headers to all responses "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "app.feeds.middleware.RelayMetadataMiddleware", # Add global ETag/Last-Modified headers ] ROOT_URLCONF = "core.urls" TEMPLATES = [] WSGI_APPLICATION = "core.wsgi.application" # Database # https://docs.djangoproject.com/en/5.2/ref/settings/#databases DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", } } # No authentication system needed for this API # Internationalization # https://docs.djangoproject.com/en/5.2/topics/i18n/ LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_TZ = True # No static files needed for API-only application # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" # Django REST Framework settings REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES": [ "app.reactions.renderers.UTF8JSONRenderer", ], "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", "PAGE_SIZE": 20, "DEFAULT_FILTER_BACKENDS": [ "rest_framework.filters.SearchFilter", "rest_framework.filters.OrderingFilter", ], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.AllowAny", ], "DEFAULT_AUTHENTICATION_CLASSES": [], "UNAUTHENTICATED_USER": None, "UNAUTHENTICATED_TOKEN": None, } # Cache configuration def redis_available(): """Check if Redis is available""" try: redis_host = os.environ.get("REDIS_HOST", "redis") redis_port = int(os.environ.get("REDIS_PORT", 6379)) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(1) result = sock.connect_ex((redis_host, redis_port)) sock.close() return result == 0 except Exception: return False if DEBUG or not redis_available(): CACHES = { "default": { "BACKEND": "django.core.cache.backends.dummy.DummyCache", } } else: CACHES = { "default": { "BACKEND": "django.core.cache.backends.redis.RedisCache", "LOCATION": f"redis://{os.environ.get('REDIS_HOST', 'redis')}:{os.environ.get('REDIS_PORT', 6379)}/{os.environ.get('REDIS_CACHE_DB', 1)}", } } # Huey configuration for task queue and cron jobs HUEY = { "huey_class": "huey.RedisHuey", "name": "org-social-relay", "immediate": False, # Required for consumer to run "connection": { "host": os.environ.get("REDIS_HOST", "redis"), "port": int(os.environ.get("REDIS_PORT", 6379)), "db": int(os.environ.get("REDIS_DB", 0)), }, "consumer": { "workers": int(os.environ.get("HUEY_WORKERS", 1)), "worker_type": "thread", }, }