Compare commits

14 Commits

Author SHA1 Message Date
fordprefect
285c849adc typo 2020-04-20 09:14:11 +02:00
fordprefect
1f3be8fd37 no outputfilename and outputfolder needed anymore 2020-04-20 09:13:59 +02:00
fordprefect
223a2b12b6 gpx file download done properly 2020-04-18 15:15:41 +02:00
fordprefect
afb5cc3336 improved web interface, JS download option missing, no storage of files on host system necessary anymore 2020-03-27 20:25:59 +01:00
fordprefect
dba6ed4b0b more saving options (stdout, return) 2020-03-27 20:24:38 +01:00
fordprefect
6eda1c26e2 first useful web interface 2020-03-26 19:17:04 +01:00
fordprefect
0b7184185f TODO added 2020-03-26 19:16:36 +01:00
fordprefect
2d293f3a5c cleanup, proper handling of ignore_ids 2020-03-26 19:06:12 +01:00
fordprefect
50085391d1 webinterface (WIP) 2020-03-26 18:00:10 +01:00
fordprefect
2b62bc4725 refactoring, object oriented. CLI interface needs polishing 2020-03-26 17:58:12 +01:00
fordprefect
d0dd884a23 gpxpy version assertion 2020-03-26 14:42:08 +01:00
fordprefect
293e29409a fix date string and introduce HTTP argument parsing 2020-03-25 21:57:23 +01:00
fordprefect
8f2ac69835 first draft of website 2020-03-25 21:56:49 +01:00
fordprefect
f21551c06e rename script 2020-03-25 21:54:22 +01:00
4 changed files with 174 additions and 8 deletions

29
index.html Normal file
View File

@@ -0,0 +1,29 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="robots" content="noindex,nofollow" />
<title>OSM search to GPX</title>
</head>
<body class=body>
<div class=head>
<h3>Export OSM search to GPX file</h3>
</div>
<div class=box>
This form allows you to perform a search of the Open Street Map database (via Nominatim) and exports all results as Waypoints in a GPX file.
<form action=websearch.py method=post>
<input name=query placeholder=Camping></input> Your search query<br>
<input name=boundingbox></input> Give coordinates of bounding box for search in the format of "x1,y1,x2,y2" (optional)<br>
<input name="ignore IDs"></input> Ignore OSM database objects with given IDs (optional)<br>
<input name="Maximum search nubmer" default=10 ></input> Maximum number of runs - increase if results are missing (optional)<br>
<input type=submit name="Submit"><br>
</form>
</div>
<div class=foot>
OSMsearchToGPX - ein Service von <a href=https://dukun.de>dukun.de</a>
</div>
</body>
</html>

View File

@@ -26,6 +26,7 @@ class OSMSearch():
self.gpxfilename = args.pop("outputfilename")
self.print_xml = True if args["output"] == "print" else False
self.use_boundingbox = args.pop("use_boundingbox")
self.ignore_ids = args.pop("ignore_ids")
if self.use_boundingbox:
assert isinstance(list, args["boundingbox"])
assert len(args["boundingbox"]) == 4
@@ -49,11 +50,13 @@ class OSMSearch():
return
if os.path.isfile(self.gpxfilename):
# open file and parse
#if verbosity > 0: print(f"found file, extending")
self.gpxfile = gpxpy.parse(open(gpxfilename, "r"))
raise NotImplementedError("We don't know how to deal with existing files yet, sry")
# TODO: file name collision? either:
# 1) amend file
#self.gpxfile = gpxpy.parse(open(gpxfilename, "r"))
# 2) refuse to work
# 3) alter file name
else:
#if verbosity > 0: print("creating new file")
self.gpxfile = gpxpy.gpx.GPX()
def get_argstring(self):
@@ -61,6 +64,8 @@ class OSMSearch():
if self.use_boundingbox:
argstring.append(",".join(list(map(str, self.searchargs["boundingbox"]))))
if self.ignore_ids != []:
argstrings.append(f"ignore_ids=" + ",".join(list(map(str, self.ignore_ids))))
for arg in self.searchargs:
argstrings.append(f"{arg}={self.searchargs[arg]}")
@@ -76,24 +81,22 @@ class OSMSearch():
r = requests.get(self.url + self.get_argstring())
if r.status_code != 200:
#if verbosity > 0: print(f"Query gone wrong: HTTP returned {r.status_code}")
exit(1)
# parse reply
reply = r.json()
assert isinstance(reply, list), "Unexpected type of reply: " + type(reply)
if len(reply) == 0:
if verbosity > 0: print(f"found {len(ignore_ids)} results in {i-1} iterations, finishing")
break
for point in reply:
self.searchargs["ignore_ids"].append(point["place_id"])
self.ignore_ids.append(point["place_id"])
# TODO use better name than "display_name", maybe add more info to Waypoint
self.gpxfile.waypoints.append(gpxpy.gpx.GPXWaypoint(latitude=point["lat"], longitude=point["lon"], name=point["display_name"]))
def save_to_disk(self):
with open(self.gpxfilename, "w") as f:
f.write(self.gpxfile.to_xml())
#if verbosity > 0: print(f"GPX file written to {gpxfilename}")
def print_to_stdout(self):
print(self.gpxfile.to_xml())

36
style.css Normal file
View File

@@ -0,0 +1,36 @@
div.box {
color:#cecece;
background-image: url('/linen_login.jpg');
background-size: 100%;
width: 80%;
height: 80%;
margin: 0px auto;
overflow: auto;
padding:10px;
border-radius:10px;
box-shadow: 0px 0px 20px #000;
}
body {
background-image:url('/linen.jpg');
background-repeat:repeat;
}
div.head {
width: 80%;
margin: auto;
}
div.foot {
width: 80%;
margin:auto;
margin-top:20px;
}
div.foot a {
color: #0000aa;
}
a {
color:#8080ee;
}

98
websearch.py Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/python
"""
CGI interface to osmsearch.py
"""
__author__ = "fordprefect"
__date__ = "2020-03-26"
__version__ = "0.1"
print("Content-type: text/html\n") # makes sure the http connection does not die - do nothing before this!
import cgi
import pathvalidate
import osmsearch
import datetime
import random
import os
import sys
assert sys.version_info >= (3, 6), "At least Python 3.8 required due to fStrings. Replace all f\"\" and comment this line to enable running in lower versions (but really, you should just update your Python version…)."
import base64
#####################################
######## configuration
#####################################
# default set of arguments
args = {
"q": "Camping",
"format": "json",
"limit": 50,
"use_boundingbox": False,
"boundingbox": [],
"ignore_ids": [],
"maxsearchnums": 10,
"url": "https://nominatim.openstreetmap.org/search/",
"output": "return",
}
immutable_args = ["format", "url", "ouput"]
outputfolder = "downloads"
DEBUG = False
#####################################
######## end of configuration
#####################################
# get cgi args sanitize, and update default args
rawargs = cgi.FieldStorage()
cgi_args = {i: rawargs.getvalue(i) for i in rawargs}
del(rawargs)
parsed_args = {}
try:
cgi_args["q"] = pathvalidate.sanitize_filename(cgi_args["query"])
except KeyError:
if DEBUG:
# local testing
cgi_args["q"] = "Camping"
else:
# we don't need to exit gracefully, whoever is arriving here has fiddled with the request manually
exit()
for arg in cgi_args:
if arg not in immutable_args and arg in args:
parsed_args[arg] = cgi_args[arg]
if DEBUG: print("Parsed argument dict: ", parsed_args)
args.update(cgi_args)
searchresult = osmsearch.OSMSearch(args)
gpxcontent = searchresult.gpxfile.to_xml()
gpxcontent_base64 = base64.b64encode(gpxcontent.encode("utf-8")).decode("utf-8")
print("""
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="robots" content="noindex,nofollow" />
<title>OSM search to GPX</title>
</head>
<body class=body>
<div class=head>
<h3>Export OSM search to GPX file</h3>
</div>
<div class=box>
<h4>Success</h4>
""" + f"""
<a href="data:text/xml;base64,{gpxcontent_base64}"
""" + """
download="search.gpx">Download GPX file here</a>
<br><br>
<a href=index.html>Return to search page</a>
</div>
<div class=foot>
OSMsearchToGPX - ein Service von <a href=https://dukun.de>dukun.de</a>
</div>
</body>
</html>
""")