134 lines
5.2 KiB
Python
134 lines
5.2 KiB
Python
import os
|
|
import asyncio
|
|
from io import BytesIO
|
|
from datetime import datetime
|
|
from nio import AsyncClient, UploadResponse, RoomSendResponse
|
|
|
|
|
|
async def send_order(pdf_path: str, analysis: dict, room_id: str, name: str, comment: str = ""):
|
|
"""
|
|
Sends a print order summary + PDF to the specified Matrix room.
|
|
"""
|
|
matrix_user = os.environ.get("MATRIX_USER")
|
|
matrix_pass = os.environ.get("MATRIX_PASS")
|
|
homeserver = os.environ.get("MATRIX_HOMESERVER", "http://einszwovier.local:8008")
|
|
|
|
if not matrix_user or not matrix_pass:
|
|
raise RuntimeError("Missing MATRIX_USER or MATRIX_PASS in environment")
|
|
|
|
client = AsyncClient(homeserver, matrix_user)
|
|
|
|
try:
|
|
login_resp = await client.login(matrix_pass)
|
|
if getattr(login_resp, "access_token", None) is None:
|
|
raise RuntimeError(f"Failed to login to Matrix: {login_resp}")
|
|
|
|
# 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 = [
|
|
"=== NEUER DRUCKAUFTRAG ===",
|
|
"",
|
|
f"Name: {name}",
|
|
f"Preis: {analysis['grand_total']:.2f} EUR",
|
|
]
|
|
|
|
# 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" - 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"
|
|
)
|
|
|
|
# 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)
|
|
|
|
# Send summary message
|
|
text_resp = await client.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content={"msgtype": "m.text", "body": summary_text},
|
|
)
|
|
if not (isinstance(text_resp, RoomSendResponse) and text_resp.event_id):
|
|
raise RuntimeError(f"Failed to send order summary: {text_resp}")
|
|
|
|
# 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=new_filename, # Use generated filename
|
|
filesize=len(pdf_bytes),
|
|
)
|
|
|
|
if upload_err or not (isinstance(upload_resp, UploadResponse) and upload_resp.content_uri):
|
|
raise RuntimeError(f"Failed to upload PDF: {upload_err or upload_resp}")
|
|
|
|
# Send PDF as file message
|
|
file_resp = await client.room_send(
|
|
room_id=room_id,
|
|
message_type="m.room.message",
|
|
content={
|
|
"msgtype": "m.file",
|
|
"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"✅ Order sent to room {room_id} as {new_filename}")
|
|
|
|
finally:
|
|
await client.logout()
|
|
await client.close()
|
|
|
|
|
|
def send_order_sync(pdf_path: str, analysis: dict, room_id: str, name: str, comment: str = ""):
|
|
asyncio.run(send_order(pdf_path, analysis, room_id, name, comment))
|