diff --git a/mailer.py b/mailer.py index fd0c741..00e180b 100644 --- a/mailer.py +++ b/mailer.py @@ -1,6 +1,7 @@ import os import asyncio from io import BytesIO +from datetime import datetime from nio import AsyncClient, UploadResponse, RoomSendResponse @@ -22,27 +23,67 @@ async def send_order(pdf_path: str, analysis: dict, room_id: str, name: str, com if getattr(login_resp, "access_token", None) is None: raise RuntimeError(f"Failed to login to Matrix: {login_resp}") - # Build German summary text + # Determine if document is color or B&W + has_color = analysis['total_area_color'] > 0 + color_marker = "Farbe" if has_color else "SW" + + # Generate new filename: ISO timestamp, name, price, color marker + # Format: YYYY-MM-DDTHHMM_Name_PriceEUR_ColorMarker.pdf + timestamp = datetime.now().strftime("%Y-%m-%dT%H%M") + # Sanitize name for filename (remove special chars, limit length) + safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_')).strip() + safe_name = safe_name.replace(' ', '_')[:30] # Max 30 chars + # Use underscore instead of decimal point/comma for price + price_str = f"{analysis['grand_total']:.2f}".replace('.', '_') + new_filename = f"{timestamp}_{safe_name}_{price_str}EUR_{color_marker}.pdf" + + # Build condensed German summary - focus on key info summary_lines = [ - f"📄 Datei: {analysis['filename']}", - f"👤 Name: {name}", + "=== NEUER DRUCKAUFTRAG ===", "", - f"💰 Gesamtkosten: {analysis['grand_total']:.2f} €", - f" - S/W: {analysis['total_area_black']:.2f} m² = {analysis['total_cost_black']:.2f} €", - f" - Farbe: {analysis['total_area_color']:.2f} m² = {analysis['total_cost_color']:.2f} €", - "", - "📝 Seitenübersicht:" + f"Name: {name}", + f"Preis: {analysis['grand_total']:.2f} EUR", ] - for page in analysis["pages"]: - seitenart = "Farbe" if page["is_color"] else "S/W" + # Add comment prominently if provided + if comment.strip(): + summary_lines.extend([ + "", + f"Kommentar:", + f"{comment.strip()}", + ]) + + # Add compact breakdown + summary_lines.extend([ + "", + "Details:", + ]) + + if analysis['total_area_black'] > 0: summary_lines.append( - f"Seite {page['page']}: {page['width_m']*1000:.0f}×{page['height_m']*1000:.0f} mm, " - f"{seitenart}, Kosten {page['cost']:.2f} €" + f" - S/W: {analysis['total_area_black']:.2f} m2 -> {analysis['total_cost_black']:.2f} EUR" ) - if comment.strip(): - summary_lines.append("\n💬 Nutzerkommentar:\n" + comment.strip()) + if analysis['total_area_color'] > 0: + summary_lines.append( + f" - Farbe: {analysis['total_area_color']:.2f} m2 -> {analysis['total_cost_color']:.2f} EUR" + ) + + # Add page count summary + total_pages = len(analysis['pages']) + color_pages = sum(1 for p in analysis['pages'] if p['is_color']) + bw_pages = total_pages - color_pages + summary_lines.append(f" - Seiten: {total_pages} gesamt ({bw_pages} S/W, {color_pages} Farbe)") + + # Optional: Add detailed page breakdown for small documents + if total_pages <= 5: # Only show details for small documents + summary_lines.append("") + summary_lines.append("Seiten:") + for page in analysis["pages"]: + seitenart = "Farbe" if page["is_color"] else "S/W" + summary_lines.append( + f" - S.{page['page']}: {page['width_m']*1000:.0f}x{page['height_m']*1000:.0f}mm, {seitenart}, {page['cost']:.2f} EUR" + ) summary_text = "\n".join(summary_lines) @@ -55,14 +96,14 @@ async def send_order(pdf_path: str, analysis: dict, room_id: str, name: str, com if not (isinstance(text_resp, RoomSendResponse) and text_resp.event_id): raise RuntimeError(f"Failed to send order summary: {text_resp}") - # Upload PDF + # Upload PDF with new filename with open(pdf_path, "rb") as f: pdf_bytes = f.read() upload_resp, upload_err = await client.upload( data_provider=BytesIO(pdf_bytes), content_type="application/pdf", - filename=os.path.basename(pdf_path), + filename=new_filename, # Use generated filename filesize=len(pdf_bytes), ) @@ -75,14 +116,14 @@ async def send_order(pdf_path: str, analysis: dict, room_id: str, name: str, com message_type="m.room.message", content={ "msgtype": "m.file", - "body": os.path.basename(pdf_path), + "body": new_filename, # Display new filename "url": upload_resp.content_uri, }, ) if not (isinstance(file_resp, RoomSendResponse) and file_resp.event_id): raise RuntimeError(f"Failed to send PDF message: {file_resp}") - print(f"✅ Text summary and PDF sent to room {room_id}") + print(f"✅ Order sent to room {room_id} as {new_filename}") finally: await client.logout() diff --git a/preview_message_format.py b/preview_message_format.py new file mode 100644 index 0000000..03111f3 --- /dev/null +++ b/preview_message_format.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +""" +Preview the new Matrix message format +""" + +def preview_message(): + # Sample data + name = "Anna Schmidt" + comment = "Bitte auf mattem Papier drucken. Danke!" + analysis = { + 'filename': 'presentation.pdf', + 'grand_total': 12.50, + 'total_area_black': 1.5, + 'total_cost_black': 6.0, + 'total_area_color': 1.3, + 'total_cost_color': 6.5, + 'pages': [ + {'page': 1, 'width_m': 0.21, 'height_m': 0.297, 'is_color': False, 'cost': 2.0}, + {'page': 2, 'width_m': 0.21, 'height_m': 0.297, 'is_color': True, 'cost': 2.5}, + {'page': 3, 'width_m': 0.21, 'height_m': 0.297, 'is_color': False, 'cost': 2.0}, + {'page': 4, 'width_m': 0.21, 'height_m': 0.297, 'is_color': True, 'cost': 2.5}, + {'page': 5, 'width_m': 0.21, 'height_m': 0.297, 'is_color': False, 'cost': 2.0}, + {'page': 6, 'width_m': 0.21, 'height_m': 0.297, 'is_color': True, 'cost': 1.5}, + ] + } + + # Generate filename preview + from datetime import datetime + timestamp = datetime.now().strftime("%Y-%m-%dT%H%M") + safe_name = "".join(c for c in name if c.isalnum() or c in (' ', '-', '_')).strip() + safe_name = safe_name.replace(' ', '_')[:30] + has_color = analysis['total_area_color'] > 0 + color_marker = "Farbe" if has_color else "SW" + price_str = f"{analysis['grand_total']:.2f}".replace('.', '_') + new_filename = f"{timestamp}_{safe_name}_{price_str}EUR_{color_marker}.pdf" + + # Generate message + summary_lines = [ + "=== NEUER DRUCKAUFTRAG ===", + "", + f"Name: {name}", + f"Preis: {analysis['grand_total']:.2f} EUR", + ] + + if comment.strip(): + summary_lines.extend([ + "", + f"Kommentar:", + f"{comment.strip()}", + ]) + + summary_lines.extend([ + "", + "Details:", + ]) + + if analysis['total_area_black'] > 0: + summary_lines.append( + f" - S/W: {analysis['total_area_black']:.2f} m2 -> {analysis['total_cost_black']:.2f} EUR" + ) + + if analysis['total_area_color'] > 0: + summary_lines.append( + f" - Farbe: {analysis['total_area_color']:.2f} m2 -> {analysis['total_cost_color']:.2f} EUR" + ) + + total_pages = len(analysis['pages']) + color_pages = sum(1 for p in analysis['pages'] if p['is_color']) + bw_pages = total_pages - color_pages + summary_lines.append(f" - Seiten: {total_pages} gesamt ({bw_pages} S/W, {color_pages} Farbe)") + + # Only show page details for <= 5 pages + if total_pages <= 5: + summary_lines.append("") + summary_lines.append("Seiten:") + for page in analysis["pages"]: + seitenart = "Farbe" if page["is_color"] else "S/W" + summary_lines.append( + f" - S.{page['page']}: {page['width_m']*1000:.0f}x{page['height_m']*1000:.0f}mm, {seitenart}, {page['cost']:.2f} EUR" + ) + + print("=" * 60) + print("NEW FILENAME:") + print("=" * 60) + print(new_filename) + print() + print("=" * 60) + print("MESSAGE PREVIEW:") + print("=" * 60) + print("\n".join(summary_lines)) + print() + print("=" * 60) + + +if __name__ == "__main__": + print("\n📝 SMALL DOCUMENT EXAMPLE (5 pages, with details):\n") + preview_message() + + print("\n\n📚 LARGE DOCUMENT EXAMPLE (6+ pages, no details):\n") + # Simulate larger document + import random + name = "Max Mustermann" + comment = "" + analysis = { + 'filename': 'thesis.pdf', + 'grand_total': 45.80, + 'total_area_black': 8.5, + 'total_cost_black': 34.0, + 'total_area_color': 2.36, + 'total_cost_color': 11.8, + 'pages': [{'page': i, 'width_m': 0.21, 'height_m': 0.297, + 'is_color': i % 3 == 0, 'cost': 5.0 if i % 3 == 0 else 4.0} + for i in range(1, 11)] + } + + from datetime import datetime + timestamp = datetime.now().strftime("%Y-%m-%dT%H%M") + safe_name = "Max_Mustermann" + has_color = analysis['total_area_color'] > 0 + color_marker = "Farbe" if has_color else "SW" + price_str = f"{analysis['grand_total']:.2f}".replace('.', '_') + new_filename = f"{timestamp}_{safe_name}_{price_str}EUR_{color_marker}.pdf" + + summary_lines = [ + "=== NEUER DRUCKAUFTRAG ===", + "", + f"Name: {name}", + f"Preis: {analysis['grand_total']:.2f} EUR", + "", + "Details:", + f" - S/W: {analysis['total_area_black']:.2f} m2 -> {analysis['total_cost_black']:.2f} EUR", + f" - Farbe: {analysis['total_area_color']:.2f} m2 -> {analysis['total_cost_color']:.2f} EUR", + ] + + total_pages = len(analysis['pages']) + color_pages = sum(1 for p in analysis['pages'] if p['is_color']) + bw_pages = total_pages - color_pages + summary_lines.append(f" - Seiten: {total_pages} gesamt ({bw_pages} S/W, {color_pages} Farbe)") + + print("=" * 60) + print("NEW FILENAME:") + print("=" * 60) + print(new_filename) + print() + print("=" * 60) + print("MESSAGE PREVIEW:") + print("=" * 60) + print("\n".join(summary_lines)) + print("\n(Page details omitted for documents > 5 pages)") + print() + print("=" * 60) diff --git a/test_matrix_connection.py b/test_matrix_connection.py new file mode 100644 index 0000000..bbf58c7 --- /dev/null +++ b/test_matrix_connection.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +""" +Test Matrix connection from host machine perspective +""" +import asyncio +import os +from nio import AsyncClient + + +async def test_connection(homeserver_url: str): + """Test connection to Matrix homeserver""" + print(f"\n🔍 Testing connection to: {homeserver_url}") + + matrix_user = os.environ.get("MATRIX_USER", "@einszwovier:einszwovier.local") + matrix_pass = os.environ.get("MATRIX_PASS", "einszwo4") + + client = AsyncClient(homeserver_url, matrix_user) + + try: + print(f" User: {matrix_user}") + print(f" Attempting login...") + + resp = await client.login(matrix_pass) + + if hasattr(resp, 'access_token'): + print(f" ✅ SUCCESS! Logged in as {matrix_user}") + print(f" Device ID: {resp.device_id}") + await client.logout() + else: + print(f" ❌ FAILED: {resp}") + + except Exception as e: + print(f" ❌ ERROR: {e}") + finally: + await client.close() + + +async def main(): + print("=" * 60) + print("Matrix Connection Test") + print("=" * 60) + + # Test different homeserver URLs + test_urls = [ + "http://localhost:8008", + "http://127.0.0.1:8008", + "http://einszwovier.local:8008", + ] + + for url in test_urls: + await test_connection(url) + + print("\n" + "=" * 60) + print("Recommendation:") + print("If localhost/127.0.0.1 works but einszwovier.local fails,") + print("configure Element to use: http://localhost:8008") + print("=" * 60) + + +if __name__ == "__main__": + asyncio.run(main())