From e7036d21d5e5c87702724283f55a77d07344f4fe Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sat, 10 May 2025 19:47:31 -0500 Subject: add flaskapi --- flaskapi.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 flaskapi.py (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py new file mode 100644 index 0000000..4b1a259 --- /dev/null +++ b/flaskapi.py @@ -0,0 +1,24 @@ +from flask import Flask, Blueprint, request + +app = Flask(__name__) + +@app.route("/") +def home(): + return "Flask is running!" + +api = Blueprint("api", __name__) + +@api.route("/seek") +def seek(): + pd = app.config["pix_display"] + + increment = request.args.get("increment", default=1, type=int) + pd.queue.put(lambda: pd.seek(increment)) + while not pd.queue.empty(): + pass + return { + "imageTime": pd.image_time, + "imageIndex": pd.current_texture_index, + } + +app.register_blueprint(api, url_prefix="/api") -- cgit v1.2.3 From 8afd27d113d20f924df73456374153397039e1ba Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sat, 10 May 2025 20:01:04 -0500 Subject: add module for immich frame client project and endpoints (merge later) --- flaskapi.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index 4b1a259..29cea7e 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -1,10 +1,13 @@ -from flask import Flask, Blueprint, request +from flask import Flask, Blueprint, request, send_from_directory -app = Flask(__name__) +app = Flask(__name__, static_folder="static/dist", static_url_path="/") @app.route("/") +@app.route("/slideshow") +@app.route("/albums") +@app.route("/settings") def home(): - return "Flask is running!" + return send_from_directory("static/public", "index.html") api = Blueprint("api", __name__) -- cgit v1.2.3 From 31f1940ec8c4aba6a0c21b20eff9657d5d11cf80 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 11 May 2025 00:20:08 -0500 Subject: albums thumbnails endpoint and albums endpoint --- flaskapi.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index 29cea7e..0791016 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -1,4 +1,5 @@ -from flask import Flask, Blueprint, request, send_from_directory +from flask import Flask, Blueprint, request, send_from_directory, send_file, abort +from flask_cors import CORS app = Flask(__name__, static_folder="static/dist", static_url_path="/") @@ -10,6 +11,7 @@ def home(): return send_from_directory("static/public", "index.html") api = Blueprint("api", __name__) +CORS(api, origins="*") # For debugging TODO remove later @api.route("/seek") def seek(): @@ -24,4 +26,22 @@ def seek(): "imageIndex": pd.current_texture_index, } +@api.route("/albums/get") +def get_albums(): + ic = app.config["immich_connector"] + keys = [ "albumName", "albumThumbnailAssetId", "id", "startDate", "endDate", "assetCount", "shared", ] + return [{ + key: album[key] for key in keys + } for album in ic.load_all_albums() ] + +@api.route("/albums/thumb/") +def get_album_thumb(key): + # TODO ensure getting actual album thumb + ic = app.config["immich_connector"] + image_data, mimetype = ic.load_image(key, size="thumbnail") + if image_data is None: + abort(400) + return send_file(image_data, mimetype=mimetype) + + app.register_blueprint(api, url_prefix="/api") -- cgit v1.2.3 From cd1657ece1fa199964abd6544b81b394ab9369aa Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 15 Jun 2025 15:06:34 -0500 Subject: callbacks on lctl, websocket controls --- flaskapi.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index 0791016..a537192 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -1,7 +1,9 @@ -from flask import Flask, Blueprint, request, send_from_directory, send_file, abort +from flask import Flask, Blueprint, request, send_from_directory, send_file, abort, redirect +from flask_socketio import SocketIO, emit from flask_cors import CORS app = Flask(__name__, static_folder="static/dist", static_url_path="/") +socketio = SocketIO(app, cors_allowed_origins="*") # TODO remove later @app.route("/") @app.route("/slideshow") @@ -13,11 +15,11 @@ def home(): api = Blueprint("api", __name__) CORS(api, origins="*") # For debugging TODO remove later -@api.route("/seek") -def seek(): +#@api.route("/seek") +@socketio.on("seek") +def seek(increment): pd = app.config["pix_display"] - increment = request.args.get("increment", default=1, type=int) pd.queue.put(lambda: pd.seek(increment)) while not pd.queue.empty(): pass @@ -26,7 +28,7 @@ def seek(): "imageIndex": pd.current_texture_index, } -@api.route("/albums/get") +@api.route("/albums") def get_albums(): ic = app.config["immich_connector"] keys = [ "albumName", "albumThumbnailAssetId", "id", "startDate", "endDate", "assetCount", "shared", ] @@ -34,14 +36,20 @@ def get_albums(): key: album[key] for key in keys } for album in ic.load_all_albums() ] -@api.route("/albums/thumb/") -def get_album_thumb(key): +@api.route("/asset//thumbnail", defaults={ "size": "thumbnail" }) +@api.route("/asset/", defaults={ "size": "preview" }) +def get_asset(key, size): # TODO ensure getting actual album thumb ic = app.config["immich_connector"] - image_data, mimetype = ic.load_image(key, size="thumbnail") + image_data, mimetype = ic.load_image(key, size=size) if image_data is None: abort(400) return send_file(image_data, mimetype=mimetype) +@api.route("/redirect/") +def immich_redirect(path): + ic = app.config["immich_connector"] + return redirect(f"{ic.server_url}/{path}") + app.register_blueprint(api, url_prefix="/api") -- cgit v1.2.3 From b8df4605b42d9a61bb4ae4731efabbdc38166063 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 16 Jun 2025 21:50:38 -0500 Subject: add config and add application thread manager --- flaskapi.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index a537192..45616ec 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -2,8 +2,14 @@ from flask import Flask, Blueprint, request, send_from_directory, send_file, abo from flask_socketio import SocketIO, emit from flask_cors import CORS +from manager import PixMan + + app = Flask(__name__, static_folder="static/dist", static_url_path="/") -socketio = SocketIO(app, cors_allowed_origins="*") # TODO remove later +api = Blueprint("api", __name__) +socketio = SocketIO(app, cors_allowed_origins="*") # NOTE debug +CORS(api, origins="*") # NOTE debug + @app.route("/") @app.route("/slideshow") @@ -12,44 +18,49 @@ socketio = SocketIO(app, cors_allowed_origins="*") # TODO remove later def home(): return send_from_directory("static/public", "index.html") -api = Blueprint("api", __name__) -CORS(api, origins="*") # For debugging TODO remove later -#@api.route("/seek") @socketio.on("seek") def seek(increment): - pd = app.config["pix_display"] - - pd.queue.put(lambda: pd.seek(increment)) - while not pd.queue.empty(): + if not (display := PixMan().display): + return {} + display.queue.put(lambda: display.seek(increment)) + while not display.queue.empty(): pass - return { - "imageTime": pd.image_time, - "imageIndex": pd.current_texture_index, - } + return { "imageIndex": display.current_texture_index } + @api.route("/albums") def get_albums(): - ic = app.config["immich_connector"] + if not (ic := PixMan().immich_connector): + return {} keys = [ "albumName", "albumThumbnailAssetId", "id", "startDate", "endDate", "assetCount", "shared", ] return [{ key: album[key] for key in keys } for album in ic.load_all_albums() ] + @api.route("/asset//thumbnail", defaults={ "size": "thumbnail" }) @api.route("/asset/", defaults={ "size": "preview" }) def get_asset(key, size): + if not (ic := PixMan().immich_connector): + return {} # TODO ensure getting actual album thumb - ic = app.config["immich_connector"] image_data, mimetype = ic.load_image(key, size=size) if image_data is None: abort(400) return send_file(image_data, mimetype=mimetype) + @api.route("/redirect/") def immich_redirect(path): - ic = app.config["immich_connector"] + if not (ic := PixMan().immich_connector): + return {} return redirect(f"{ic.server_url}/{path}") +@api.route("/config/update", methods=["POST"]) +def config_update(): + return { "success": PixMan().update_config(request.json) } + + app.register_blueprint(api, url_prefix="/api") -- cgit v1.2.3 From c5465f7ceed37f1ba6575248e1035e1430e78921 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 16 Jun 2025 21:58:13 -0500 Subject: config route and fix config saving/creation --- flaskapi.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index 45616ec..bb670a2 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -1,4 +1,4 @@ -from flask import Flask, Blueprint, request, send_from_directory, send_file, abort, redirect +from flask import Flask, Blueprint, request, send_from_directory, send_file, abort, redirect, jsonify from flask_socketio import SocketIO, emit from flask_cors import CORS @@ -62,5 +62,9 @@ def immich_redirect(path): def config_update(): return { "success": PixMan().update_config(request.json) } +@api.route("/config") +def config(): + return jsonify(PixMan().config) + app.register_blueprint(api, url_prefix="/api") -- cgit v1.2.3 From c9e7eb40fc5f408cc4177763fd4e82a3632388a1 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 17 Jun 2025 22:34:39 -0500 Subject: cast config from api --- flaskapi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index bb670a2..beabea0 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -3,6 +3,7 @@ from flask_socketio import SocketIO, emit from flask_cors import CORS from manager import PixMan +from settings import Config app = Flask(__name__, static_folder="static/dist", static_url_path="/") @@ -60,7 +61,7 @@ def immich_redirect(path): @api.route("/config/update", methods=["POST"]) def config_update(): - return { "success": PixMan().update_config(request.json) } + return { "success": PixMan().update_config(Config(**request.json)) } @api.route("/config") def config(): -- cgit v1.2.3 From ce64f1a42c9570efa75cc2f568e59d683f499bdd Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 20 Jun 2025 22:32:28 -0500 Subject: config update and more endpoints for api fromtend --- flaskapi.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index beabea0..a539dc5 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -30,16 +30,33 @@ def seek(increment): return { "imageIndex": display.current_texture_index } +@api.route("/albums/update", methods=["POST"]) +def albums_update(): + return { "success": PixMan().update_config(album_list=request.json) } + @api.route("/albums") -def get_albums(): +def albums_get(): if not (ic := PixMan().immich_connector): return {} keys = [ "albumName", "albumThumbnailAssetId", "id", "startDate", "endDate", "assetCount", "shared", ] + selected_albums = PixMan().config.album_list return [{ - key: album[key] for key in keys - } for album in ic.load_all_albums() ] + key: album.get(key, None) for key in keys + } | { "selected": album in selected_albums } for album in ic.load_all_albums() if album["assetCount"] ] + + +@api.route("/asset//filename") +def get_asset_name(key): + if not (ic := PixMan().immich_connector): + return {} + # TODO ensure getting actual album thumb + name = ic.load_image_filename(key) + if name is None: + abort(400) + return { "filename": name } +@api.route("/asset//fullsize", defaults={ "size": "fullsize" }) @api.route("/asset//thumbnail", defaults={ "size": "thumbnail" }) @api.route("/asset/", defaults={ "size": "preview" }) def get_asset(key, size): @@ -61,10 +78,10 @@ def immich_redirect(path): @api.route("/config/update", methods=["POST"]) def config_update(): - return { "success": PixMan().update_config(Config(**request.json)) } + return { "success": PixMan().update_config(**request.json) } @api.route("/config") -def config(): +def config_get(): return jsonify(PixMan().config) -- cgit v1.2.3 From 8fa092b81aa09239e15b44e2002c7d18d3f4244b Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 20 Jun 2025 22:35:34 -0500 Subject: fix selected attr on /albums --- flaskapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index a539dc5..2e2ced4 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -42,7 +42,7 @@ def albums_get(): selected_albums = PixMan().config.album_list return [{ key: album.get(key, None) for key in keys - } | { "selected": album in selected_albums } for album in ic.load_all_albums() if album["assetCount"] ] + } | { "selected": album["id"] in selected_albums } for album in ic.load_all_albums() if album["assetCount"] ] @api.route("/asset//filename") -- cgit v1.2.3 From 0b0c1978c4f7b57a240575de56b8e40d29c3c219 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 24 Jun 2025 18:34:07 -0500 Subject: live reload window display config --- flaskapi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'flaskapi.py') diff --git a/flaskapi.py b/flaskapi.py index 2e2ced4..633eed2 100644 --- a/flaskapi.py +++ b/flaskapi.py @@ -32,7 +32,7 @@ def seek(increment): @api.route("/albums/update", methods=["POST"]) def albums_update(): - return { "success": PixMan().update_config(album_list=request.json) } + return { "success": PixMan().update_config({ "album_list": request.json }) } @api.route("/albums") def albums_get(): @@ -78,7 +78,7 @@ def immich_redirect(path): @api.route("/config/update", methods=["POST"]) def config_update(): - return { "success": PixMan().update_config(**request.json) } + return { "success": PixMan().update_config(request.json) } @api.route("/config") def config_get(): -- cgit v1.2.3