Add "location" support (embed a tag with a Place object)
This commit is contained in:
parent
cf983ca9f3
commit
e611d61739
4 changed files with 93 additions and 1 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
@ -50,6 +51,8 @@ from core.tasks import Tasks
|
||||||
from utils import emojis
|
from utils import emojis
|
||||||
from utils import now
|
from utils import now
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
blueprint = flask.Blueprint("api", __name__)
|
blueprint = flask.Blueprint("api", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -450,6 +453,7 @@ def api_new_note() -> _Response:
|
||||||
|
|
||||||
source = None
|
source = None
|
||||||
summary = None
|
summary = None
|
||||||
|
place_tags = []
|
||||||
|
|
||||||
# Basic Micropub (https://www.w3.org/TR/micropub/) "create" support
|
# Basic Micropub (https://www.w3.org/TR/micropub/) "create" support
|
||||||
is_micropub = False
|
is_micropub = False
|
||||||
|
@ -463,8 +467,24 @@ def api_new_note() -> _Response:
|
||||||
if "jwt_payload" not in flask.g or "create" not in flask.g.jwt_payload["scope"]:
|
if "jwt_payload" not in flask.g or "create" not in flask.g.jwt_payload["scope"]:
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
# Handle location sent via form-data
|
||||||
|
# `geo:28.5,9.0,0.0`
|
||||||
|
location = _user_api_arg("location", default="")
|
||||||
|
if location.startswith("geo:"):
|
||||||
|
slat, slng, *_ = location[4:].split(",")
|
||||||
|
place_tags.append(
|
||||||
|
{
|
||||||
|
"type": ap.ActivityType.PLACE.value,
|
||||||
|
"url": "",
|
||||||
|
"name": "",
|
||||||
|
"latitude": float(slat),
|
||||||
|
"longitude": float(slng),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Handle JSON microformats2 data
|
# Handle JSON microformats2 data
|
||||||
if _user_api_arg("type", default=None):
|
if _user_api_arg("type", default=None):
|
||||||
|
_logger.info(f"Micropub request: {request.json}")
|
||||||
try:
|
try:
|
||||||
source = request.json["properties"]["content"][0]
|
source = request.json["properties"]["content"][0]
|
||||||
except (ValueError, KeyError):
|
except (ValueError, KeyError):
|
||||||
|
@ -493,6 +513,21 @@ def api_new_note() -> _Response:
|
||||||
if summary is None:
|
if summary is None:
|
||||||
summary = _user_api_arg("summary", default="")
|
summary = _user_api_arg("summary", default="")
|
||||||
|
|
||||||
|
if not place_tags:
|
||||||
|
if _user_api_arg("location_lat", default=None):
|
||||||
|
lat = float(_user_api_arg("location_lat"))
|
||||||
|
lng = float(_user_api_arg("location_lng"))
|
||||||
|
loc_name = _user_api_arg("location_name", default="")
|
||||||
|
place_tags.append(
|
||||||
|
{
|
||||||
|
"type": ap.ActivityType.PLACE.value,
|
||||||
|
"url": "",
|
||||||
|
"name": loc_name,
|
||||||
|
"latitude": lat,
|
||||||
|
"longitude": lng,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# All the following fields are specific to the API (i.e. not Micropub related)
|
# All the following fields are specific to the API (i.e. not Micropub related)
|
||||||
_reply, reply = None, None
|
_reply, reply = None, None
|
||||||
try:
|
try:
|
||||||
|
@ -507,7 +542,7 @@ def api_new_note() -> _Response:
|
||||||
content, tags = parse_markdown(source)
|
content, tags = parse_markdown(source)
|
||||||
|
|
||||||
# Check for custom emojis
|
# Check for custom emojis
|
||||||
tags = tags + emojis.tags(content)
|
tags = tags + emojis.tags(content) + place_tags
|
||||||
|
|
||||||
to: List[str] = []
|
to: List[str] = []
|
||||||
cc: List[str] = []
|
cc: List[str] = []
|
||||||
|
|
|
@ -49,6 +49,15 @@
|
||||||
<input type="text" name="file_description" placeholder="attachment description (optional)">
|
<input type="text" name="file_description" placeholder="attachment description (optional)">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<input type="text" name="location_lat" id="location_lat" placeholder="latitude (optional)">
|
||||||
|
<input type="text" name="location_lng" id="location_lng" placeholder="longitude (optional)">
|
||||||
|
<a href="#" class="location_autofill">ask browser for location</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="text" name="location_name" placeholder="location name (optional)">
|
||||||
|
</p>
|
||||||
|
|
||||||
{% if request.args.get("question") == "1" %}
|
{% if request.args.get("question") == "1" %}
|
||||||
<div style="margin-top:20px;">
|
<div style="margin-top:20px;">
|
||||||
<p>Open for: <select name="open_for">
|
<p>Open for: <select name="open_for">
|
||||||
|
@ -114,4 +123,16 @@ var items = document.getElementsByClassName("ji")
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
items[i].addEventListener('click', ji);
|
items[i].addEventListener('click', ji);
|
||||||
}
|
}
|
||||||
|
var askForLocation = function(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
navigator.geolocation.getCurrentPosition(function(position) {
|
||||||
|
document.getElementById("location_lat").value = position.coords.latitude;
|
||||||
|
document.getElementById("location_lng").value = position.coords.longitude;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var items = document.getElementsByClassName("location_autofill")
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
items[i].addEventListener('click', askForLocation);
|
||||||
|
}
|
||||||
|
|
||||||
</script>{% endblock %}
|
</script>{% endblock %}
|
||||||
|
|
|
@ -208,6 +208,11 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ obj.content | clean | replace_custom_emojis(obj) | code_highlight | safe }}
|
{{ obj.content | clean | replace_custom_emojis(obj) | code_highlight | safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if obj | has_place %}
|
||||||
|
<p>Location: {{ obj | get_place | safe }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if obj.attachment and obj | has_type('Note') %}
|
{% if obj.attachment and obj | has_type('Note') %}
|
||||||
|
|
|
@ -240,6 +240,37 @@ def get_actor(url):
|
||||||
return f"Error<{url}/{exc!r}>"
|
return f"Error<{url}/{exc!r}>"
|
||||||
|
|
||||||
|
|
||||||
|
@filters.app_template_filter()
|
||||||
|
def has_place(note):
|
||||||
|
for tag in note.get("tag", []):
|
||||||
|
if tag.get("type") == "Place":
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@filters.app_template_filter()
|
||||||
|
def get_place(note):
|
||||||
|
for tag in note.get("tag", []):
|
||||||
|
if tag.get("type") == "Place":
|
||||||
|
lat = tag["latitude"]
|
||||||
|
lng = tag["longitude"]
|
||||||
|
out = ""
|
||||||
|
if tag.get("name"):
|
||||||
|
out += f"{tag['name']} "
|
||||||
|
|
||||||
|
out += (
|
||||||
|
'<span class="h-geo">'
|
||||||
|
f'<data class="p-latitude" value="{lat}"></data>'
|
||||||
|
f'<data class="p-longitude" value="{lng}"></data>'
|
||||||
|
f'<a href="https://www.openstreetmap.org/?mlat={lat}&mlon={lng}#map=16/{lat}/{lng}">{lat},{lng}</a>'
|
||||||
|
"</span>"
|
||||||
|
)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@filters.app_template_filter()
|
@filters.app_template_filter()
|
||||||
def poll_answer_key(choice: str) -> str:
|
def poll_answer_key(choice: str) -> str:
|
||||||
return _answer_key(choice)
|
return _answer_key(choice)
|
||||||
|
|
Loading…
Reference in a new issue