Initial commit: OpenMaps project
This commit is contained in:
219
app.py
Normal file
219
app.py
Normal file
@@ -0,0 +1,219 @@
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
import requests
|
||||
import time
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
NOMINATIM_SEARCH_URL = "https://nominatim.openstreetmap.org/search"
|
||||
NOMINATIM_REVERSE_URL = "https://nominatim.openstreetmap.org/reverse"
|
||||
|
||||
# Nominatim asks clients to identify themselves.
|
||||
HEADERS = {
|
||||
"User-Agent": "LibreMapViewer/1.0 (local Flask application)"
|
||||
}
|
||||
|
||||
# Very simple rate limiting so we don't hammer Nominatim.
|
||||
last_request_time = 0
|
||||
MIN_REQUEST_INTERVAL = 1.0
|
||||
|
||||
|
||||
def nominatim_request(url, params):
|
||||
"""
|
||||
Make a request to Nominatim while respecting a small
|
||||
delay between requests.
|
||||
"""
|
||||
global last_request_time
|
||||
|
||||
elapsed = time.time() - last_request_time
|
||||
|
||||
if elapsed < MIN_REQUEST_INTERVAL:
|
||||
time.sleep(MIN_REQUEST_INTERVAL - elapsed)
|
||||
|
||||
response = requests.get(
|
||||
url,
|
||||
params=params,
|
||||
headers=HEADERS,
|
||||
timeout=15
|
||||
)
|
||||
|
||||
last_request_time = time.time()
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.route("/search")
|
||||
def search():
|
||||
query = request.args.get("q", "").strip()
|
||||
|
||||
if not query:
|
||||
return jsonify({
|
||||
"error": "Please enter a location"
|
||||
}), 400
|
||||
|
||||
params = {
|
||||
"q": query,
|
||||
"format": "jsonv2",
|
||||
"limit": 8,
|
||||
"addressdetails": 1,
|
||||
"extratags": 1,
|
||||
"namedetails": 1,
|
||||
"dedupe": 1,
|
||||
}
|
||||
|
||||
try:
|
||||
results = nominatim_request(
|
||||
NOMINATIM_SEARCH_URL,
|
||||
params
|
||||
)
|
||||
|
||||
except requests.RequestException as e:
|
||||
return jsonify({
|
||||
"error": f"Search failed: {e}"
|
||||
}), 500
|
||||
|
||||
normalized = []
|
||||
|
||||
for item in results:
|
||||
|
||||
normalized.append({
|
||||
"place_id": item.get("place_id"),
|
||||
|
||||
"osm_type": item.get("osm_type"),
|
||||
"osm_id": item.get("osm_id"),
|
||||
|
||||
"display_name":
|
||||
item.get("display_name", ""),
|
||||
|
||||
"lat":
|
||||
float(item["lat"]),
|
||||
|
||||
"lon":
|
||||
float(item["lon"]),
|
||||
|
||||
"type":
|
||||
item.get("type"),
|
||||
|
||||
"category":
|
||||
item.get("category"),
|
||||
|
||||
"address":
|
||||
item.get("address", {}),
|
||||
|
||||
"extratags":
|
||||
item.get("extratags", {}),
|
||||
|
||||
"namedetails":
|
||||
item.get("namedetails", {}),
|
||||
|
||||
"importance":
|
||||
item.get("importance", 0),
|
||||
|
||||
"boundingbox":
|
||||
item.get("boundingbox"),
|
||||
})
|
||||
|
||||
return jsonify(normalized)
|
||||
|
||||
|
||||
@app.route("/geocode")
|
||||
def geocode():
|
||||
|
||||
lat = request.args.get("lat")
|
||||
lon = request.args.get("lon")
|
||||
|
||||
if not lat or not lon:
|
||||
return jsonify({
|
||||
"error": "Missing latitude or longitude"
|
||||
}), 400
|
||||
|
||||
try:
|
||||
lat = float(lat)
|
||||
lon = float(lon)
|
||||
except ValueError:
|
||||
return jsonify({
|
||||
"error": "Invalid latitude or longitude"
|
||||
}), 400
|
||||
|
||||
params = {
|
||||
"lat": lat,
|
||||
"lon": lon,
|
||||
|
||||
"format": "jsonv2",
|
||||
|
||||
"zoom": 18,
|
||||
|
||||
"addressdetails": 1,
|
||||
|
||||
"extratags": 1,
|
||||
|
||||
"namedetails": 1,
|
||||
}
|
||||
|
||||
try:
|
||||
|
||||
result = nominatim_request(
|
||||
NOMINATIM_REVERSE_URL,
|
||||
params
|
||||
)
|
||||
|
||||
except requests.RequestException as e:
|
||||
|
||||
return jsonify({
|
||||
"error": f"Reverse geocoding failed: {e}"
|
||||
}), 500
|
||||
|
||||
if not result:
|
||||
|
||||
return jsonify({
|
||||
"display_name": None
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
|
||||
"place_id":
|
||||
result.get("place_id"),
|
||||
|
||||
"osm_type":
|
||||
result.get("osm_type"),
|
||||
|
||||
"osm_id":
|
||||
result.get("osm_id"),
|
||||
|
||||
"display_name":
|
||||
result.get("display_name", ""),
|
||||
|
||||
"lat":
|
||||
float(result.get("lat", lat)),
|
||||
|
||||
"lon":
|
||||
float(result.get("lon", lon)),
|
||||
|
||||
"type":
|
||||
result.get("type"),
|
||||
|
||||
"category":
|
||||
result.get("category"),
|
||||
|
||||
"address":
|
||||
result.get("address", {}),
|
||||
|
||||
"extratags":
|
||||
result.get("extratags", {}),
|
||||
|
||||
"namedetails":
|
||||
result.get("namedetails", {}),
|
||||
})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(
|
||||
port=5000,
|
||||
debug=True
|
||||
)
|
||||
Reference in New Issue
Block a user