Skip to content
Snippets Groups Projects
app.py 36.9 KiB
Newer Older
@cache.cached(key_prefix=cache_key_prefix_view)
@add_links(PRECONNECT_HEADERS + JS_LINK_HEADERS + CSS_LINK_HEADERS)
Cédric Krier's avatar
Cédric Krier committed
def donate_thanks():
    return render_template('donate_thanks.html.jinja')
Cédric Krier's avatar
Cédric Krier committed


@app.route('/donate/cancel')
@cache.cached(key_prefix=cache_key_prefix_view)
@add_links(PRECONNECT_HEADERS + JS_LINK_HEADERS + CSS_LINK_HEADERS)
Cédric Krier's avatar
Cédric Krier committed
def donate_cancel():
    return render_template('donate_cancel.html.jinja')
class Service(enum.Flag):
    NONE = 0
    CONSULTING = enum.auto()
    DEVELOPMENT = enum.auto()
    HOSTING = enum.auto()
    TRAINING = enum.auto()


class Provider:
    def __init__(self, name, positions, services=Service.NONE):
        self.name = name
        self.positions = positions
        self.services = services

    def __getattr__(self, name):
        if self.services:
            return self.services & getattr(Service, name.upper())

    def __json__(self):
        return {
            'name': self.name,
            'positions': self.positions,
            }


PROVIDERS = [
    Provider(name="ACK",
        positions=[(43.29464884900557, -3.001523942912372)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.TRAINING),
    Provider(name="Adiczion",
        positions=[(43.52153, 5.43150)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="B2CK",
        positions=[(50.631123, 5.567552)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.TRAINING),
    Provider(name="Coopengo",
        positions=[(48.873278, 2.324776)],
        services=Service.DEVELOPMENT),
    Provider(name="Datalife",
        positions=[(37.9596885, -1.2086241)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="First Telecom",
        positions=[(38.0131591, 23.7721521)],
        services=Service.CONSULTING),
    Provider(name="gcoop",
        positions=[(-34.59675, -58.43035)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="IntegraPer",
        positions=[(-11.9753824, -77.0860785)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="INROWGA",
        positions=[(18.476389, -69.893333)],
        services=Service.CONSULTING),
    Provider(name="Kopen Software",
        positions=[(41.5995983, 0.5799085)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.HOSTING
        | Service.TRAINING),
    Provider(name="Lampero",
        positions=[(44.4758631, 25.8231538)],
        services=Service.CONSULTING),
    Provider(name="Lava Lab Software",
        positions=[(-27.978905, 153.389466)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="m-ds",
        positions=[(52.520008, 13.404954)],
Cédric Krier's avatar
Cédric Krier committed
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.HOSTING
        | Service.TRAINING),
    Provider(name="NaN-tic",
        positions=[(41.544063, 2.115122)],
        services=Service.CONSULTING | Service.DEVELOPMENT),
    Provider(name="power solutions",
        positions=[(47.0467674, 8.3048232)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.HOSTING),
    Provider(name="SISalp",
        positions=[(45.903956, 6.099937), (43.132028, 5.935532)],
        services=Service.CONSULTING | Service.HOSTING),
    Provider(name="Virtual Things",
        positions=[(48.13585, 11.577415), (50.775116, 6.083565)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.TRAINING),
    Provider(name="Wuerfel Datentechnik",
        positions=[(49.24776, 8.87911)],
        services=Service.CONSULTING | Service.DEVELOPMENT | Service.TRAINING),
@app.route('/service-providers')
@cache.cached(key_prefix=cache_key_prefix_view, query_string=True)
@add_links(PRECONNECT_HEADERS + JS_LINK_HEADERS + CSS_LINK_HEADERS)
def service_providers():
    providers = PROVIDERS.copy()
    shuffle(providers)
    services = []
    environ = {}
    filters = {'consulting', 'development', 'hosting', 'training'}
    if not (request.args.keys() <= filters):
        abort(HTTPStatus.BAD_REQUEST)
    for filter_name in filters:
        environ[filter_name] = request.args.get(filter_name, type=int)
        if (environ[filter_name] is not None
                and environ[filter_name] not in {0, 1}):
            abort(HTTPStatus.BAD_REQUEST)
        if environ[filter_name]:
            services.append(getattr(Service, filter_name.upper()))
    if services:
        services = functools.reduce(operator.ior, services)
        providers = list(
            filter(lambda p: (p.services & services) == services, providers))
    return render_template(
        'service_providers.html.jinja', providers=providers, **environ)
@app.route('/services.html', endpoint='service_providers-alt')
def service_providers_alt():
    return redirect(url_for('service_providers'))


@app.route('/service-providers/start')
@cache.cached(key_prefix=cache_key_prefix_view)
@add_links(PRECONNECT_HEADERS + JS_LINK_HEADERS + CSS_LINK_HEADERS)
def service_providers_start():
    return render_template('service_providers_start.html.jinja')
@app.route('/favicon.ico')
def favicon():
    return redirect(url_for('static', filename='images/favicon.ico'))


@app.route('/_warmup')
def warmup():
    fetch_news_items()
    fetch_events()
    for supporter in fetch_supporters():
        hash = hashlib.md5(supporter['email'].encode('utf-8')).hexdigest()
        try:
            fetch_gravatar(
                hash, s='198', d=gravatar.default, r=gravatar.rating)
        except Exception:
            app.logger.warning('fail to fetch gravatar')
Cédric Krier's avatar
Cédric Krier committed
    for path in glob.glob(os.path.join(app.static_folder, '**/*.webp')):
        dominant_color(os.path.relpath(path, app.static_folder))
@app.errorhandler(HTTPStatus.NOT_FOUND)
@cache.cached(key_prefix=cache_key_prefix_view)
@add_links(PRECONNECT_HEADERS + JS_LINK_HEADERS + CSS_LINK_HEADERS)
def not_found(error):
    return render_template(
        'not_found.html.jinja', canonical=None), HTTPStatus.NOT_FOUND
class RequestFormatter(logging.Formatter):
    def format(self, record):
        record.url = request.url
        record.remote_addr = request.remote_addr
        return super().format(record)


mail_handler = SMTPHandler(
    mailhost='mx.tryton.org',
    fromaddr='www@tryton.org',
    toaddrs=['webmaster@tryton.org'],
    subject="[www.tryton.org] Application Error",
    )
mail_handler.setLevel(logging.ERROR)
formatter = RequestFormatter(
    '[%(asctime)s] %(remote_addr)s requested %(url)s\n'
    '%(levelname)s in %(module)s: %(message)s'
    )
default_handler.setFormatter(formatter)
mail_handler.setFormatter(formatter)

Cédric Krier's avatar
Cédric Krier committed
if __name__ == '__main__':
    app.config['CDN_DEBUG'] = ast.literal_eval(
        os.environ.get('CDN_DEBUG', 'True'))
    app.run(debug=ast.literal_eval(os.environ.get('DEBUG', 'True')))

if not app.debug:
    app.logger.addHandler(mail_handler)