Добавлен веб-личный кабинет: посты, контент-план, медиа-библиотека и генерация картинок
This commit is contained in:
1 parent
d8c086d3b4
commit
81625b2e6f
35 files changed
+2220
-64
No files matched your search
@@ -0,0 +1,89 @@
|
||||
import base64
|
||||
import struct
|
||||
|
||||
import requests
|
||||
|
||||
from config import PIAPI_API_KEY, PIAPI_IMAGE_MODEL, get_proxies
|
||||
|
||||
PIAPI_IMAGE_URL = "https://api.piapi.ai/v1/images/generations"
|
||||
|
||||
# Доступные размеры (gpt-image-1)
|
||||
IMAGE_SIZES = {
|
||||
"square": ("1024x1024", "Квадрат 1024x1024"),
|
||||
"wide": ("1536x1024", "Горизонтальный 1536x1024"),
|
||||
"tall": ("1024x1536", "Вертикальный 1024x1536"),
|
||||
}
|
||||
|
||||
# Пресеты стилей - дописываются к промпту
|
||||
STYLE_PRESETS = {
|
||||
"none": ("Без стиля", ""),
|
||||
"photo": ("Фотореализм", ", ultra realistic photo, professional photography, natural lighting"),
|
||||
"illustration": ("Иллюстрация", ", digital illustration, vibrant colors, detailed"),
|
||||
"minimal": ("Минимализм", ", minimalist style, clean background, simple composition"),
|
||||
"3d": ("3D-рендер", ", 3D render, soft shadows, modern design"),
|
||||
"flat": ("Плоская графика", ", flat vector illustration, bold shapes, social media style"),
|
||||
}
|
||||
|
||||
|
||||
def detect_ext(data: bytes) -> str:
|
||||
"""Определяет расширение файла по magic-байтам."""
|
||||
if data[:8] == b"\x89PNG\r\n\x1a\n":
|
||||
return ".png"
|
||||
if data[:2] == b"\xff\xd8":
|
||||
return ".jpg"
|
||||
if data[:4] == b"RIFF" and data[8:12] == b"WEBP":
|
||||
return ".webp"
|
||||
if data[:4] == b"GIF8":
|
||||
return ".gif"
|
||||
return ".png"
|
||||
|
||||
|
||||
class ImageGenerator:
|
||||
"""Генерация изображений через PiAPI (OpenAI-совместимый /images/generations)."""
|
||||
|
||||
def __init__(self, model: str | None = None):
|
||||
self.model = model or PIAPI_IMAGE_MODEL
|
||||
self.proxies = get_proxies()
|
||||
|
||||
def generate(self, prompt: str, size: str = "square") -> bytes:
|
||||
"""Генерирует картинку и возвращает её байты. Поднимает исключение при ошибке."""
|
||||
if size not in IMAGE_SIZES:
|
||||
size = "square"
|
||||
size_value = IMAGE_SIZES[size][0]
|
||||
|
||||
response = requests.post(
|
||||
PIAPI_IMAGE_URL,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {PIAPI_API_KEY}",
|
||||
},
|
||||
json={
|
||||
"model": self.model,
|
||||
"prompt": prompt,
|
||||
"n": 1,
|
||||
"size": size_value,
|
||||
},
|
||||
proxies=self.proxies,
|
||||
timeout=240,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json().get("data") or []
|
||||
if not data:
|
||||
raise RuntimeError("Пустой ответ от API картинок")
|
||||
|
||||
item = data[0]
|
||||
if item.get("b64_json"):
|
||||
return base64.b64decode(item["b64_json"])
|
||||
if item.get("url"):
|
||||
img_response = requests.get(item["url"], proxies=self.proxies, timeout=120)
|
||||
img_response.raise_for_status()
|
||||
return img_response.content
|
||||
|
||||
raise RuntimeError("Неожиданный формат ответа от API картинок")
|
||||
|
||||
def build_prompt(self, prompt: str, style: str = "none") -> str:
|
||||
"""Дополняет промпт пресетом стиля."""
|
||||
if style in STYLE_PRESETS:
|
||||
return prompt.strip() + STYLE_PRESETS[style][1]
|
||||
return prompt.strip()
|
||||
Reference in new issue
Block a user