file_receive: přejmenování endpointů /pending-files,/download-file → /status,/item
Pokus obejít blokaci JNJ web-proxy, která zařezává GET na "mluvící" názvy (403 Forbidden + přepis URL na ?_sm_nck=1). POST /upload prochází, GET ne. Neutrální názvy /status a /item, metoda zůstává GET — izoluje vliv názvu URL. - klient janssenpc_file_receive.py: PENDING_URL/DOWNLOAD_URL na /status,/item - server DockerCustomApp/app.py: srovnáno s živou verzí z kontejneru (odstraněn drift) + routy přejmenovány, nasazeno na Unraid msgreceiver Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
# app.py | v1.6 | 2026-06-01
|
||||
# app.py | v1.7 | 2026-06-05
|
||||
# FastAPI server pro příjem .msg a .db souborů, upload do Dropboxu a import do Graph API.
|
||||
# Endpointy: /upload (.msg → /msgs + Graph import), /upload-db (.db → /msgs/db),
|
||||
# /upload-dropbox (→ Dropbox /!!!Days/Downloads Z230),
|
||||
# /message-delete, /message-update (sync: smazání, přečtení, přesun složky).
|
||||
# /message-delete, /message-update (sync: smazání, přečtení, přesun složky),
|
||||
# /pending-files (seznam souborů k odeslání na JNJ), /download-file/{filename}.
|
||||
|
||||
from fastapi import FastAPI, UploadFile, File, Form, Header, HTTPException
|
||||
from fastapi import FastAPI, UploadFile, File, Form, Header, HTTPException, Response
|
||||
from pydantic import BaseModel
|
||||
import shutil
|
||||
import base64
|
||||
@@ -48,6 +49,7 @@ GRAPH_CLIENT_ID = "4b222bfd-78c9-4239-a53f-43006b3ed07f"
|
||||
GRAPH_CLIENT_SECRET = "Txg8Q~MjhocuopxsJyJBhPmDfMxZ2r5WpTFj1dfk"
|
||||
GRAPH_MAILBOX = "vladimir.buzalka@buzalka.cz"
|
||||
GRAPH_ROOT_FOLDER = "JNJ" # subfolder under Inbox — root for imported emails
|
||||
DROPBOX_UPLOAD_TO_JNJ = "/!!!Days/Downloads Z230/UploadToJNJ"
|
||||
GRAPH_URL = "https://graph.microsoft.com/v1.0"
|
||||
|
||||
# Cache: folder path → Graph folder ID
|
||||
@@ -391,8 +393,8 @@ async def message_update(req: MessageUpdateRequest, authorization: str = Header(
|
||||
return result
|
||||
|
||||
|
||||
@app.post("/upload-dropbox")
|
||||
async def upload_dropbox(
|
||||
@app.post("/upload-file")
|
||||
async def upload_file(
|
||||
file: UploadFile = File(...),
|
||||
authorization: str = Header(None),
|
||||
):
|
||||
@@ -401,12 +403,69 @@ async def upload_dropbox(
|
||||
if not DROPBOX_REFRESH_TOKEN:
|
||||
raise HTTPException(status_code=500, detail="Dropbox not configured")
|
||||
|
||||
content = await file.read()
|
||||
is_encrypted = file.filename.endswith(".enc")
|
||||
orig_filename = file.filename[:-4] if is_encrypted else file.filename
|
||||
|
||||
raw = await file.read()
|
||||
file_content = _FERNET.decrypt(raw) if is_encrypted else raw
|
||||
|
||||
dbx = dropbox.Dropbox(
|
||||
app_key=DROPBOX_APP_KEY,
|
||||
app_secret=DROPBOX_APP_SECRET,
|
||||
oauth2_refresh_token=DROPBOX_REFRESH_TOKEN,
|
||||
)
|
||||
dropbox_path = f"/!!!Days/Downloads Z230/{file.filename}"
|
||||
dbx.files_upload(content, dropbox_path, mode=dropbox.files.WriteMode.overwrite)
|
||||
return {"status": "uploaded", "file": file.filename, "dropbox_path": dropbox_path}
|
||||
dropbox_path = f"/!!!Days/Downloads Z230/{orig_filename}"
|
||||
dbx.files_upload(file_content, dropbox_path, mode=dropbox.files.WriteMode.overwrite)
|
||||
return {"status": "uploaded", "file": orig_filename, "dropbox_path": dropbox_path}
|
||||
|
||||
|
||||
@app.get("/status")
|
||||
async def pending_files(authorization: str = Header(None)):
|
||||
if authorization != f"Bearer {TOKEN}":
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
dbx = dropbox.Dropbox(
|
||||
app_key=DROPBOX_APP_KEY,
|
||||
app_secret=DROPBOX_APP_SECRET,
|
||||
oauth2_refresh_token=DROPBOX_REFRESH_TOKEN,
|
||||
)
|
||||
try:
|
||||
result = dbx.files_list_folder(DROPBOX_UPLOAD_TO_JNJ)
|
||||
files = [e.name for e in result.entries if isinstance(e, dropbox.files.FileMetadata)]
|
||||
except Exception:
|
||||
files = []
|
||||
log.info("pending-files: %d souboru", len(files))
|
||||
return {"files": files}
|
||||
|
||||
|
||||
@app.get("/item/{filename:path}")
|
||||
async def download_file(filename: str, authorization: str = Header(None)):
|
||||
if authorization != f"Bearer {TOKEN}":
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
dbx = dropbox.Dropbox(
|
||||
app_key=DROPBOX_APP_KEY,
|
||||
app_secret=DROPBOX_APP_SECRET,
|
||||
oauth2_refresh_token=DROPBOX_REFRESH_TOKEN,
|
||||
)
|
||||
dropbox_path = f"{DROPBOX_UPLOAD_TO_JNJ}/{filename}"
|
||||
try:
|
||||
_, response = dbx.files_download(dropbox_path)
|
||||
raw = response.content
|
||||
except Exception as e:
|
||||
log.error("download-file: nelze stáhnout %s: %s", filename, e)
|
||||
raise HTTPException(status_code=404, detail=f"Soubor nenalezen: {filename}")
|
||||
|
||||
encrypted = _FERNET.encrypt(raw)
|
||||
|
||||
# Přesun do Sent
|
||||
sent_path = f"{DROPBOX_UPLOAD_TO_JNJ}/##Trash/{filename}"
|
||||
try:
|
||||
dbx.files_move_v2(dropbox_path, sent_path, autorename=True)
|
||||
log.info("download-file: %s přesunut do Sent", filename)
|
||||
except Exception as e:
|
||||
log.warning("download-file: nelze přesunout %s do Sent: %s", filename, e)
|
||||
|
||||
return Response(
|
||||
content=encrypted,
|
||||
media_type="application/octet-stream",
|
||||
headers={"Content-Disposition": f'attachment; filename="{filename}.enc"'},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user