Unquote label in flask routes

Encode label in Camera.jsx
This commit is contained in:
Justin Wong 2022-08-19 17:52:45 +08:00
parent 01482d791b
commit 0bcfbc941b
2 changed files with 29 additions and 22 deletions

View File

@ -8,6 +8,7 @@ import subprocess as sp
import time import time
from functools import reduce from functools import reduce
from pathlib import Path from pathlib import Path
from urllib.parse import unquote
import cv2 import cv2
@ -17,6 +18,7 @@ from flask import (
Flask, Flask,
Response, Response,
current_app, current_app,
g,
jsonify, jsonify,
make_response, make_response,
request, request,
@ -35,6 +37,11 @@ logger = logging.getLogger(__name__)
bp = Blueprint("frigate", __name__) bp = Blueprint("frigate", __name__)
@bp.url_value_preprocessor
def unquote_label(endpoint, values):
g.label = unquote(values.pop("label", ""))
def create_app( def create_app(
frigate_config, frigate_config,
database: SqliteDatabase, database: SqliteDatabase,
@ -340,8 +347,8 @@ def event_thumbnail(id, max_cache_age=2592000):
@bp.route("/<camera_name>/<label>/best.jpg") @bp.route("/<camera_name>/<label>/best.jpg")
@bp.route("/<camera_name>/<label>/thumbnail.jpg") @bp.route("/<camera_name>/<label>/thumbnail.jpg")
def label_thumbnail(camera_name, label): def label_thumbnail(camera_name):
if label == "any": if g.label == "any":
event_query = ( event_query = (
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
@ -352,7 +359,7 @@ def label_thumbnail(camera_name, label):
event_query = ( event_query = (
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
.where(Event.label == label) .where(Event.label == g.label)
.where(Event.has_snapshot == True) .where(Event.has_snapshot == True)
.order_by(Event.start_time.desc()) .order_by(Event.start_time.desc())
) )
@ -423,8 +430,8 @@ def event_snapshot(id):
@bp.route("/<camera_name>/<label>/snapshot.jpg") @bp.route("/<camera_name>/<label>/snapshot.jpg")
def label_snapshot(camera_name, label): def label_snapshot(camera_name):
if label == "any": if g.label == "any":
event_query = ( event_query = (
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
@ -435,7 +442,7 @@ def label_snapshot(camera_name, label):
event_query = ( event_query = (
Event.select() Event.select()
.where(Event.camera == camera_name) .where(Event.camera == camera_name)
.where(Event.label == label) .where(Event.label == g.label)
.where(Event.has_snapshot == True) .where(Event.has_snapshot == True)
.order_by(Event.start_time.desc()) .order_by(Event.start_time.desc())
) )
@ -491,7 +498,7 @@ def event_clip(id):
def events(): def events():
limit = request.args.get("limit", 100) limit = request.args.get("limit", 100)
camera = request.args.get("camera", "all") camera = request.args.get("camera", "all")
label = request.args.get("label", "all") label = unquote(request.args.get("label", "all"))
sub_label = request.args.get("sub_label", "all") sub_label = request.args.get("sub_label", "all")
zone = request.args.get("zone", "all") zone = request.args.get("zone", "all")
after = request.args.get("after", type=float) after = request.args.get("after", type=float)
@ -753,9 +760,9 @@ def recordings(camera_name):
return jsonify([e for e in recordings.dicts()]) return jsonify([e for e in recordings.dicts()])
@bp.route("/<camera>/start/<int:start_ts>/end/<int:end_ts>/clip.mp4") @bp.route("/<camera_name>/start/<int:start_ts>/end/<int:end_ts>/clip.mp4")
@bp.route("/<camera>/start/<float:start_ts>/end/<float:end_ts>/clip.mp4") @bp.route("/<camera_name>/start/<float:start_ts>/end/<float:end_ts>/clip.mp4")
def recording_clip(camera, start_ts, end_ts): def recording_clip(camera_name, start_ts, end_ts):
download = request.args.get("download", type=bool) download = request.args.get("download", type=bool)
recordings = ( recordings = (
@ -765,7 +772,7 @@ def recording_clip(camera, start_ts, end_ts):
| (Recordings.end_time.between(start_ts, end_ts)) | (Recordings.end_time.between(start_ts, end_ts))
| ((start_ts > Recordings.start_time) & (end_ts < Recordings.end_time)) | ((start_ts > Recordings.start_time) & (end_ts < Recordings.end_time))
) )
.where(Recordings.camera == camera) .where(Recordings.camera == camera_name)
.order_by(Recordings.start_time.asc()) .order_by(Recordings.start_time.asc())
) )
@ -780,7 +787,7 @@ def recording_clip(camera, start_ts, end_ts):
if clip.end_time > end_ts: if clip.end_time > end_ts:
playlist_lines.append(f"outpoint {int(end_ts - clip.start_time)}") playlist_lines.append(f"outpoint {int(end_ts - clip.start_time)}")
file_name = f"clip_{camera}_{start_ts}-{end_ts}.mp4" file_name = f"clip_{camera_name}_{start_ts}-{end_ts}.mp4"
path = f"/tmp/cache/{file_name}" path = f"/tmp/cache/{file_name}"
ffmpeg_cmd = [ ffmpeg_cmd = [
@ -809,7 +816,7 @@ def recording_clip(camera, start_ts, end_ts):
) )
if p.returncode != 0: if p.returncode != 0:
logger.error(p.stderr) logger.error(p.stderr)
return f"Could not create clip from recordings for {camera}.", 500 return f"Could not create clip from recordings for {camera_name}.", 500
response = make_response() response = make_response()
response.headers["Content-Description"] = "File Transfer" response.headers["Content-Description"] = "File Transfer"
@ -825,9 +832,9 @@ def recording_clip(camera, start_ts, end_ts):
return response return response
@bp.route("/vod/<camera>/start/<int:start_ts>/end/<int:end_ts>") @bp.route("/vod/<camera_name>/start/<int:start_ts>/end/<int:end_ts>")
@bp.route("/vod/<camera>/start/<float:start_ts>/end/<float:end_ts>") @bp.route("/vod/<camera_name>/start/<float:start_ts>/end/<float:end_ts>")
def vod_ts(camera, start_ts, end_ts): def vod_ts(camera_name, start_ts, end_ts):
recordings = ( recordings = (
Recordings.select() Recordings.select()
.where( .where(
@ -835,7 +842,7 @@ def vod_ts(camera, start_ts, end_ts):
| Recordings.end_time.between(start_ts, end_ts) | Recordings.end_time.between(start_ts, end_ts)
| ((start_ts > Recordings.start_time) & (end_ts < Recordings.end_time)) | ((start_ts > Recordings.start_time) & (end_ts < Recordings.end_time))
) )
.where(Recordings.camera == camera) .where(Recordings.camera == camera_name)
.order_by(Recordings.start_time.asc()) .order_by(Recordings.start_time.asc())
) )
@ -876,14 +883,14 @@ def vod_ts(camera, start_ts, end_ts):
) )
@bp.route("/vod/<year_month>/<day>/<hour>/<camera>") @bp.route("/vod/<year_month>/<day>/<hour>/<camera_name>")
def vod_hour(year_month, day, hour, camera): def vod_hour(year_month, day, hour, camera_name):
start_date = datetime.strptime(f"{year_month}-{day} {hour}", "%Y-%m-%d %H") start_date = datetime.strptime(f"{year_month}-{day} {hour}", "%Y-%m-%d %H")
end_date = start_date + timedelta(hours=1) - timedelta(milliseconds=1) end_date = start_date + timedelta(hours=1) - timedelta(milliseconds=1)
start_ts = start_date.timestamp() start_ts = start_date.timestamp()
end_ts = end_date.timestamp() end_ts = end_date.timestamp()
return vod_ts(camera, start_ts, end_ts) return vod_ts(camera_name, start_ts, end_ts)
@bp.route("/vod/event/<id>") @bp.route("/vod/event/<id>")

View File

@ -133,8 +133,8 @@ export default function Camera({ camera }) {
className="mb-4 mr-4" className="mb-4 mr-4"
key={objectType} key={objectType}
header={objectType} header={objectType}
href={`/events?camera=${camera}&label=${objectType}`} href={`/events?camera=${camera}&label=${encodeURIComponent(objectType)}`}
media={<img src={`${apiHost}/api/${camera}/${objectType}/thumbnail.jpg`} />} media={<img src={`${apiHost}/api/${camera}/${encodeURIComponent(objectType)}/thumbnail.jpg`} />}
/> />
))} ))}
</div> </div>