diff --git a/.env.sample b/.env.sample index ae1fc46..ffa6b49 100644 --- a/.env.sample +++ b/.env.sample @@ -262,9 +262,36 @@ # Default: https://rebrickable.com/instructions/{path} # BK_REBRICKABLE_LINK_INSTRUCTIONS_PATTERN= -# Optional: User-Agent to use when querying Rebrickable outside of the Rebrick python library -# Default: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' -# BK_REBRICKABLE_USER_AGENT= +# Optional: User-Agent to use when querying Rebrickable and Peeron outside of the Rebrick python library +# Default: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 +# BK_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 + +# Legacy: User-Agent for Rebrickable (use BK_USER_AGENT instead) +# BK_REBRICKABLE_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 + +# Optional: Delay in milliseconds between Peeron page downloads to avoid being potentially blocked +# Default: 1000 +# BK_PEERON_DOWNLOAD_DELAY=1000 + +# Optional: Minimum image size (width/height) for valid Peeron instruction pages +# Images smaller than this are considered error placeholders and will be rejected +# Default: 100 +# BK_PEERON_MIN_IMAGE_SIZE=100 + +# Optional: Pattern for Peeron instruction page URLs. Will be passed to Python .format() +# Supports {set_number} and {version_number} parameters +# Default: http://peeron.com/scans/{set_number}-{version_number} +# BK_PEERON_INSTRUCTION_PATTERN= + +# Optional: Pattern for Peeron thumbnail URLs. Will be passed to Python .format() +# Supports {set_number} and {version_number} parameters +# Default: http://belay.peeron.com/thumbs/{set_number}-{version_number}/ +# BK_PEERON_THUMBNAIL_PATTERN= + +# Optional: Pattern for Peeron scan URLs. Will be passed to Python .format() +# Supports {set_number} and {version_number} parameters +# Default: http://belay.peeron.com/scans/{set_number}-{version_number}/ +# BK_PEERON_SCAN_PATTERN= # Optional: Display Rebrickable links wherever applicable # Default: false diff --git a/bricktracker/socket.py b/bricktracker/socket.py index 10c3358..fd64389 100644 --- a/bricktracker/socket.py +++ b/bricktracker/socket.py @@ -6,6 +6,8 @@ from flask_socketio import SocketIO from .instructions import BrickInstructions from .instructions_list import BrickInstructionsList +from .peeron_instructions import PeeronPage +from .peeron_pdf import PeeronPDF from .set import BrickSet from .socket_decorator import authenticated_socket, rebrickable_socket from .sql import close as sql_close @@ -18,6 +20,7 @@ MESSAGES: Final[dict[str, str]] = { 'CONNECT': 'connect', 'DISCONNECT': 'disconnect', 'DOWNLOAD_INSTRUCTIONS': 'download_instructions', + 'DOWNLOAD_PEERON_PAGES': 'download_peeron_pages', 'FAIL': 'fail', 'IMPORT_SET': 'import_set', 'LOAD_SET': 'load_set', @@ -105,6 +108,56 @@ class BrickSocket(object): instructions.download(path) BrickInstructionsList(force=True) + + @self.socket.on(MESSAGES['DOWNLOAD_PEERON_PAGES'], namespace=self.namespace) # noqa: E501 + @authenticated_socket(self) + def download_peeron_pages(data: dict[str, Any], /) -> None: + logger.debug('Socket: DOWNLOAD_PEERON_PAGES={data} (from: {fr})'.format( + data=data, + fr=request.sid, # type: ignore + )) + + try: + # Extract data from the request + set_number = data.get('set', '') + pages_data = data.get('pages', []) + + if not set_number: + raise ValueError("Set number is required") + + if not pages_data: + raise ValueError("No pages selected") + + # Parse set number + if '-' in set_number: + parts = set_number.split('-', 1) + set_num = parts[0] + version_num = parts[1] if len(parts) > 1 else '1' + else: + set_num = set_number + version_num = '1' + + # Convert page data to PeeronPage objects + pages = [] + for page_data in pages_data: + page = PeeronPage( + page_number=page_data.get('page_number', ''), + thumbnail_url=page_data.get('thumbnail_url', ''), + image_url=page_data.get('image_url', ''), + alt_text=page_data.get('alt_text', '') + ) + pages.append(page) + + # Create PDF generator and start download + pdf_generator = PeeronPDF(set_num, version_num, pages, socket=self) + pdf_generator.create_pdf() + + # Refresh instructions list to include new PDF + BrickInstructionsList(force=True) + + except Exception as e: + logger.error(f"Error in download_peeron_pages: {e}") + self.fail(message=f"Error downloading Peeron pages: {e}") @self.socket.on(MESSAGES['IMPORT_SET'], namespace=self.namespace) @rebrickable_socket(self) diff --git a/requirements.txt b/requirements.txt index 7cd3644..f0e433d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,5 @@ requests tzdata bs4 cloudscraper +fpdf2 +pillow \ No newline at end of file