Karten-Ausbau (OSM), Forum-Erweiterung, UI-Komponenten, Refactor Tagebuch/Gassi (DRY), Landing/SEO — APP_VER 1155

This commit is contained in:
rene 2026-06-03 17:24:47 +02:00
parent 2d907f6370
commit 10e39ed135
18 changed files with 871 additions and 405 deletions

View file

@ -423,3 +423,65 @@ async def submit_poi_edit(osm_id: str, data: PoiEditCreate,
poi[data.field], data.new_value.strip(), user["id"])
)
return {"status": "pending", "message": "Korrektur wurde zur Prüfung eingereicht."}
# ------------------------------------------------------------------
# Geocoding-Proxy GET /api/osm/geocode?q=…
# Nominatim-Rate-Limit: 1 req/s — serverseitig throttled
# ------------------------------------------------------------------
_nominatim_sem = asyncio.Semaphore(1)
_nominatim_last = 0.0
@router.get('/geocode')
async def geocode_search(q: str = Query(..., min_length=2, max_length=200)):
import time
global _nominatim_last
async with _nominatim_sem:
wait = 1.1 - (time.monotonic() - _nominatim_last)
if wait > 0:
await asyncio.sleep(wait)
_nominatim_last = time.monotonic()
try:
async with httpx.AsyncClient(timeout=6.0) as client:
resp = await client.get(
'https://nominatim.openstreetmap.org/search',
params={
'q': q,
'format': 'jsonv2',
'limit': 6,
'countrycodes': 'de,at,ch',
'addressdetails': 1,
'accept-language': 'de',
},
headers={
'User-Agent': _OVERPASS_UA,
'Referer': 'https://banyaro.app/',
}
)
resp.raise_for_status()
data = resp.json()
except Exception as e:
logger.warning("Nominatim-Fehler: %s", e)
raise HTTPException(502, "Geocoding nicht verfügbar")
out = []
for r in data[:6]:
addr = r.get('address', {})
short = (
addr.get('amenity') or addr.get('shop') or addr.get('leisure') or
addr.get('road') or addr.get('village') or addr.get('town') or
addr.get('city') or r.get('name') or
r.get('display_name', '').split(',')[0]
)
city = addr.get('city') or addr.get('town') or addr.get('village') or addr.get('municipality') or ''
state = addr.get('state', '')
subtitle = ', '.join(filter(None, [city, state]))
out.append({
'lat': float(r['lat']),
'lon': float(r['lon']),
'name': short,
'subtitle': subtitle,
'full': r.get('display_name', ''),
'type': r.get('type', ''),
})
return out