chore: claude final touches

This commit is contained in:
Daniil
2026-03-17 18:11:23 +03:00
parent 4b90925c2a
commit 0299949553
21 changed files with 1915 additions and 101 deletions
@@ -0,0 +1,192 @@
"""add caption_presets table
Revision ID: d5e6f7a8b9c0
Revises: c4d5e6f7a8b9
Create Date: 2026-03-14 12:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = "d5e6f7a8b9c0"
down_revision: Union[str, None] = "c4d5e6f7a8b9"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.create_table(
"caption_presets",
sa.Column("user_id", sa.UUID(), nullable=True),
sa.Column("name", sa.String(length=128), nullable=False),
sa.Column("description", sa.Text(), nullable=True),
sa.Column("is_system", sa.Boolean(), nullable=False, server_default=sa.text("false")),
sa.Column("style_config", sa.JSON(), nullable=False),
sa.Column("preview_url", sa.String(length=512), nullable=True),
sa.Column("id", sa.UUID(), nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.text("true")),
sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(
op.f("ix_caption_presets_user_id"),
"caption_presets",
["user_id"],
unique=False,
)
# Seed system presets
caption_presets = sa.table(
"caption_presets",
sa.column("id", sa.UUID()),
sa.column("user_id", sa.UUID()),
sa.column("name", sa.String()),
sa.column("description", sa.Text()),
sa.column("is_system", sa.Boolean()),
sa.column("style_config", sa.JSON()),
sa.column("preview_url", sa.String()),
sa.column("is_active", sa.Boolean()),
)
op.bulk_insert(
caption_presets,
[
{
"id": "00000000-0000-4000-a000-000000000001",
"user_id": None,
"name": "Классические",
"description": "Белый текст с тенью, жёлтая подсветка слова",
"is_system": True,
"style_config": {
"text": {
"font_family": "Lobster",
"font_size": 40,
"font_weight": 400,
"text_color": "#FFFFFF",
"highlight_color": "#FFCC00",
"text_shadow": "2px 2px 4px rgba(0,0,0,0.5)",
"text_stroke_width": 0,
"text_stroke_color": "#000000",
},
"layout": {
"vertical_position": "bottom",
"horizontal_alignment": "center",
"padding_px": 20,
"max_width_pct": 90,
"lines_per_screen": 2,
},
"animation": {
"highlight_style": "color_scale",
"highlight_scale": 1.1,
"segment_transition": "fade",
"fade_duration_frames": 3,
"animation_speed": 1.0,
},
"background": {
"bg_color": "rgba(0,0,0,0)",
"bg_blur_px": 0,
"bg_glow_color": None,
"bg_border_radius_px": 0,
"bg_padding_px": 0,
},
},
"preview_url": None,
"is_active": True,
},
{
"id": "00000000-0000-4000-a000-000000000002",
"user_id": None,
"name": "Неон",
"description": "Голубой текст с неоновым свечением, пурпурная подсветка",
"is_system": True,
"style_config": {
"text": {
"font_family": "Courier New",
"font_size": 45,
"font_weight": 400,
"text_color": "#00FFFF",
"highlight_color": "#FF00FF",
"text_shadow": "0 0 5px #0ff, 0 0 10px #0ff, 0 0 20px #0ff",
"text_stroke_width": 0,
"text_stroke_color": "#000000",
},
"layout": {
"vertical_position": "bottom",
"horizontal_alignment": "center",
"padding_px": 20,
"max_width_pct": 90,
"lines_per_screen": 2,
},
"animation": {
"highlight_style": "color_scale",
"highlight_scale": 1.2,
"segment_transition": "fade",
"fade_duration_frames": 3,
"animation_speed": 1.0,
},
"background": {
"bg_color": "rgba(0,0,0,0.6)",
"bg_blur_px": 0,
"bg_glow_color": None,
"bg_border_radius_px": 15,
"bg_padding_px": 20,
},
},
"preview_url": None,
"is_active": True,
},
{
"id": "00000000-0000-4000-a000-000000000003",
"user_id": None,
"name": "Минимализм",
"description": "Маленький белый текст без фона, плавное появление",
"is_system": True,
"style_config": {
"text": {
"font_family": "Inter",
"font_size": 28,
"font_weight": 300,
"text_color": "#FFFFFF",
"highlight_color": "#FFFFFF",
"text_shadow": "1px 1px 2px rgba(0,0,0,0.3)",
"text_stroke_width": 0,
"text_stroke_color": "#000000",
},
"layout": {
"vertical_position": "bottom",
"horizontal_alignment": "center",
"padding_px": 30,
"max_width_pct": 80,
"lines_per_screen": 1,
},
"animation": {
"highlight_style": "color",
"highlight_scale": 1.0,
"segment_transition": "fade",
"fade_duration_frames": 5,
"animation_speed": 1.0,
},
"background": {
"bg_color": "rgba(0,0,0,0)",
"bg_blur_px": 0,
"bg_glow_color": None,
"bg_border_radius_px": 0,
"bg_padding_px": 0,
},
},
"preview_url": None,
"is_active": True,
},
],
)
def downgrade() -> None:
op.drop_index(op.f("ix_caption_presets_user_id"), table_name="caption_presets")
op.drop_table("caption_presets")