# SPDX-License-Identifier: AGPL-3.0-or-later
# Hydrilla&Haketilo website logic.
#
# Copyright (C) 2021, 2022 Wojtek Kosior
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#
# I, Wojtek Kosior, thereby promise not to sue for violation of this
# file's license. Although I request that you do not make use of this
# code in a proprietary program, I am not going to enforce this in
# court.
import gettext
import dataclasses as dc
import typing as t
from pathlib import Path
import flask
import werkzeug
import itsdangerous
import jinja2
from . import common_jinja_templates
here = Path(__file__).resolve().parent
supported_locales = {'en_US', 'pl_PL'}
default_locale = 'en_US'
def choose_locale() -> None:
app = t.cast(HydrillaWebsite, flask.current_app)
user_chosen_locale = flask.request.cookies.get('chosen-locale')
if user_chosen_locale not in supported_locales:
user_chosen_locale = None
if user_chosen_locale is None:
best_locale_match = flask.request.accept_languages.best_match(
supported_locales,
default = default_locale
)
if best_locale_match is None:
app._hydrilla_request_locale = default_locale
else:
app._hydrilla_request_locale = best_locale_match
else:
app._hydrilla_request_locale = user_chosen_locale
translations = gettext.translation(
'messages',
localedir = here / 'locales',
languages = [app._hydrilla_request_locale]
)
app.jinja_env.install_gettext_translations(translations)
@dc.dataclass(init=False)
class HydrillaWebsite(flask.Flask):
_hydrilla_request_locale: str
def __init__(self) -> None:
super().__init__(__name__)
loaders = [jinja2.PackageLoader(__package__)]
combined_loader = common_jinja_templates.combine_with_loaders(loaders)
self.jinja_options = {
**self.jinja_options,
'loader': combined_loader,
'autoescape': jinja2.select_autoescape(['.jinja']),
'lstrip_blocks': True,
'extensions': [
*self.jinja_options.get('extensions', []),
'jinja2.ext.i18n',
'jinja2.ext.do'
]
}
self.before_request(choose_locale)
website_app = HydrillaWebsite()
@website_app.route('/', methods=['GET'])
def main() -> str:
return flask.render_template(
'index.html.jinja',
locale_serializer = itsdangerous.Serializer(secret, salt='set_locale')
)
@website_app.route('/favicon.ico', methods=['GET'])
def favicon() -> str:
return flask.send_file('static/haketilo-favicon.ico')
@website_app.route('/downloads', methods=['GET'])
def downloads() -> str:
return flask.render_template('downloads.html.jinja')
@website_app.route('/set-lang', methods=['POST'])
def set_locale() -> werkzeug.Response:
serializer = itsdangerous.Serializer(secret, salt='set_locale')
new_locale = serializer.loads(flask.request.form['lang_code'])
response = flask.redirect(flask.url_for('main') + '#langs', code=303)
response.set_cookie(key='chosen-locale', value=new_locale, path='/')
return response
secret = 'not-so-secret'
def set_secret(new_secret: str) -> None:
global secret
secret = new_secret