Files
i2p.www/i2p2www/__init__.py

250 lines
6.2 KiB
Python
Raw Normal View History

2013-12-12 06:16:00 +00:00
# -*- coding: utf-8 -*-
2012-12-19 12:00:12 +00:00
from flask import Flask, request, g, redirect, url_for, abort, render_template, send_from_directory, safe_join
try:
from flaskext.babel import Babel
except ImportError:
from flask_babel import Babel
try:
from flask.ext.cache import Cache
except ImportError:
from flask_cache import Cache
2012-06-03 01:06:09 +00:00
from docutils.core import publish_parts
2012-06-01 21:15:42 +00:00
import os.path
2012-06-01 23:15:41 +00:00
import os
2012-06-01 21:15:42 +00:00
2013-08-31 04:48:31 +00:00
try:
from i2p2www import settings
except ImportError:
settings = None
2014-12-01 01:58:04 +00:00
###########
# Constants
2015-09-13 17:58:04 +00:00
CURRENT_I2P_VERSION = '0.9.22'
2014-01-06 23:49:42 +00:00
CANONICAL_DOMAIN = 'geti2p.net'
2013-08-31 04:48:31 +00:00
CACHE_CONFIG = settings.CACHE_CONFIG if settings and hasattr(settings, 'CACHE_CONFIG') else {
'CACHE_DEFAULT_TIMEOUT': 600,
}
2013-08-31 04:31:20 +00:00
BLOG_POSTS_PER_FEED = 10
BLOG_POSTS_PER_PAGE = 10
MEETINGS_PER_PAGE = 20
# This list defines the order that languages appear in the dropdown.
SUPPORTED_LANGS = [
'en',
'de',
'es',
'fr',
'ru',
2014-02-04 10:10:38 +00:00
'zh',
'ar',
'id',
'he',
2013-12-12 06:16:00 +00:00
'it',
'ja',
'ko',
'mg',
2014-07-07 03:34:47 +00:00
'nl',
2015-05-14 04:40:16 +00:00
'fa',
2013-12-12 06:16:00 +00:00
'pl',
'pt',
'pt_BR',
'ro',
2015-05-14 04:40:16 +00:00
'fi',
2014-02-04 10:10:38 +00:00
'sv',
'uk',
]
2013-12-12 06:16:00 +00:00
SUPPORTED_LANG_NAMES = {
2015-05-14 04:40:16 +00:00
'ar': u'Arabic العربية',
'id': u'Bahasa Indonesia',
2015-05-14 04:40:16 +00:00
'zh': u'Chinese 中文',
'de': u'Deutsch',
2013-12-12 06:16:00 +00:00
'en': u'English',
'es': u'Castellano',
'fr': u'Français',
'he': u'Hebrew עברית',
2013-12-12 06:16:00 +00:00
'it': u'Italiano',
2015-05-14 04:40:16 +00:00
'ja': u'Japanese 日本語',
'ko': u'Korean 한국말',
'mg': u'Fiteny Malagasy',
2014-07-07 03:34:47 +00:00
'nl': u'Nederlands',
2015-05-14 04:40:16 +00:00
'fa': u'Persian فارسی',
'pl': u'Polski',
'pt': u'Português',
'pt_BR': u'Português do Brasil',
2015-05-14 04:40:16 +00:00
'ro': u'Română',
'ru': u'Russian Русский язык',
'fi': u'Suomi',
2014-02-04 10:10:38 +00:00
'sv': u'Svenska',
2015-05-14 04:40:16 +00:00
'uk': u'Ukrainian Українська',
2013-12-12 06:16:00 +00:00
}
RTL_LANGS = [
'he',
'ar',
]
DEFAULT_GETTEXT_DOMAIN = 'priority'
GETTEXT_DOMAIN_MAPPING = {
'about': ['about'],
'blog': ['blog'],
'comparison': ['comparison'],
'docs': ['docs'],
'get-involved': ['get-involved'],
'misc': ['misc'],
'research': ['research'],
}
2012-06-01 21:15:42 +00:00
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
2012-06-01 23:15:41 +00:00
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
2012-06-03 01:06:09 +00:00
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings/logs')
SITE_DIR = os.path.join(TEMPLATE_DIR, 'site')
MIRRORS_FILE = os.path.join(TEMPLATE_DIR, 'downloads/mirrors')
2013-08-11 13:05:05 +00:00
ANONBIB_CFG = os.path.join(TEMPLATE_DIR, 'papers/anonbib.cfg')
ANONBIB_FILE = os.path.join(TEMPLATE_DIR, 'papers/anonbib.bib')
2012-06-01 21:15:42 +00:00
###################
# Application setup
2012-12-05 01:21:34 +00:00
class MyFlask(Flask):
jinja_options = dict(Flask.jinja_options)
jinja_options.setdefault('extensions',
[]).append('i2p2www.extensions.HighlightExtension')
app = application = MyFlask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR)
2012-06-01 21:15:42 +00:00
app.debug = bool(os.environ.get('APP_DEBUG', 'False'))
babel = Babel(app, default_domain=DEFAULT_GETTEXT_DOMAIN)
2013-08-31 04:48:31 +00:00
cache = Cache(app, config=CACHE_CONFIG)
#################
# Babel selectors
@babel.localeselector
def get_locale():
# If the language is already set from the url, use that
if hasattr(g, 'lang'):
return g.lang
# otherwise try to guess the language from the user accept
# header the browser transmits. The best match wins.
return request.accept_languages.best_match(SUPPORTED_LANGS)
2012-06-01 21:15:42 +00:00
@babel.domainselector
def get_domains():
domains = []
frags = request.path.split('/', 2)
if len(frags) == 3:
path = frags[2]
for subpath in GETTEXT_DOMAIN_MAPPING:
if path.startswith(subpath):
domains.extend(GETTEXT_DOMAIN_MAPPING[subpath])
# Always end with the priority domain, as it contains
# various template strings and is likely to be the most
# up-to-date (in case of any common translation strings).
domains.append(DEFAULT_GETTEXT_DOMAIN)
return domains
2012-09-10 12:14:29 +00:00
##########################
# Hooks - helper functions
def after_this_request(f):
if not hasattr(g, 'after_request_callbacks'):
g.after_request_callbacks = []
g.after_request_callbacks.append(f)
return f
2012-09-10 12:14:29 +00:00
###########################
# Hooks - url preprocessing
@app.url_value_preprocessor
def pull_lang(endpoint, values):
if not values:
return
g.lang=values.pop('lang', None)
2012-06-03 01:06:09 +00:00
@app.url_defaults
def set_lang(endpoint, values):
if not values:
return
if endpoint == 'static':
# Static urls shouldn't have a lang flag
# (causes complete reload on lang change)
return
2012-06-03 01:06:09 +00:00
if 'lang' in values:
return
if hasattr(g, 'lang'):
values['lang'] = g.lang
2012-09-10 12:14:29 +00:00
########################
# Hooks - before request
# Detect and store chosen theme
@app.before_request
def detect_theme():
theme = 'duck'
if 'style' in request.cookies:
theme = request.cookies['style']
if 'theme' in request.args.keys():
theme = request.args['theme']
# TEMPORARY: enable external themes
# TODO: Remove this (and the corresponding lines in global/layout.html
if theme[:7] == 'http://':
g.exttheme = theme
theme = 'duck'
if not os.path.isfile(safe_join(safe_join(STATIC_DIR, 'styles'), '%s/desktop.css' % theme)):
theme = 'duck'
g.theme = theme
@after_this_request
def remember_theme(resp):
if g.theme == 'duck' and 'style' in request.cookies:
resp.delete_cookie('style')
elif g.theme != 'duck':
resp.set_cookie('style', g.theme)
return resp
2012-06-01 23:15:41 +00:00
2012-09-10 12:14:29 +00:00
#######################
# Hooks - after request
@app.after_request
def call_after_request_callbacks(response):
for callback in getattr(g, 'after_request_callbacks', ()):
response = callback(response)
return response
##################
# Template filters
@app.template_filter('restructuredtext')
def restructuredtext(value):
parts = publish_parts(source=value, writer_name="html")
return parts['html_body']
################
2012-09-10 11:56:51 +00:00
# Error handlers
2012-06-03 01:06:09 +00:00
@app.errorhandler(404)
def page_not_found(error):
return render_template('global/error_404.html'), 404
2012-09-10 11:28:34 +00:00
2012-09-11 00:17:00 +00:00
@app.errorhandler(500)
def server_error(error):
return render_template('global/error_500.html'), 500
# Import these to ensure they get loaded
import templatevars
2012-12-19 21:30:06 +00:00
import urls