diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/Letterboxd-Diary-Posters-Picker-Backend.iml b/.idea/Letterboxd-Diary-Posters-Picker-Backend.iml new file mode 100644 index 0000000..5aba0af --- /dev/null +++ b/.idea/Letterboxd-Diary-Posters-Picker-Backend.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..100bc1c --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..927064f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..146f9ba --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/main.py b/main.py index cee0556..d233c9f 100644 --- a/main.py +++ b/main.py @@ -5,20 +5,22 @@ from src.api.routes import api_bp from flask_sse import sse from config import config + def create_app(): app = Flask(__name__) CORS(app) - + env = os.environ.get('FLASK_ENV', 'default') app.config.from_object(config[env]) - + app.register_blueprint(sse, url_prefix='/stream') app.register_blueprint(api_bp, url_prefix='/api') - + return app + if __name__ == "__main__": - port = int(os.environ.get("PORT", 5000)) + port = int(os.environ.get("PORT", 5000)) app = create_app() - app.run(host='0.0.0.0', port=port, debug=True) \ No newline at end of file + app.run(host='0.0.0.0', port=port, debug=True) diff --git a/src/api/routes.py b/src/api/routes.py index 36b8497..0958f5a 100644 --- a/src/api/routes.py +++ b/src/api/routes.py @@ -1,7 +1,10 @@ import io import math import os -from flask import Blueprint, jsonify, request, session +import zipfile + +import requests +from flask import Blueprint, jsonify, request, session, send_file from werkzeug.utils import secure_filename from src.services.tmdb_service import TMDBService from src.services.image_service import ImageService @@ -149,3 +152,48 @@ def delete_csv(): except Exception as e: print(f"Error in delete_csv: {str(e)}") return jsonify({'error': 'An error occurred while deleting the CSV file'}), 500 + + +@api_bp.route('/download-posters', methods=['POST']) +def download_posters(): + user_id = session.get('user_id') + + if user_id not in user_csvs: + return jsonify({'error': 'No CSV file found. Please upload a CSV file.'}), 404 + + csv_content = user_csvs[user_id] + + try: + zip_buffer = io.BytesIO() + + with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file: + if isinstance(csv_content, bytes): + df = pd.read_csv(io.StringIO(csv_content.decode('utf-8'))) + else: + df = pd.read_csv(io.StringIO(csv_content)) + + movies = df.to_dict('records') + + for movie in movies: + poster_url = get_poster_url(movie['Name'], movie['Year']) + if poster_url: + try: + response = requests.get(poster_url) + if response.status_code == 200: + zip_file.writestr(f"{movie['Name']}_{movie['Year']}.jpg", response.content) + except Exception as e: + print(f"Error downloading poster for {movie['Name']}: {str(e)}") + continue + + zip_buffer.seek(0) + + return send_file( + zip_buffer, + mimetype='application/zip', + as_attachment=True, + download_name='posters.zip' + ) + + except Exception as e: + print(f"Error in download_posters: {str(e)}") + return jsonify({'error': 'An error occurred while fetching movie posters'}), 500 diff --git a/src/services/file_utils.py b/src/services/file_utils.py index bb81a0e..a7f1f1a 100644 --- a/src/services/file_utils.py +++ b/src/services/file_utils.py @@ -1,8 +1,10 @@ import re import os + def clean_filename(filename): return re.sub(r'[\\/*?:"<>|]', '_', filename) + def ensure_directory(directory): - os.makedirs(directory, exist_ok=True) \ No newline at end of file + os.makedirs(directory, exist_ok=True) diff --git a/src/services/image_service.py b/src/services/image_service.py index d40992e..8f6e516 100644 --- a/src/services/image_service.py +++ b/src/services/image_service.py @@ -2,6 +2,7 @@ import requests from PIL import Image import io + class ImageService: def download_image(self, image_url, save_path=None): response = requests.get(image_url, stream=True) @@ -10,4 +11,4 @@ class ImageService: if save_path: image.save(save_path) return image - return None \ No newline at end of file + return None