[Feeds] handle non-200 status codes when updating podcasts
[mygpo.git] / mygpo / settings.py
blobf68d27ec67a76a4708b3f3722809edb48f2fea69
1 # Django settings for mygpo project.
3 # This file is part of my.gpodder.org.
5 # my.gpodder.org is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
10 # my.gpodder.org is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
13 # License for more details.
15 # You should have received a copy of the GNU Affero General Public License
16 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
19 import re
20 import sys
21 import os.path
22 import dj_database_url
25 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
28 def get_bool(name, default):
29 return os.getenv(name, str(default)).lower() == 'true'
32 def get_intOrNone(name, default):
33 """ Parses the env variable, accepts ints and literal None"""
34 value = os.getenv(name, str(default))
35 if value.lower() == 'none':
36 return None
37 return int(value)
40 DEBUG = get_bool('DEBUG', False)
42 ADMINS = re.findall(r'\s*([^<]+) <([^>]+)>\s*', os.getenv('ADMINS', ''))
44 MANAGERS = ADMINS
46 DATABASES = {
47 'default': dj_database_url.config(
48 default='postgres://mygpo:mygpo@localhost/mygpo'),
52 _cache_used = bool(os.getenv('CACHE_BACKEND', False))
54 if _cache_used:
55 CACHES = {}
56 CACHES['default'] = {
57 'BACKEND': os.getenv(
58 'CACHE_BACKEND',
59 'django.core.cache.backends.memcached.MemcachedCache'),
60 'LOCATION': os.getenv('CACHE_LOCATION'),
64 # Local time zone for this installation. Choices can be found here:
65 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
66 # although not all choices may be available on all operating systems.
67 # If running in a Windows environment this must be set to the same as your
68 # system time zone.
69 TIME_ZONE = 'UTC'
71 # Language code for this installation. All choices can be found here:
72 # http://www.i18nguy.com/unicode/language-identifiers.html
73 LANGUAGE_CODE = 'en-us'
75 SITE_ID = 1
77 # If you set this to False, Django will make some optimizations so as not
78 # to load the internationalization machinery.
79 USE_I18N = True
81 STATIC_ROOT = 'staticfiles'
82 STATIC_URL = '/media/'
84 STATICFILES_DIRS = (
85 os.path.abspath(os.path.join(BASE_DIR, '..', 'htdocs', 'media')),
89 TEMPLATES = [{
90 'BACKEND': 'django.template.backends.django.DjangoTemplates',
91 'DIRS': [],
92 'OPTIONS': {
93 'context_processors': [
94 'django.contrib.auth.context_processors.auth',
95 'django.template.context_processors.debug',
96 'django.template.context_processors.i18n',
97 'django.template.context_processors.media',
98 'django.template.context_processors.static',
99 'django.template.context_processors.tz',
100 'django.contrib.messages.context_processors.messages',
101 'mygpo.web.google.analytics',
102 'mygpo.web.google.adsense',
103 # make the debug variable available in templates
104 # https://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-debug
105 'django.core.context_processors.debug',
107 # required so that the request obj can be accessed from
108 # templates. this is used to direct users to previous
109 # page after login
110 'django.core.context_processors.request',
112 'loaders': [
113 ('django.template.loaders.cached.Loader', [
114 'django.template.loaders.app_directories.Loader',
121 MIDDLEWARE_CLASSES = (
122 'django.middleware.common.CommonMiddleware',
123 'django.middleware.csrf.CsrfViewMiddleware',
124 'django.contrib.sessions.middleware.SessionMiddleware',
125 'django.contrib.auth.middleware.AuthenticationMiddleware',
126 'django.middleware.locale.LocaleMiddleware',
127 'django.contrib.messages.middleware.MessageMiddleware',
130 ROOT_URLCONF = 'mygpo.urls'
132 INSTALLED_APPS = (
133 'django.contrib.contenttypes',
134 'django.contrib.messages',
135 'django.contrib.admin',
136 'django.contrib.humanize',
137 'django.contrib.auth',
138 'django.contrib.sessions',
139 'django.contrib.staticfiles',
140 'django.contrib.sites',
141 'djcelery',
142 'mygpo.core',
143 'mygpo.podcasts',
144 'mygpo.chapters',
145 'mygpo.search',
146 'mygpo.users',
147 'mygpo.api',
148 'mygpo.web',
149 'mygpo.publisher',
150 'mygpo.subscriptions',
151 'mygpo.history',
152 'mygpo.favorites',
153 'mygpo.usersettings',
154 'mygpo.data',
155 'mygpo.userfeeds',
156 'mygpo.suggestions',
157 'mygpo.directory',
158 'mygpo.categories',
159 'mygpo.episodestates',
160 'mygpo.maintenance',
161 'mygpo.share',
162 'mygpo.administration',
163 'mygpo.pubsub',
164 'mygpo.podcastlists',
165 'mygpo.votes',
168 try:
169 import debug_toolbar
170 INSTALLED_APPS += ('debug_toolbar', )
172 except ImportError:
173 pass
176 try:
177 import opbeat
179 if not DEBUG:
180 INSTALLED_APPS += ('opbeat.contrib.django', )
182 # add opbeat middleware to the beginning of the middleware classes list
183 MIDDLEWARE_CLASSES = \
184 ('opbeat.contrib.django.middleware.OpbeatAPMMiddleware',) + \
185 MIDDLEWARE_CLASSES
187 except ImportError:
188 pass
191 ACCOUNT_ACTIVATION_DAYS = int(os.getenv('ACCOUNT_ACTIVATION_DAYS', 7))
193 AUTHENTICATION_BACKENDS = (
194 'mygpo.users.backend.CaseInsensitiveModelBackend',
195 'mygpo.web.auth.EmailAuthenticationBackend',
198 SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
200 # TODO: use (default) JSON serializer for security
201 # this would currently fail as we're (de)serializing datetime objects
202 # https://docs.djangoproject.com/en/1.5/topics/http/sessions/#session-serialization
203 SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
206 MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
208 USER_CLASS = 'mygpo.users.models.User'
210 LOGIN_URL = '/login/'
212 CSRF_FAILURE_VIEW = 'mygpo.web.views.csrf_failure'
215 DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', '')
217 SECRET_KEY = os.getenv('SECRET_KEY', '')
219 if 'test' in sys.argv:
220 SECRET_KEY = 'test'
222 GOOGLE_ANALYTICS_PROPERTY_ID = os.getenv('GOOGLE_ANALYTICS_PROPERTY_ID', '')
224 DIRECTORY_EXCLUDED_TAGS = os.getenv('DIRECTORY_EXCLUDED_TAGS', '').split()
226 FLICKR_API_KEY = os.getenv('FLICKR_API_KEY', '')
228 SOUNDCLOUD_CONSUMER_KEY = os.getenv('SOUNDCLOUD_CONSUMER_KEY', '')
230 MAINTENANCE = get_bool('MAINTENANCE', False)
233 ALLOWED_HOSTS = ['*']
236 LOGGING = {
237 'version': 1,
238 'disable_existing_loggers': False,
239 'formatters': {
240 'verbose': {
241 'format': '%(asctime)s %(name)s %(levelname)s %(message)s',
244 'filters': {
245 'require_debug_false': {
246 '()': 'django.utils.log.RequireDebugFalse'
249 'handlers': {
250 'console': {
251 'level': os.getenv('LOGGING_CONSOLE_LEVEL', 'DEBUG'),
252 'class': 'logging.StreamHandler',
253 'formatter': 'verbose',
255 'mail_admins': {
256 'level': 'ERROR',
257 'filters': ['require_debug_false'],
258 'class': 'django.utils.log.AdminEmailHandler',
261 'loggers': {
262 'django': {
263 'handlers': os.getenv('LOGGING_DJANGO_HANDLERS',
264 'console').split(),
265 'propagate': True,
266 'level': os.getenv('LOGGING_DJANGO_LEVEL', 'WARN'),
268 'mygpo': {
269 'handlers': os.getenv('LOGGING_MYGPO_HANDLERS', 'console').split(),
270 'level': os.getenv('LOGGING_MYGPO_LEVEL', 'INFO'),
272 'celery': {
273 'handlers': os.getenv('LOGGING_CELERY_HANDLERS',
274 'console').split(),
275 'level': os.getenv('LOGGING_CELERY_LEVEL', 'DEBUG'),
280 _use_log_file = bool(os.getenv('LOGGING_FILENAME', False))
282 if _use_log_file:
283 LOGGING['handlers']['file'] = {
284 'level': 'INFO',
285 'class': 'logging.handlers.RotatingFileHandler',
286 'filename': os.getenv('LOGGING_FILENAME'),
287 'maxBytes': 10000000,
288 'backupCount': 10,
289 'formatter': 'verbose',
293 # minimum number of subscribers a podcast must have to be assigned a slug
294 PODCAST_SLUG_SUBSCRIBER_LIMIT = int(os.getenv(
295 'PODCAST_SLUG_SUBSCRIBER_LIMIT', 10))
297 # minimum number of subscribers that a podcast needs to "push" one of its
298 # categories to the top
299 MIN_SUBSCRIBERS_CATEGORY = int(os.getenv('MIN_SUBSCRIBERS_CATEGORY', 10))
301 # maximum number of episode actions that the API processes immediatelly before
302 # returning the response. Larger requests will be handled in background.
303 # Handler can be set to None to disable
304 API_ACTIONS_MAX_NONBG = int(os.getenv('API_ACTIONS_MAX_NONBG', 100))
305 API_ACTIONS_BG_HANDLER = 'mygpo.api.tasks.episode_actions_celery_handler'
308 ADSENSE_CLIENT = os.getenv('ADSENSE_CLIENT', '')
310 ADSENSE_SLOT_BOTTOM = os.getenv('ADSENSE_SLOT_BOTTOM', '')
312 # we're running behind a proxy that sets the X-Forwarded-Proto header correctly
313 # see https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
314 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
317 # enabled access to staff-only areas with ?staff=<STAFF_TOKEN>
318 STAFF_TOKEN = os.getenv('STAFF_TOKEN', None)
320 # Flattr settings -- available after you register your app
321 FLATTR_KEY = os.getenv('FLATTR_KEY', '')
322 FLATTR_SECRET = os.getenv('FLATTR_SECRET', '')
324 # Flattr thing of the webservice. Will be flattr'd when a user sets
325 # the "Auto-Flattr gpodder.net" option
326 FLATTR_MYGPO_THING = os.getenv(
327 'FLATTR_MYGPO_THING',
328 'https://flattr.com/submit/auto?user_id=stefankoegl&url=http://gpodder.net'
331 # The User-Agent string used for outgoing HTTP requests
332 USER_AGENT = 'gpodder.net (+https://github.com/gpodder/mygpo)'
334 # Base URL of the website that is used if the actually used parameters is not
335 # available. Request handlers, for example, can access the requested domain.
336 # Code that runs in background can not do this, and therefore requires a
337 # default value. This should be set to something like 'http://example.com'
338 DEFAULT_BASE_URL = os.getenv('DEFAULT_BASE_URL', '')
341 ### Celery
343 BROKER_URL = os.getenv('BROKER_URL', 'redis://localhost')
344 CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
346 SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'no-reply@example.com')
348 CELERY_TASK_RESULT_EXPIRES = 60 * 60 # 1h expiry time in seconds
350 CELERY_ACCEPT_CONTENT = ['pickle', 'json']
352 CELERY_SEND_TASK_ERROR_EMAILS = get_bool('CELERY_SEND_TASK_ERROR_EMAILS',
353 False)
355 BROKER_POOL_LIMIT = get_intOrNone('BROKER_POOL_LIMIT', 10)
357 ### Google API
359 GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '')
360 GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '')
362 # URL where users of the site can get support
363 SUPPORT_URL = os.getenv('SUPPORT_URL', '')
366 FEEDSERVICE_URL = os.getenv('FEEDSERVICE_URL', 'http://feeds.gpodder.net/')
368 # Elasticsearch settings
370 ELASTICSEARCH_SERVER = os.getenv('ELASTICSEARCH_SERVER', '127.0.0.1:9200')
371 ELASTICSEARCH_INDEX = os.getenv('ELASTICSEARCH_INDEX', 'mygpo')
372 ELASTICSEARCH_TIMEOUT = float(os.getenv('ELASTICSEARCH_TIMEOUT', '2'))
374 # time for how long an activation is valid; after that, an unactivated user
375 # will be deleted
376 ACTIVATION_VALID_DAYS = int(os.getenv('ACTIVATION_VALID_DAYS', 10))
379 OPBEAT = {
380 "ORGANIZATION_ID": os.getenv('OPBEAT_ORGANIZATION_ID', ''),
381 "APP_ID": os.getenv('OPBEAT_APP_ID', ''),
382 "SECRET_TOKEN": os.getenv('OPBEAT_SECRET_TOKEN', ''),
386 INTERNAL_IPS = os.getenv('INTERNAL_IPS', '').split()
388 EMAIL_BACKEND = os.getenv('EMAIL_BACKEND',
389 'django.core.mail.backends.smtp.EmailBackend')
391 PODCAST_AD_ID = os.getenv('PODCAST_AD_ID')