from datetime import datetime
import icalendar
import recurring_ical_events
import requests
from flask import request
from flask.json import jsonify
from flask_babel import gettext
from flask_cors import cross_origin
from flask_security import auth_required, url_for_security
from flask_security.utils import localize_callback
from sqlalchemy import func
from project import app, csrf
from project.api.custom_widget.schemas import CustomWidgetSchema
from project.dateutils import form_input_to_date
from project.maputils import find_gmaps_places, get_gmaps_place
from project.models import AdminUnit, CustomWidget, EventOrganizer, EventPlace
from project.services.place import get_event_places
from project.services.user import find_user_by_email
from project.utils import decode_response_content, get_place_str
@app.route("/js/check/organization/short_name", methods=["POST"])
def js_check_org_short_name():
csrf.protect()
short_name = request.form["short_name"]
admin_unit_id = (
int(request.form["admin_unit_id"]) if "admin_unit_id" in request.form else -1
)
organization = AdminUnit.query.filter(
func.lower(AdminUnit.short_name) == short_name.lower()
).first()
if not organization or organization.id == admin_unit_id:
return jsonify(True)
error = gettext("Short name is already taken")
return jsonify(error)
@app.route("/js/check/organization/name", methods=["POST"])
def js_check_org_name():
csrf.protect()
name = request.form["name"]
admin_unit_id = (
int(request.form["admin_unit_id"]) if "admin_unit_id" in request.form else -1
)
organization = AdminUnit.query.filter(
func.lower(AdminUnit.name) == name.lower()
).first()
if not organization or organization.id == admin_unit_id:
return jsonify(True)
error = gettext("Name is already taken")
return jsonify(error)
@app.route("/js/check/event_place/name", methods=["POST"])
def js_check_event_place_name():
csrf.protect()
name = request.form["name"]
admin_unit_id = (
int(request.form["admin_unit_id"]) if "admin_unit_id" in request.form else -1
)
event_place_id = (
int(request.form["event_place_id"]) if "event_place_id" in request.form else -1
)
event_place = (
EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit_id)
.filter(func.lower(EventPlace.name) == name.lower())
.first()
)
if not event_place or event_place.id == event_place_id:
return jsonify(True)
error = gettext("A place already exists with this name.")
return jsonify(error)
@app.route("/js/check/organizer/name", methods=["POST"])
def js_check_organizer_name():
csrf.protect()
name = request.form["name"]
admin_unit_id = (
int(request.form["admin_unit_id"]) if "admin_unit_id" in request.form else -1
)
organizer_id = (
int(request.form["organizer_id"]) if "organizer_id" in request.form else -1
)
organizer = (
EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit_id)
.filter(func.lower(EventOrganizer.name) == name.lower())
.first()
)
if not organizer or organizer.id == organizer_id:
return jsonify(True)
error = gettext("An organizer already exists with this name.")
return jsonify(error)
@app.route("/js/check/register/email", methods=["POST"])
def js_check_register_email():
csrf.protect()
email = request.form["email"]
user = find_user_by_email(email)
if not user:
return jsonify(True)
msg = gettext("An account already exists with this email.")
url = url_for_security("forgot_password")
link_text = localize_callback("Forgot password")
link = ' – %s' % (url, link_text)
error = msg + link
return jsonify(error)
@app.route("/js/autocomplete/place")
def js_autocomplete_place():
csrf.protect()
admin_unit_id = int(request.args.get("admin_unit_id", "0"))
keyword = request.args.get("keyword")
exclude_gmaps = request.args.get("exclude_gmaps")
places_result = list()
google_places_result = list()
if admin_unit_id > 0:
places = get_event_places(admin_unit_id, keyword, 5)
places_result = [{"id": p.id, "text": get_place_str(p)} for p in places]
if not exclude_gmaps:
google_places = find_gmaps_places(keyword) if keyword else list()
google_places_result = [
{
"id": p["place_id"],
"gmaps_id": p["place_id"],
"text": p["description"],
"main_text": p["structured_formatting"]["main_text"],
}
for p in google_places
]
if exclude_gmaps:
results = places_result
elif admin_unit_id <= 0:
results = google_places_result
else:
results = list()
if len(places) > 0:
results.append(
{
"text": gettext("Places of organization"),
"children": places_result,
}
)
if len(google_places) > 0:
results.append(
{
"text": gettext("Places of Google Maps"),
"children": google_places_result,
}
)
result = {"results": results}
return jsonify(result)
@app.route("/js/autocomplete/gmaps_place")
def js_autocomplete_gmaps_place():
csrf.protect()
gmaps_id = request.args["gmaps_id"]
place = get_gmaps_place(gmaps_id)
return jsonify(place)
@app.route("/js/icalevents", methods=["POST"])
@auth_required()
def js_icalevents():
csrf.protect()
try:
url = request.form["url"]
date_from = request.form["date_from"]
date_to = request.form["date_to"]
start_date = form_input_to_date(date_from).date()
end_date = form_input_to_date(date_to).date()
response = requests.get(url)
ical_string = decode_response_content(response)
calendar = icalendar.Calendar.from_ical(ical_string)
events = recurring_ical_events.of(calendar).between(start_date, end_date)
items = list()
for event in events:
summary = event.get("SUMMARY")
dt_start = event.get("DTSTART")
dt_end = event.get("DTEND")
location = event.get("LOCATION")
description = event.get("DESCRIPTION")
if not summary or not dt_start: # pragma: no cover
continue
start = dt_start.dt
item = {
"name": summary,
"start": start,
"allday": not isinstance(start, datetime),
}
if dt_end:
item["end"] = dt_end.dt
vevent = {
"url": url,
}
if location:
vevent["location"] = location
if dt_end:
vevent["description"] = description
item["vevent"] = vevent
items.append(item)
result = {
"url": url,
"items": items,
}
return jsonify(result)
except Exception as e: # pragma: no cover
app.logger.exception(url)
return getattr(e, "message", "Unknown error"), 400
@app.route("/js/wlcw/")
@cross_origin()
def js_widget_loader_custom_widget(id: int):
widget = CustomWidget.query.get_or_404(id)
schema = CustomWidgetSchema()
return schema.dump(widget)