Spaces:
Running
Running
import os | |
from pathlib import Path | |
from datetime import timedelta | |
from urllib.parse import urlparse | |
import nltk | |
from nltk.data import find | |
from os import getenv | |
from decouple import config | |
# def download_nltk_data(): | |
# try: | |
# find('tokenizers/punkt') | |
# except LookupError: | |
# nltk.download('punkt') | |
# try: | |
# find('corpora/stopwords') | |
# except LookupError: | |
# nltk.download('stopwords') | |
# # Call the function to ensure the required NLTK data is available | |
# download_nltk_data() | |
# Replace the DATABASES section of your settings.py with this | |
tmpPostgres = urlparse(config("DATABASE_URL")) | |
DATABASES = { | |
'default': { | |
'ENGINE': 'django.db.backends.postgresql', | |
'NAME': 'tunevault', | |
'USER': 'tunevault_owner', | |
'PASSWORD': config('DB_PASS'), | |
'HOST': 'ep-patient-resonance-a19rwm71.ap-southeast-1.aws.neon.tech', | |
'PORT': '5432', | |
'OPTIONS': { | |
'sslmode': 'require', | |
}, | |
}, | |
'songs': { | |
'ENGINE': 'django.db.backends.postgresql', | |
'NAME': 'tunevault', | |
'USER': 'tunevault_owner', | |
'PASSWORD': config('DB_PASS'), | |
'HOST': 'ep-patient-resonance-a19rwm71.ap-southeast-1.aws.neon.tech', | |
'PORT': '5432', | |
'OPTIONS': { | |
'sslmode': 'require', | |
}, | |
} | |
} | |
SPOTIFY_CLIENT_ID = config('SPOTIFY_CLIENT_ID') | |
SPOTIFY_CLIENT_SECRET = config('SPOTIFY_CLIENT_SECRET') | |
SPOTIFY_REDIRECT_URI = 'http://localhost:8000/spotify/callback' | |
# Google OAuth Settings | |
GOOGLE_CLIENT_ID = config('OAUTH_CLIENT_ID', default='') | |
GOOGLE_CLIENT_SECRET = config('OAUTH_CLIENT_SECRET', default='') | |
GOOGLE_REDIRECT_URI = config('GOOGLE_REDIRECT_URI', default='http://localhost:3000/auth/google/callback') | |
BASE_DIR = Path(__file__).resolve().parent.parent | |
SECRET_KEY = 'your-secret-key-here' | |
DEBUG = True | |
ALLOWED_HOSTS = [ | |
'songporter.onrender.com', | |
'songporter.vercel.app', | |
'localhost', | |
'127.0.0.1' | |
] | |
INSTALLED_APPS = [ | |
'django.contrib.admin', | |
'django.contrib.auth', | |
'django.contrib.contenttypes', | |
'django.contrib.sessions', | |
'django.contrib.messages', | |
'django.contrib.staticfiles', | |
'django.contrib.sites', | |
# Third-party apps | |
'rest_framework', | |
'rest_framework.authtoken', | |
'allauth', | |
'allauth.account', | |
'allauth.socialaccount', | |
'allauth.socialaccount.providers.google', | |
'youtube_dl', | |
'corsheaders', | |
'django_celery_results', | |
'drf_yasg', | |
# Local apps | |
'users', | |
'songs', | |
] | |
MIDDLEWARE = [ | |
'django.middleware.security.SecurityMiddleware', | |
'whitenoise.middleware.WhiteNoiseMiddleware', | |
'django.contrib.sessions.middleware.SessionMiddleware', | |
'corsheaders.middleware.CorsMiddleware', | |
'django.middleware.common.CommonMiddleware', | |
'django.middleware.csrf.CsrfViewMiddleware', | |
'django.contrib.auth.middleware.AuthenticationMiddleware', | |
'django.contrib.messages.middleware.MessageMiddleware', | |
'django.middleware.clickjacking.XFrameOptionsMiddleware', | |
'allauth.account.middleware.AccountMiddleware', # Add this line | |
] | |
ROOT_URLCONF = 'tunevault.urls' | |
TEMPLATES = [ | |
{ | |
'BACKEND': 'django.template.backends.django.DjangoTemplates', | |
'DIRS': [], | |
'APP_DIRS': True, | |
'OPTIONS': { | |
'context_processors': [ | |
'django.template.context_processors.debug', | |
'django.template.context_processors.request', | |
'django.contrib.auth.context_processors.auth', | |
'django.contrib.messages.context_processors.messages', | |
], | |
}, | |
}, | |
] | |
WSGI_APPLICATION = 'tunevault.wsgi.application' | |
AUTH_USER_MODEL = 'users.CustomUser' | |
AUTH_PASSWORD_VALIDATORS = [ | |
{ | |
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | |
}, | |
] | |
LANGUAGE_CODE = 'en-us' | |
TIME_ZONE = 'UTC' | |
USE_I18N = True | |
USE_TZ = True | |
STATIC_URL = '/static/' | |
# This production code might break development mode, so we check whether we're in DEBUG mode | |
if not DEBUG: # Tell Django to copy static assets into a path called `staticfiles` (this is specific to Render) | |
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') | |
# Enable the WhiteNoise storage backend, which compresses static files to reduce disk use | |
# and renames the files with unique names for each version to support long-term caching | |
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' | |
MEDIA_URL = '/media/' | |
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') | |
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' | |
# Django AllAuth settings | |
AUTHENTICATION_BACKENDS = [ | |
'django.contrib.auth.backends.ModelBackend', | |
'allauth.account.auth_backends.AuthenticationBackend', | |
] | |
SITE_ID = 1 | |
SOCIALACCOUNT_PROVIDERS = { | |
'google': { | |
'APP': { | |
'client_id': GOOGLE_CLIENT_ID, | |
'secret': GOOGLE_CLIENT_SECRET, | |
'key': '' | |
}, | |
'SCOPE': [ | |
'profile', | |
'email', | |
], | |
'AUTH_PARAMS': { | |
'access_type': 'online', | |
}, | |
'OAUTH_PKCE_ENABLED': True, | |
'VERIFIED_EMAIL': True, | |
} | |
} | |
# Django allauth config | |
ACCOUNT_EMAIL_VERIFICATION = 'none' # Set to 'mandatory' in production | |
ACCOUNT_SIGNUP_FIELDS = ['email*', 'username*', 'password1*', 'password2*'] | |
ACCOUNT_LOGIN_METHODS = {'email'} | |
# Login/logout URLs | |
LOGIN_REDIRECT_URL = '/' | |
LOGOUT_REDIRECT_URL = '/' | |
# Django Rest Framework settings | |
REST_FRAMEWORK = { | |
'DEFAULT_AUTHENTICATION_CLASSES': [ | |
'rest_framework.authentication.TokenAuthentication', | |
'rest_framework.authentication.SessionAuthentication', | |
], | |
'DEFAULT_PERMISSION_CLASSES': [ | |
'rest_framework.permissions.IsAuthenticated', | |
], | |
'DEFAULT_THROTTLE_CLASSES': [ | |
'rest_framework.throttling.AnonRateThrottle', | |
'rest_framework.throttling.UserRateThrottle' | |
], | |
'DEFAULT_THROTTLE_RATES': { | |
'anon': '100/day', | |
'user': '1000/day' | |
}, | |
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', | |
} | |
# Celery Configuration | |
CELERY_BROKER_URL = 'redis://default:Rh3mejxoZ1eRjMvtFnQWl79HezdWnKZV@redis-18712.crce182.ap-south-1-1.ec2.redns.redis-cloud.com:18712' | |
CELERY_RESULT_BACKEND = 'redis://default:Rh3mejxoZ1eRjMvtFnQWl79HezdWnKZV@redis-18712.crce182.ap-south-1-1.ec2.redns.redis-cloud.com:18712' | |
CELERY_ACCEPT_CONTENT = ['json'] | |
CELERY_TASK_SERIALIZER = 'json' | |
CELERY_RESULT_SERIALIZER = 'json' | |
CELERY_TIMEZONE = TIME_ZONE | |
CELERY_TASK_TRACK_STARTED = True | |
CELERY_TASK_TIME_LIMIT = 30 * 60 | |
# Define Celery Beat schedule | |
from celery.schedules import crontab | |
CELERY_BEAT_SCHEDULE = { | |
'cleanup-cache-daily': { | |
'task': 'songs.tasks.cleanup_cache', | |
'schedule': crontab(hour=2, minute=0), # Run at 2:00 AM every day | |
'options': { | |
'expires': 3600, # Expires after 1 hour | |
}, | |
}, | |
} | |
# Redis Cache | |
CACHES = { | |
"default": { | |
"BACKEND": "django_redis.cache.RedisCache", | |
"LOCATION": "redis://default:Rh3mejxoZ1eRjMvtFnQWl79HezdWnKZV@redis-18712.crce182.ap-south-1-1.ec2.redns.redis-cloud.com:18712", | |
"OPTIONS": { | |
"CLIENT_CLASS": "django_redis.client.DefaultClient", | |
} | |
} | |
} | |
# Logging | |
LOGGING = { | |
'version': 1, | |
'disable_existing_loggers': False, | |
'formatters': { | |
'verbose': { | |
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', | |
'style': '{', | |
}, | |
'simple': { | |
'format': '{levelname} {message}', | |
'style': '{', | |
}, | |
}, | |
'handlers': { | |
'file': { | |
'level': 'DEBUG', | |
'class': 'logging.FileHandler', | |
'filename': 'debug.log', | |
'formatter': 'verbose', | |
}, | |
'console': { | |
'level': 'INFO', | |
'class': 'logging.StreamHandler', | |
'formatter': 'simple', | |
}, | |
}, | |
'loggers': { | |
'django': { | |
'handlers': ['file', 'console'], | |
'level': 'INFO', | |
'propagate': True, | |
}, | |
'songs': { | |
'handlers': ['file', 'console'], | |
'level': 'DEBUG', | |
'propagate': True, | |
}, | |
}, | |
} | |
# CORS settings | |
CORS_ALLOW_ALL_ORIGINS = True # For development only, restrict in production | |
CORS_EXPOSE_HEADERS = ['X-Thumbnail-URL', 'X-Song-Title', 'X-Song-Artist'] | |
# Swagger settings | |
SWAGGER_SETTINGS = { | |
'SECURITY_DEFINITIONS': { | |
'Bearer': { | |
'type': 'apiKey', | |
'name': 'Authorization', | |
'in': 'header' | |
} | |
}, | |
'USE_SESSION_AUTH': True, | |
'DEFAULT_INFO': 'tunevault.urls.api_info', | |
'OPERATIONS_SORTER': 'alpha', | |
'TAGS_SORTER': 'alpha', | |
'VALIDATOR_URL': None, | |
} | |
# Sentry configuration for error monitoring | |
import sentry_sdk | |
from sentry_sdk.integrations.django import DjangoIntegration | |
from sentry_sdk.integrations.celery import CeleryIntegration | |
sentry_sdk.init( | |
dsn="", # Add your Sentry DSN when deployed | |
integrations=[ | |
DjangoIntegration(), | |
CeleryIntegration(), | |
], | |
traces_sample_rate=0.1, | |
send_default_pii=True | |
) | |
# Rate limiting settings | |
RATELIMIT_USE_CACHE = 'default' | |
RATELIMIT_VIEW = 'songs.views.ratelimited_error' | |
RATELIMIT_ENABLE = True | |
# Format support | |
SUPPORTED_AUDIO_FORMATS = ['mp3', 'aac'] | |
DEFAULT_AUDIO_FORMAT = 'mp3' | |
# Hugging Face Space URLs | |
HUGGINGFACE_RECOMMENDATION_URL = "https://monilm-songporter.hf.space/recommendations/" | |
HUGGINGFACE_ARTIST_INFO_URL = "https://monilm-songporter.hf.space/artist-info/" | |