aboutsummaryrefslogtreecommitdiff
# 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