from flask import Flask, request, render_template from typing import TypedDict import configparser import sqlite3 import os class Config(TypedDict): dbPath: str def parseConfig() -> Config: cfg_path = os.environ.get("CONFIG", "/etc/ftth-ipe-map/conf.ini") cfg = configparser.ConfigParser() with open(cfg_path, "r") as f: cfg.read_file(f) return {'dbPath':cfg.get("DB","path")} app = Flask(__name__) cfg:Config = parseConfig() @app.route("/", methods=["GET"]) def getMap(): return render_template("map.html") @app.route("/eligdata", methods=["GET"]) def getEligData(): args = request.args valid_args = True processed_args = {} for k in ['swx', 'swy', 'nex', 'ney']: valid_args = valid_args and k in args if valid_args: try: processed_args[k] = float(args[k]) except ValueError: valid_args = False if valid_args: cur = cursorWithSpatialite() # Let's first see how big is the area we're about to query. # If it's too big, abort the request to prevent a server DOS. cur.execute(''' SELECT Area(BuildMBR(:swx,:swy,:nex,:ney,4326)) ''',processed_args) req_area = cur.fetchone()[0] if req_area <= 0.08: cur.execute(''' SELECT X(ImmeubleGeoPoint), Y(ImmeubleGeoPoint), IdentifiantImmeuble, EtatImmeuble, NumeroVoieImmeuble, TypeVoieImmeuble, NomVoieImmeuble FROM ipe WHERE ROWID IN ( SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'ipe' AND search_frame = BuildMBR(:swx, :swy, :nex, :ney, 4326)) ''',processed_args) buildings = [ { 'x':b[0], 'y':b[1], 'idImm':b[2], 'etatImm':b[3], 'numVoieImm': b[4], 'typeVoieImm': b[5], 'nomVoieImm': b[6] } for b in cur.fetchall()] return { "buildings": buildings} else: return "The requested area is too wide, please reduce it", 400 else: return "Invalid bounding box coordinates", 400 def cursorWithSpatialite(): db = sqlite3.connect(cfg['dbPath']) cur = db.cursor() db.enable_load_extension(True) cur.execute('SELECT load_extension("mod_spatialite")') return cur