Files
2026-09-10 11:34:19 +03:30

33 lines
3.0 KiB
Python

import mimetypes
import magic
from pathlib import Path
from django.core.exceptions import ValidationError
from .models import Attachment,AttachmentPolicy
TYPE_EXT={"IMAGE":{".jpg",".jpeg",".png",".gif",".webp"},"VIDEO":{".mp4",".webm",".mov"},"VOICE":{".webm",".ogg",".mp3",".m4a",".wav"},"PDF":{".pdf"},"WORD":{".doc",".docx"},"EXCEL":{".xls",".xlsx"},"ZIP":{".zip"},"RAR":{".rar"}}
def classify(ext,mime):
if ext==".webm" and str(mime).startswith("audio/"): return "VOICE"
for kind,extensions in TYPE_EXT.items():
if ext in extensions:return kind
return "OTHER"
def save_attachments(message,files,user):
files=list(files); result=[]
counts={}
for upload in files:
ext=Path(Path(upload.name).name).suffix.lower(); kind=classify(ext,getattr(upload,"content_type", "")); counts[kind]=counts.get(kind,0)+1
for kind,count in counts.items():
policy=AttachmentPolicy.objects.filter(attachment_type=kind,is_enabled=True).first()
if not policy: raise ValidationError(f"نوع فایل {kind} مجاز نیست.")
if count>policy.max_files_per_message: raise ValidationError(f"تعداد فایل‌های {kind} بیش از حد مجاز است.")
for upload in files:
name=Path(upload.name).name[:255]; ext=Path(name).suffix.lower(); declared=getattr(upload,"content_type","") or mimetypes.guess_type(name)[0] or "application/octet-stream"
head=upload.read(8192); upload.seek(0); detected=magic.from_buffer(head,mime=True) or "application/octet-stream"; kind=classify(ext,declared)
policy=AttachmentPolicy.objects.filter(attachment_type=kind,is_enabled=True).first()
if not policy: raise ValidationError(f"نوع فایل {ext or name} مجاز نیست.")
if upload.size>policy.max_file_size: raise ValidationError(f"حجم فایل {name} بیش از حد مجاز است.")
if policy.allowed_extensions and ext not in policy.allowed_extensions: raise ValidationError("پسوند فایل مجاز نیست.")
if policy.allowed_mime_types and detected not in policy.allowed_mime_types: raise ValidationError("نوع محتوای واقعی فایل مجاز نیست.")
compatible={"IMAGE":detected.startswith("image/"),"VIDEO":detected.startswith("video/"),"VOICE":detected.startswith("audio/") or detected in {"video/webm","application/ogg"},"PDF":detected=="application/pdf","ZIP":detected in {"application/zip","application/x-zip-compressed"}}.get(kind,True)
if not compatible: raise ValidationError(f"محتوای واقعی فایل {name} با پسوند آن سازگار نیست.")
obj=Attachment(message=message,file=upload,original_name=name,stored_name="pending",relative_path="pending",attachment_type=kind,mime_type=detected,extension=ext,file_size=upload.size,uploaded_by=user); obj.save(); obj.stored_name=Path(obj.file.name).name; obj.relative_path=obj.file.name; obj.save(update_fields=["stored_name","relative_path"]); result.append(obj)
return result