Skip to content

Commit 361d025

Browse files
committed
Serving screenshots
1 parent e2e6bd2 commit 361d025

File tree

2 files changed

+39
-59
lines changed

2 files changed

+39
-59
lines changed

ansible/roles/deploy/tasks/main.yml

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
key_file: /opt/keys/deploy_key
1818
accept_hostkey: yes
1919
register: git_pull
20+
notify: restart kindle-automator
2021

2122
# Update Python dependencies if requirements.txt changed
2223
- name: Update Python dependencies if requirements.txt changed
@@ -27,21 +28,3 @@
2728
args:
2829
executable: /bin/bash
2930
when: git_pull.changed
30-
31-
# Notify handler to restart the kindle-automator service
32-
- name: Trigger kindle-automator service restart
33-
debug:
34-
msg: "Triggering kindle-automator service restart"
35-
changed_when: true
36-
notify: restart kindle-automator
37-
38-
# Check service status after restart
39-
- name: Check service status
40-
shell: systemctl status kindle-automator
41-
register: service_status
42-
changed_when: false
43-
failed_when: false
44-
45-
- name: Display service status
46-
debug:
47-
var: service_status.stdout_lines

server/server.py

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import traceback
88
from typing import Optional
99

10-
from flask import Flask, request, send_file
10+
from flask import Flask, make_response, redirect, request, send_file
1111
from flask_restful import Api, Resource
1212

1313
from automator import KindleAutomator
@@ -247,7 +247,6 @@ def post(self):
247247

248248
class ScreenshotResource(Resource):
249249
@ensure_automator_healthy
250-
@handle_automator_response(server)
251250
def get(self):
252251
"""Get current page screenshot and return a URL to access it or display it directly"""
253252
try:
@@ -269,10 +268,10 @@ def get(self):
269268
if save:
270269
# Return URL to access the screenshot (POST method preserves the image)
271270
image_url = f"/image/{image_id}"
272-
return {"screenshot_url": image_url}, 200
271+
return handle_automator_response({"screenshot_url": image_url}, 200)
273272
else:
274-
# Return ImageResource
275-
return ImageResource.get(image_id)
273+
# Use the shared serve_image function to serve the image directly
274+
return serve_image(image_id, delete_after=True)
276275

277276
except Exception as e:
278277
logger.error(f"Error getting screenshot: {e}")
@@ -457,58 +456,56 @@ def post(self):
457456
return {"error": str(e)}, 500
458457

459458

460-
class ImageResource(Resource):
461-
def _get_image_path(self, image_id):
462-
"""Get full path for an image file."""
463-
# Build path to image using project root
464-
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
459+
# Helper function to get image path
460+
def get_image_path(image_id):
461+
"""Get full path for an image file."""
462+
# Build path to image using project root
463+
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
465464

466-
# Ensure .png extension
467-
if not image_id.endswith(".png"):
468-
image_id = f"{image_id}.png"
465+
# Ensure .png extension
466+
if not image_id.endswith(".png"):
467+
image_id = f"{image_id}.png"
469468

470-
return os.path.join(project_root, "screenshots", image_id)
469+
return os.path.join(project_root, "screenshots", image_id)
471470

472-
def get(self, image_id):
473-
"""Get an image by ID and delete it after serving."""
474-
try:
475-
image_path = self._get_image_path(image_id)
471+
# Helper function to serve an image with option to delete after serving
472+
def serve_image(image_id, delete_after=True):
473+
"""Serve an image by ID with option to delete after serving.
474+
475+
This function properly handles the Flask response object to work with Flask-RESTful.
476+
"""
477+
try:
478+
image_path = get_image_path(image_id)
476479

477-
if not os.path.exists(image_path):
478-
logger.error(f"Image not found at path: {image_path}")
479-
return {"error": "Image not found"}, 404
480+
if not os.path.exists(image_path):
481+
logger.error(f"Image not found at path: {image_path}")
482+
return {"error": "Image not found"}, 404
480483

481-
# Return the image file
482-
response = send_file(image_path, mimetype="image/png")
484+
# Create a response that bypasses Flask-RESTful's serialization
485+
response = make_response(send_file(image_path, mimetype="image/png"))
483486

484-
# Delete the file after sending
487+
# Delete the file after sending if requested
488+
if delete_after:
485489
try:
486490
os.remove(image_path)
487491
logger.info(f"Deleted image: {image_path}")
488492
except Exception as e:
489493
logger.error(f"Failed to delete image {image_path}: {e}")
490494

491-
return response
495+
return response
492496

493-
except Exception as e:
494-
logger.error(f"Error serving image: {e}")
495-
return {"error": str(e)}, 500
497+
except Exception as e:
498+
logger.error(f"Error serving image: {e}")
499+
return {"error": str(e)}, 500
500+
501+
class ImageResource(Resource):
502+
def get(self, image_id):
503+
"""Get an image by ID and delete it after serving."""
504+
return serve_image(image_id, delete_after=True)
496505

497506
def post(self, image_id):
498507
"""Get an image by ID without deleting it."""
499-
try:
500-
image_path = self._get_image_path(image_id)
501-
502-
if not os.path.exists(image_path):
503-
logger.error(f"Image not found at path: {image_path}")
504-
return {"error": "Image not found"}, 404
505-
506-
# Return the image file without deleting
507-
return send_file(image_path, mimetype="image/png")
508-
509-
except Exception as e:
510-
logger.error(f"Error serving image: {e}")
511-
return {"error": str(e)}, 500
508+
return serve_image(image_id, delete_after=False)
512509

513510

514511
# Add resources to API

0 commit comments

Comments
 (0)