"""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")