"""File containing infoscreen views.""" from django.shortcuts import render from django.http import HttpResponse, HttpResponseBadRequest from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_http_methods from django.contrib.contenttypes.models import ContentType from django.contrib.auth.decorators import permission_required from infoscreen.models import UploadFileForm import sikweb.settings as settings import json import logging import threading import requests from infoscreen.models import Rotation, InfoItem, InfoInstance from infoscreen.models import (ABBInfoItem, ExternalImageInfoItem, ImageInfoItem, SossoInfoItem, HslInfoItem) from infoscreen.models import EventInfoItem from infoscreen.models import ExternalWebsiteInfoItem from infoscreen.models import ImageUploadForm from infoscreen.models import HSLDataModel from infoscreen.models import ApyInfoItem from infoscreen.models import VideoInfoItem from infoscreen.hsl_fetcher import HSLFetcher def index(request, idx, *args, **kwargs): """Render infoscreen index page.""" return render(request, 'infoscreen_index.html', {'rotation': idx}) @permission_required('infoscreen.change_infoinstance', login_url='/login') def admin(request, *args, **kwargs): """Render infoscreen admin page.""" return render(request, 'infoscreen_admin.html', {}) def default(request, *args, **kwargs): """Try getting first rotation item.""" try: first = Rotation.objects.all()[0].id except: first = 0 return index(request, first, *args, **kwargs) def get_apy_json(request): """Render APY diilikone page.""" return HttpResponse( requests.get("https://api-diilikone.apy.fi/deals/top-groups").text) @require_http_methods(["GET"]) def rotation(request, idx, *args, **kwargs): """Get rotation.""" try: rotation = Rotation.objects.get(pk=idx) except Rotation.DoesNotExist: resp = HttpResponse('{"error": "Rotation not found"}') resp.status_code = 404 return resp return HttpResponse(json.dumps(rotation.get_dict())) def create_item_generator(model): """Create Infoscreen item generator.""" @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('infoscreen.change_infoinstance', login_url='/login') def create_item(request, *args, **kwargs): try: data = json.loads(request.body.decode("utf-8")) except ValueError: return HttpResponseBadRequest( '{"status":"failure","error":"invalid json supplied"}') try: model.create_from_dict(data) return HttpResponse('{"status":"success"}') except RuntimeError as e: return HttpResponseBadRequest( json.dumps({"status": "failure", "error": str(e)})) return create_item def delete_item_generator(model): """Delete Infoscreen item generator.""" @ensure_csrf_cookie @require_http_methods(["DELETE"]) @permission_required('infoscreen.change_infoinstance', login_url='/login') def delete_item(request, *args, **kwargs): idx = kwargs.pop("idx", 0) try: item = model.objects.get(pk=idx) except model.DoesNotExist: resp = HttpResponse('{"error":"object not found"}') resp.status_code = 404 return resp try: item.delete() return HttpResponse('{"status":"success"}') except: resp = HttpResponse('{"error" : "could not delete item"}') resp.status_code = 500 return resp return delete_item # due to model structure this is little complicated @ensure_csrf_cookie @permission_required('infoscreen.change_infoinstance', login_url='/login') @require_http_methods(["DELETE"]) def delete_info_item(request, *args, **kwargs): """Delete info item.""" type_id = kwargs.pop("type_id", 0) idx = kwargs.pop("idx", 0) if True: ct = ContentType.objects.get_for_id(type_id) item = ct.get_object_for_this_type(pk=idx) else: resp = HttpResponse('{"error":"object not found"}') resp.status_code = 404 return resp try: item.delete() return HttpResponse('{"status":"success"}') except: resp = HttpResponse('{"error" : "could not delete item"}') resp.status_code = 500 return resp @require_http_methods(["GET"]) def rotations(request, *args, **kwargs): """Return rotation lists.""" rotations = list(map(lambda r: r.get_list(), Rotation.objects.all())) return HttpResponse(json.dumps(rotations)) @require_http_methods(["GET"]) def info_types(request, *args, **kwargs): """Return info item types.""" types = [] classes = InfoItem.get_subclasses() for c in classes: types.append({ "name": c.display_name, "create_template_url": c.get_create_template_url(), }) return HttpResponse(json.dumps(types)) def info_items(request, *args, **kwargs): """Return Infoscreen items.""" items = [] classes = InfoItem.get_subclasses() for c in classes: for i in c.objects.all(): items.append(i.get_dict()) return HttpResponse(json.dumps(items)) @require_http_methods(["POST"]) @ensure_csrf_cookie @permission_required('infoscreen.change_infoinstance', login_url='/login') def create_image_item(request, *args, **kwargs): """Create image Infoscreen item.""" form = ImageUploadForm(request.POST, request.FILES) if not form.is_valid(): return HttpResponseBadRequest('{"status": "failure",' '"error": "invalid data supplied"}') img = form.cleaned_data['image'] name = form.cleaned_data['name'] ImageInfoItem.objects.create(img=img, name=name) return HttpResponse('{"status":"success"}') @require_http_methods(["POST"]) @ensure_csrf_cookie @permission_required('infoscreen.change_infoinstance', login_url='/login') def create_video_item(request, *args, **kwargs): """Create video Infoscreen item.""" form = UploadFileForm(request.POST, request.FILES) if not form.is_valid(): return HttpResponseBadRequest('{"status": "failure",' '"error": "invalid data supplied"}') video = form.cleaned_data['video'] name = form.cleaned_data['name'] VideoInfoItem.objects.create(video=video, name=name) return HttpResponse('{"status": "success"}') @require_http_methods(["POST"]) @ensure_csrf_cookie @permission_required('infoscreen.add_rotation', login_url='/login') def create_rotation(request, *args, **kwargs): """Create rotation.""" try: data = json.loads(request.body.decode("utf-8")) except: return HttpResponse('{"error": "bad post body!"}', status=400) try: name = data["name"] Rotation.objects.create(name=name) resp = HttpResponse(status=200) except: resp = HttpResponse( '{"error" : "could not create rotation!"}', status=400) return resp @require_http_methods(["DELETE"]) @ensure_csrf_cookie @permission_required('infoscreen.delete_rotation', login_url='/login') def delete_rotation(request, *args, **kwargs): """Delete rotation.""" id = kwargs.pop("id", 0) logging.warning("Deleting rotation with id={}".format(id)) try: Rotation.objects.filter(id=id).delete() resp = HttpResponse(status=200) except: resp = HttpResponse( '{"error" : "could not delete rotation!"}', status=400) return resp @require_http_methods(["GET"]) def hsl_timetable_settings(request, *args, **kwargs): """Set HSL timetable settings.""" d = {"departure_threshold": settings.HSL_DEPARTURE_THRESHOLD, "hurry_threshold": settings.HSL_HURRY_THRESHOLD} resp = json.dumps(d) return HttpResponse(resp, status=200) @require_http_methods(["GET"]) def CurrentHSLView(request, *args, **kwargs): """Get HSL data and return it.""" fetcher = HSLFetcher() fetcherThread = threading.Thread(target=fetcher.fetch_if_needed, args=[]) fetcherThread.setDaemon(False) fetcherThread.start() data = HSLDataModel.objects.all() if len(data) < 1: return HttpResponse( '{"error" : "Could not find timetables from database."}', status=500) return HttpResponse(data[len(data) - 1].data, status=200) createInstance = create_item_generator(InfoInstance) deleteInstance = delete_item_generator(InfoInstance) createABBItem = create_item_generator(ABBInfoItem) createSossoItem = create_item_generator(SossoInfoItem) createHslItem = create_item_generator(HslInfoItem) createExternalImageInfoItem = create_item_generator(ExternalImageInfoItem) createExternalWebsiteItem = create_item_generator(ExternalWebsiteInfoItem) createEventItem = create_item_generator(EventInfoItem) createApyItem = create_item_generator(ApyInfoItem) createVideoItem = create_item_generator(VideoInfoItem)