post / templates /base.py
ex510's picture
Upload 3 files
ab4b623 verified
"""
Base Template Class
كل تمبلت جديد بيرث من الكلاس ده
"""
from abc import ABC, abstractmethod
from PIL import Image
from dataclasses import dataclass
from typing import Optional
@dataclass
class RenderRequest:
"""البيانات اللي بتيجي من n8n"""
title: str
discount: str = ""
badge: str = ""
phone: str = ""
website: str = ""
image_path: str = ""
music_path: str = ""
output_path: str = "/tmp/output.mp4"
# إضافات اختيارية
bg_left: str = ""
bg_right: str = ""
duration: int = 6
fps: int = 30
width: int = 1280
height: int = 720
music_volume: float = 0.20
class BaseTemplate(ABC):
"""
الكلاس الأساسي — كل تمبلت بيرث منه
عشان تعمل تمبلت جديد:
1. عمل ملف في templates/
2. ترث من BaseTemplate
3. تعمل make_frame بتاعك
"""
NAME = "base"
DESCRIPTION = "Base template"
AUTHOR = ""
def ease_out(self, t: float) -> float:
return 1 - (1 - t) ** 3
def ease_in_out(self, t: float) -> float:
return t * t * (3 - 2 * t)
def load_font(self, size: int):
from PIL import ImageFont
candidates = [
'/tmp/arabic.ttf',
'/usr/share/fonts/truetype/noto/NotoNaskhArabic-Bold.ttf',
'/usr/share/fonts/truetype/noto/NotoSansArabic-Bold.ttf',
'/usr/share/fonts/opentype/noto/NotoNaskhArabic-Bold.otf',
'C:/Windows/Fonts/arial.ttf',
]
for path in candidates:
import os
if os.path.exists(path):
try:
return ImageFont.truetype(path, size)
except:
continue
return ImageFont.load_default()
def parse_color(self, s: str, default: tuple) -> tuple:
try:
return tuple(int(x) for x in s.split(','))
except:
return default
@abstractmethod
def make_frame(self, t: float, req: RenderRequest, product_img, logo_img) -> Image.Image:
"""
ارسم frame واحد
t = الوقت الحالي بالثواني
يرجع PIL Image RGB
"""
pass
@property
def info(self) -> dict:
return {
"name": self.NAME,
"description": self.DESCRIPTION,
"author": self.AUTHOR,
}