تم الانتهاء من آخر دفعة تحسينات على المشروع، وتشمل:
تحويل لوحة الإدارة الداخلية من secret header إلى session auth حقيقي مع صلاحيات admin. إضافة دعم إدارة الأدوار من داخل لوحة الإدارة نفسها، مع حماية الحسابات المعتمدة عبر INTERNAL_ADMIN_EMAILS. تحسين بيانات المستخدم في الواجهة والباكند لتشمل role وis_allowlisted_admin. إضافة اختبار frontend مخصص لصفحة /internal/admin بدل الاعتماد فقط على build واختبار routes. تحسين إضافي في الأداء عبر إزالة الاعتماد على pdfjs-dist/pdf.worker في عدّ صفحات PDF واستبداله بمسار أخف باستخدام pdf-lib. تحسين تقسيم الـ chunks في build لتقليل أثر الحزم الكبيرة وفصل أجزاء مثل network, icons, pdf-core, وeditor. التحقق الذي تم: نجاح build للواجهة. نجاح اختبار صفحة الإدارة الداخلية في frontend. نجاح اختبارات auth/admin في backend. نجاح full backend suite مسبقًا مع EXIT:0. ولو تريد نسخة أقصر جدًا، استخدم هذه: آخر التحديثات: تم تحسين نظام الإدارة الداخلية ليعتمد على صلاحيات وجلسات حقيقية بدل secret header، مع إضافة إدارة أدوار من لوحة admin نفسها، وإضافة اختبارات frontend مخصصة للوحة، وتحسين أداء الواجهة عبر إزالة pdf.worker وتحسين تقسيم الـ chunks في build. جميع الاختبارات والتحققات الأساسية المطلوبة نجح
This commit is contained in:
65
backend/app/tasks/barcode_tasks.py
Normal file
65
backend/app/tasks/barcode_tasks.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""Celery tasks for barcode generation."""
|
||||
import os
|
||||
import logging
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from app.extensions import celery
|
||||
from app.services.barcode_service import generate_barcode, BarcodeGenerationError
|
||||
from app.services.storage_service import storage
|
||||
from app.services.task_tracking_service import finalize_task_tracking
|
||||
from app.utils.sanitizer import cleanup_task_files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _cleanup(task_id: str):
|
||||
cleanup_task_files(task_id, keep_outputs=not storage.use_s3)
|
||||
|
||||
|
||||
def _get_output_dir(task_id: str) -> str:
|
||||
output_dir = os.path.join(current_app.config["OUTPUT_FOLDER"], task_id)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
return output_dir
|
||||
|
||||
|
||||
def _finalize_task(
|
||||
task_id, user_id, tool, original_filename, result,
|
||||
usage_source, api_key_id, celery_task_id,
|
||||
):
|
||||
finalize_task_tracking(
|
||||
user_id=user_id, tool=tool, original_filename=original_filename,
|
||||
result=result, usage_source=usage_source, api_key_id=api_key_id,
|
||||
celery_task_id=celery_task_id,
|
||||
)
|
||||
_cleanup(task_id)
|
||||
return result
|
||||
|
||||
|
||||
@celery.task(bind=True, name="app.tasks.barcode_tasks.generate_barcode_task")
|
||||
def generate_barcode_task(
|
||||
self, data, barcode_type, task_id, output_format="png",
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
ext = "svg" if output_format == "svg" else "png"
|
||||
output_path = os.path.join(output_dir, f"{task_id}_barcode.{ext}")
|
||||
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Generating barcode..."})
|
||||
stats = generate_barcode(data, barcode_type, output_path, output_format)
|
||||
final_path = stats.pop("output_path")
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(final_path, task_id, folder="outputs")
|
||||
download_name = f"barcode_{barcode_type}.{ext}"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "barcode", data[:50],
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except BarcodeGenerationError as e:
|
||||
return _finalize_task(task_id, user_id, "barcode", data[:50],
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
111
backend/app/tasks/image_extra_tasks.py
Normal file
111
backend/app/tasks/image_extra_tasks.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""Celery tasks for image extra tools — Crop, Rotate/Flip."""
|
||||
import os
|
||||
import logging
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from app.extensions import celery
|
||||
from app.services.image_extra_service import (
|
||||
crop_image,
|
||||
rotate_flip_image,
|
||||
ImageExtraError,
|
||||
)
|
||||
from app.services.storage_service import storage
|
||||
from app.services.task_tracking_service import finalize_task_tracking
|
||||
from app.utils.sanitizer import cleanup_task_files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _cleanup(task_id: str):
|
||||
cleanup_task_files(task_id, keep_outputs=not storage.use_s3)
|
||||
|
||||
|
||||
def _get_output_dir(task_id: str) -> str:
|
||||
output_dir = os.path.join(current_app.config["OUTPUT_FOLDER"], task_id)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
return output_dir
|
||||
|
||||
|
||||
def _finalize_task(
|
||||
task_id, user_id, tool, original_filename, result,
|
||||
usage_source, api_key_id, celery_task_id,
|
||||
):
|
||||
finalize_task_tracking(
|
||||
user_id=user_id, tool=tool, original_filename=original_filename,
|
||||
result=result, usage_source=usage_source, api_key_id=api_key_id,
|
||||
celery_task_id=celery_task_id,
|
||||
)
|
||||
_cleanup(task_id)
|
||||
return result
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Image Crop
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.image_extra_tasks.crop_image_task")
|
||||
def crop_image_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
left, top, right, bottom, quality=85,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
ext = os.path.splitext(original_filename)[1].lower().strip(".")
|
||||
if ext not in ("png", "jpg", "jpeg", "webp"):
|
||||
ext = "png"
|
||||
output_path = os.path.join(output_dir, f"{task_id}_cropped.{ext}")
|
||||
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Cropping image..."})
|
||||
stats = crop_image(input_path, output_path, left, top, right, bottom, quality)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_cropped.{ext}"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "image-crop", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except ImageExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "image-crop", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Image Rotate/Flip
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.image_extra_tasks.rotate_flip_image_task")
|
||||
def rotate_flip_image_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
rotation=0, flip_horizontal=False, flip_vertical=False, quality=85,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
ext = os.path.splitext(original_filename)[1].lower().strip(".")
|
||||
if ext not in ("png", "jpg", "jpeg", "webp"):
|
||||
ext = "png"
|
||||
output_path = os.path.join(output_dir, f"{task_id}_transformed.{ext}")
|
||||
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Transforming image..."})
|
||||
stats = rotate_flip_image(input_path, output_path, rotation,
|
||||
flip_horizontal, flip_vertical, quality)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_transformed.{ext}"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "image-rotate-flip", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except ImageExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "image-rotate-flip", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
171
backend/app/tasks/pdf_convert_tasks.py
Normal file
171
backend/app/tasks/pdf_convert_tasks.py
Normal file
@@ -0,0 +1,171 @@
|
||||
"""Celery tasks for new PDF conversions — PDF↔PPTX, Excel→PDF, Sign PDF."""
|
||||
import os
|
||||
import logging
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from app.extensions import celery
|
||||
from app.services.pdf_convert_service import (
|
||||
pdf_to_pptx,
|
||||
excel_to_pdf,
|
||||
pptx_to_pdf,
|
||||
sign_pdf,
|
||||
PDFConvertError,
|
||||
)
|
||||
from app.services.storage_service import storage
|
||||
from app.services.task_tracking_service import finalize_task_tracking
|
||||
from app.utils.sanitizer import cleanup_task_files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _cleanup(task_id: str):
|
||||
cleanup_task_files(task_id, keep_outputs=not storage.use_s3)
|
||||
|
||||
|
||||
def _get_output_dir(task_id: str) -> str:
|
||||
output_dir = os.path.join(current_app.config["OUTPUT_FOLDER"], task_id)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
return output_dir
|
||||
|
||||
|
||||
def _finalize_task(
|
||||
task_id, user_id, tool, original_filename, result,
|
||||
usage_source, api_key_id, celery_task_id,
|
||||
):
|
||||
finalize_task_tracking(
|
||||
user_id=user_id, tool=tool, original_filename=original_filename,
|
||||
result=result, usage_source=usage_source, api_key_id=api_key_id,
|
||||
celery_task_id=celery_task_id,
|
||||
)
|
||||
_cleanup(task_id)
|
||||
return result
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PDF to PowerPoint
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_convert_tasks.pdf_to_pptx_task")
|
||||
def pdf_to_pptx_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}.pptx")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Converting PDF to PowerPoint..."})
|
||||
stats = pdf_to_pptx(input_path, output_path)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}.pptx"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {
|
||||
"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats,
|
||||
}
|
||||
return _finalize_task(task_id, user_id, "pdf-to-pptx", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFConvertError as e:
|
||||
return _finalize_task(task_id, user_id, "pdf-to-pptx", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Excel to PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_convert_tasks.excel_to_pdf_task")
|
||||
def excel_to_pdf_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Converting Excel to PDF..."})
|
||||
output_path = excel_to_pdf(input_path, output_dir)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
output_size = os.path.getsize(output_path)
|
||||
result = {
|
||||
"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, "output_size": output_size,
|
||||
}
|
||||
return _finalize_task(task_id, user_id, "excel-to-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFConvertError as e:
|
||||
return _finalize_task(task_id, user_id, "excel-to-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PowerPoint to PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_convert_tasks.pptx_to_pdf_task")
|
||||
def pptx_to_pdf_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Converting PowerPoint to PDF..."})
|
||||
output_path = pptx_to_pdf(input_path, output_dir)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
output_size = os.path.getsize(output_path)
|
||||
result = {
|
||||
"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, "output_size": output_size,
|
||||
}
|
||||
return _finalize_task(task_id, user_id, "pptx-to-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFConvertError as e:
|
||||
return _finalize_task(task_id, user_id, "pptx-to-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sign PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_convert_tasks.sign_pdf_task")
|
||||
def sign_pdf_task(
|
||||
self, input_path, signature_path, task_id, original_filename,
|
||||
page=0, x=100, y=100, width=200, height=80,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}_signed.pdf")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Signing PDF..."})
|
||||
stats = sign_pdf(input_path, signature_path, output_path, page, x, y, width, height)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_signed.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {
|
||||
"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats,
|
||||
}
|
||||
return _finalize_task(task_id, user_id, "sign-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFConvertError as e:
|
||||
return _finalize_task(task_id, user_id, "sign-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
164
backend/app/tasks/pdf_extra_tasks.py
Normal file
164
backend/app/tasks/pdf_extra_tasks.py
Normal file
@@ -0,0 +1,164 @@
|
||||
"""Celery tasks for extended PDF tools — Crop, Flatten, Repair, Metadata."""
|
||||
import os
|
||||
import logging
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from app.extensions import celery
|
||||
from app.services.pdf_extra_service import (
|
||||
crop_pdf,
|
||||
flatten_pdf,
|
||||
repair_pdf,
|
||||
edit_pdf_metadata,
|
||||
PDFExtraError,
|
||||
)
|
||||
from app.services.storage_service import storage
|
||||
from app.services.task_tracking_service import finalize_task_tracking
|
||||
from app.utils.sanitizer import cleanup_task_files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _cleanup(task_id: str):
|
||||
cleanup_task_files(task_id, keep_outputs=not storage.use_s3)
|
||||
|
||||
|
||||
def _get_output_dir(task_id: str) -> str:
|
||||
output_dir = os.path.join(current_app.config["OUTPUT_FOLDER"], task_id)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
return output_dir
|
||||
|
||||
|
||||
def _finalize_task(
|
||||
task_id, user_id, tool, original_filename, result,
|
||||
usage_source, api_key_id, celery_task_id,
|
||||
):
|
||||
finalize_task_tracking(
|
||||
user_id=user_id, tool=tool, original_filename=original_filename,
|
||||
result=result, usage_source=usage_source, api_key_id=api_key_id,
|
||||
celery_task_id=celery_task_id,
|
||||
)
|
||||
_cleanup(task_id)
|
||||
return result
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Crop PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_extra_tasks.crop_pdf_task")
|
||||
def crop_pdf_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
margin_left=0, margin_right=0, margin_top=0, margin_bottom=0, pages="all",
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}_cropped.pdf")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Cropping PDF..."})
|
||||
stats = crop_pdf(input_path, output_path, margin_left, margin_right,
|
||||
margin_top, margin_bottom, pages)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_cropped.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "crop-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "crop-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Flatten PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_extra_tasks.flatten_pdf_task")
|
||||
def flatten_pdf_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}_flattened.pdf")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Flattening PDF..."})
|
||||
stats = flatten_pdf(input_path, output_path)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_flattened.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "flatten-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "flatten-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Repair PDF
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_extra_tasks.repair_pdf_task")
|
||||
def repair_pdf_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}_repaired.pdf")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Repairing PDF..."})
|
||||
stats = repair_pdf(input_path, output_path)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
base = os.path.splitext(original_filename)[0]
|
||||
download_name = f"{base}_repaired.pdf"
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "repair-pdf", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "repair-pdf", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Edit PDF Metadata
|
||||
# ---------------------------------------------------------------------------
|
||||
@celery.task(bind=True, name="app.tasks.pdf_extra_tasks.edit_metadata_task")
|
||||
def edit_metadata_task(
|
||||
self, input_path, task_id, original_filename,
|
||||
title=None, author=None, subject=None, keywords=None, creator=None,
|
||||
user_id=None, usage_source="web", api_key_id=None,
|
||||
):
|
||||
output_dir = _get_output_dir(task_id)
|
||||
output_path = os.path.join(output_dir, f"{task_id}_metadata.pdf")
|
||||
try:
|
||||
self.update_state(state="PROCESSING", meta={"step": "Editing PDF metadata..."})
|
||||
stats = edit_pdf_metadata(input_path, output_path, title, author, subject, keywords, creator)
|
||||
|
||||
self.update_state(state="PROCESSING", meta={"step": "Uploading result..."})
|
||||
s3_key = storage.upload_file(output_path, task_id, folder="outputs")
|
||||
download_name = original_filename
|
||||
download_url = storage.generate_presigned_url(s3_key, original_filename=download_name)
|
||||
|
||||
result = {"status": "completed", "download_url": download_url,
|
||||
"filename": download_name, **stats}
|
||||
return _finalize_task(task_id, user_id, "edit-metadata", original_filename,
|
||||
result, usage_source, api_key_id, self.request.id)
|
||||
except PDFExtraError as e:
|
||||
return _finalize_task(task_id, user_id, "edit-metadata", original_filename,
|
||||
{"status": "failed", "error": str(e)},
|
||||
usage_source, api_key_id, self.request.id)
|
||||
Reference in New Issue
Block a user