feat: Add complete Docker deployment with web-based setup wizard
Major additions: - Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js) - Production Docker configuration (docker-compose.prod.yml, .env.production) - Database initialization SQL files (deploy/init_settings.sql) - Template builder system with drag-and-drop UI - Advanced features (OAuth, CDN, enhanced analytics, monetization) - Comprehensive documentation (deployment guides, quick start, feature docs) - Design system with accessibility and responsive layout - Deployment automation scripts (deploy.ps1, generate-secrets.ps1) Setup wizard allows customization of: - Platform name and branding - Domain configuration - Membership tiers and pricing - Admin credentials - Feature toggles Database includes 270+ tables for complete video streaming platform with advanced features for analytics, moderation, template building, and monetization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
701
__install/add_advanced_features.sql
Normal file
701
__install/add_advanced_features.sql
Normal file
@@ -0,0 +1,701 @@
|
||||
-- EasyStream Advanced Features Database Schema
|
||||
-- Version: 2.0
|
||||
-- This file adds support for:
|
||||
-- 1. API & OAuth system
|
||||
-- 2. Advanced analytics
|
||||
-- 3. Monetization features
|
||||
-- 4. CDN integration
|
||||
-- 5. Advanced search
|
||||
-- 6. Collaborative features
|
||||
-- 7. AI features
|
||||
-- 8. Advanced moderation
|
||||
-- 9. Email notifications
|
||||
-- 10. Mobile app support
|
||||
|
||||
-- =====================================================
|
||||
-- 1. API & OAuth System
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_api_keys` (
|
||||
`key_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`api_key` VARCHAR(64) NOT NULL UNIQUE,
|
||||
`api_secret` VARCHAR(64) NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`scopes` JSON DEFAULT NULL COMMENT 'Permission scopes: videos.read, videos.write, etc.',
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`request_count` INT UNSIGNED DEFAULT 0,
|
||||
`last_used_at` DATETIME DEFAULT NULL,
|
||||
`expires_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`revoked_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_api_key` (`api_key`),
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_active` (`is_active`, `expires_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_oauth_tokens` (
|
||||
`token_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`client_id` VARCHAR(64) NOT NULL,
|
||||
`access_token` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`refresh_token` VARCHAR(255) DEFAULT NULL UNIQUE,
|
||||
`token_type` VARCHAR(20) DEFAULT 'Bearer',
|
||||
`scopes` JSON DEFAULT NULL,
|
||||
`expires_at` DATETIME NOT NULL,
|
||||
`refresh_expires_at` DATETIME DEFAULT NULL,
|
||||
`is_revoked` TINYINT(1) DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_access_token` (`access_token`),
|
||||
INDEX `idx_refresh_token` (`refresh_token`),
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_expires` (`expires_at`, `is_revoked`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_api_logs` (
|
||||
`log_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`endpoint` VARCHAR(255) NOT NULL,
|
||||
`method` VARCHAR(10) NOT NULL,
|
||||
`status` SMALLINT UNSIGNED NOT NULL,
|
||||
`duration` FLOAT DEFAULT 0 COMMENT 'Request duration in seconds',
|
||||
`ip_address` VARCHAR(45) DEFAULT NULL,
|
||||
`user_agent` TEXT DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_endpoint` (`endpoint`),
|
||||
INDEX `idx_created` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_webhooks` (
|
||||
`webhook_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`url` VARCHAR(500) NOT NULL,
|
||||
`events` JSON NOT NULL COMMENT 'Events to trigger: video.upload, comment.new, etc.',
|
||||
`secret` VARCHAR(64) NOT NULL,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`last_triggered_at` DATETIME DEFAULT NULL,
|
||||
`failure_count` INT DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_active` (`is_active`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 2. Advanced Analytics System
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_analytics_events` (
|
||||
`event_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`session_id` VARCHAR(64) DEFAULT NULL,
|
||||
`event_type` VARCHAR(50) NOT NULL COMMENT 'view, play, pause, seek, like, comment, share, etc.',
|
||||
`file_key` VARCHAR(20) DEFAULT NULL,
|
||||
`file_type` ENUM('video', 'short', 'live', 'image', 'audio', 'doc', 'blog') DEFAULT NULL,
|
||||
`event_data` JSON DEFAULT NULL COMMENT 'Additional event data',
|
||||
`timestamp_sec` INT UNSIGNED DEFAULT NULL COMMENT 'Video timestamp in seconds',
|
||||
`ip_address` VARCHAR(45) DEFAULT NULL,
|
||||
`user_agent` TEXT DEFAULT NULL,
|
||||
`referrer` VARCHAR(500) DEFAULT NULL,
|
||||
`country` VARCHAR(2) DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_file_key` (`file_key`),
|
||||
INDEX `idx_event_type` (`event_type`),
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_session` (`session_id`),
|
||||
INDEX `idx_created` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_analytics_retention` (
|
||||
`retention_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`timestamp_sec` INT UNSIGNED NOT NULL COMMENT 'Second in the video',
|
||||
`viewers` INT UNSIGNED DEFAULT 0 COMMENT 'Number of viewers at this second',
|
||||
`completed` INT UNSIGNED DEFAULT 0 COMMENT 'Number who completed from here',
|
||||
`dropped` INT UNSIGNED DEFAULT 0 COMMENT 'Number who dropped at this second',
|
||||
`updated_at` DATETIME NOT NULL,
|
||||
UNIQUE KEY `unique_retention` (`file_key`, `timestamp_sec`),
|
||||
INDEX `idx_file_key` (`file_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_analytics_heatmaps` (
|
||||
`heatmap_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`x_coord` FLOAT NOT NULL COMMENT 'X coordinate (0-1)',
|
||||
`y_coord` FLOAT NOT NULL COMMENT 'Y coordinate (0-1)',
|
||||
`clicks` INT UNSIGNED DEFAULT 0,
|
||||
`hovers` INT UNSIGNED DEFAULT 0,
|
||||
`date` DATE NOT NULL,
|
||||
INDEX `idx_file_key` (`file_key`, `date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_analytics_traffic` (
|
||||
`traffic_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`source_type` ENUM('direct', 'search', 'social', 'external', 'internal', 'suggested') NOT NULL,
|
||||
`source_name` VARCHAR(255) DEFAULT NULL COMMENT 'Google, Facebook, etc.',
|
||||
`referrer_url` VARCHAR(500) DEFAULT NULL,
|
||||
`visits` INT UNSIGNED DEFAULT 1,
|
||||
`date` DATE NOT NULL,
|
||||
INDEX `idx_file_key` (`file_key`, `date`),
|
||||
INDEX `idx_source` (`source_type`, `date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_analytics_demographics` (
|
||||
`demo_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`age_range` VARCHAR(20) DEFAULT NULL COMMENT '18-24, 25-34, etc.',
|
||||
`gender` VARCHAR(20) DEFAULT NULL,
|
||||
`country` VARCHAR(2) DEFAULT NULL,
|
||||
`views` INT UNSIGNED DEFAULT 1,
|
||||
`watch_time` INT UNSIGNED DEFAULT 0 COMMENT 'Total watch time in seconds',
|
||||
`date` DATE NOT NULL,
|
||||
INDEX `idx_file_key` (`file_key`, `date`),
|
||||
INDEX `idx_country` (`country`, `date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 3. Monetization Features
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_membership_tiers` (
|
||||
`tier_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL COMMENT 'Channel owner',
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`price_monthly` DECIMAL(10,2) NOT NULL,
|
||||
`currency` VARCHAR(3) DEFAULT 'USD',
|
||||
`perks` JSON DEFAULT NULL COMMENT 'List of membership perks',
|
||||
`badge_url` VARCHAR(500) DEFAULT NULL,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`),
|
||||
INDEX `idx_active` (`is_active`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_memberships` (
|
||||
`membership_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`tier_id` INT UNSIGNED NOT NULL,
|
||||
`subscriber_id` INT UNSIGNED NOT NULL,
|
||||
`channel_owner_id` INT UNSIGNED NOT NULL,
|
||||
`status` ENUM('active', 'cancelled', 'expired', 'paused') DEFAULT 'active',
|
||||
`started_at` DATETIME NOT NULL,
|
||||
`expires_at` DATETIME DEFAULT NULL,
|
||||
`cancelled_at` DATETIME DEFAULT NULL,
|
||||
`payment_method` VARCHAR(50) DEFAULT NULL,
|
||||
`stripe_subscription_id` VARCHAR(255) DEFAULT NULL,
|
||||
INDEX `idx_subscriber` (`subscriber_id`, `status`),
|
||||
INDEX `idx_channel` (`channel_owner_id`, `status`),
|
||||
INDEX `idx_tier` (`tier_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_super_chats` (
|
||||
`super_chat_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL COMMENT 'Sender',
|
||||
`recipient_id` INT UNSIGNED NOT NULL COMMENT 'Receiver (channel owner)',
|
||||
`file_key` VARCHAR(20) DEFAULT NULL COMMENT 'Associated video/live stream',
|
||||
`amount` DECIMAL(10,2) NOT NULL,
|
||||
`currency` VARCHAR(3) DEFAULT 'USD',
|
||||
`message` VARCHAR(500) DEFAULT NULL,
|
||||
`type` ENUM('super_chat', 'super_thanks', 'tip') DEFAULT 'super_chat',
|
||||
`payment_status` ENUM('pending', 'completed', 'refunded', 'failed') DEFAULT 'pending',
|
||||
`stripe_payment_id` VARCHAR(255) DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_recipient` (`recipient_id`, `created_at`),
|
||||
INDEX `idx_file_key` (`file_key`),
|
||||
INDEX `idx_status` (`payment_status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_revenue_shares` (
|
||||
`share_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`period_start` DATE NOT NULL,
|
||||
`period_end` DATE NOT NULL,
|
||||
`ad_revenue` DECIMAL(10,2) DEFAULT 0,
|
||||
`membership_revenue` DECIMAL(10,2) DEFAULT 0,
|
||||
`super_chat_revenue` DECIMAL(10,2) DEFAULT 0,
|
||||
`total_revenue` DECIMAL(10,2) DEFAULT 0,
|
||||
`platform_fee` DECIMAL(10,2) DEFAULT 0,
|
||||
`payout_amount` DECIMAL(10,2) DEFAULT 0,
|
||||
`payout_status` ENUM('pending', 'processing', 'paid', 'failed') DEFAULT 'pending',
|
||||
`payout_date` DATE DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`, `period_start`),
|
||||
INDEX `idx_status` (`payout_status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_ad_campaigns` (
|
||||
`campaign_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`advertiser_id` INT UNSIGNED NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`ad_type` ENUM('pre_roll', 'mid_roll', 'post_roll', 'banner', 'overlay') NOT NULL,
|
||||
`target_categories` JSON DEFAULT NULL,
|
||||
`target_demographics` JSON DEFAULT NULL,
|
||||
`budget_daily` DECIMAL(10,2) DEFAULT NULL,
|
||||
`budget_total` DECIMAL(10,2) DEFAULT NULL,
|
||||
`spent` DECIMAL(10,2) DEFAULT 0,
|
||||
`cpm` DECIMAL(10,2) DEFAULT NULL COMMENT 'Cost per 1000 impressions',
|
||||
`impressions` INT UNSIGNED DEFAULT 0,
|
||||
`clicks` INT UNSIGNED DEFAULT 0,
|
||||
`start_date` DATE NOT NULL,
|
||||
`end_date` DATE DEFAULT NULL,
|
||||
`status` ENUM('draft', 'active', 'paused', 'completed') DEFAULT 'draft',
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_advertiser` (`advertiser_id`),
|
||||
INDEX `idx_status` (`status`, `start_date`, `end_date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_transactions` (
|
||||
`transaction_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`type` ENUM('membership', 'super_chat', 'super_thanks', 'ad_payout', 'tip', 'refund') NOT NULL,
|
||||
`amount` DECIMAL(10,2) NOT NULL,
|
||||
`currency` VARCHAR(3) DEFAULT 'USD',
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`reference_id` VARCHAR(255) DEFAULT NULL COMMENT 'External payment ID',
|
||||
`payment_method` VARCHAR(50) DEFAULT NULL,
|
||||
`status` ENUM('pending', 'completed', 'failed', 'refunded') DEFAULT 'pending',
|
||||
`metadata` JSON DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`, `created_at`),
|
||||
INDEX `idx_type` (`type`, `status`),
|
||||
INDEX `idx_reference` (`reference_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 4. CDN Integration
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_cdn_stats` (
|
||||
`stat_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`cdn_provider` VARCHAR(50) NOT NULL COMMENT 'cloudflare, aws, bunny, etc.',
|
||||
`region` VARCHAR(50) DEFAULT NULL,
|
||||
`bandwidth_mb` DECIMAL(12,2) DEFAULT 0,
|
||||
`requests` INT UNSIGNED DEFAULT 0,
|
||||
`cache_hits` INT UNSIGNED DEFAULT 0,
|
||||
`cache_misses` INT UNSIGNED DEFAULT 0,
|
||||
`date` DATE NOT NULL,
|
||||
INDEX `idx_file_key` (`file_key`, `date`),
|
||||
INDEX `idx_provider` (`cdn_provider`, `date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_cdn_config` (
|
||||
`config_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`provider` VARCHAR(50) NOT NULL,
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`api_key` VARCHAR(255) DEFAULT NULL,
|
||||
`api_secret` VARCHAR(255) DEFAULT NULL,
|
||||
`zone_id` VARCHAR(255) DEFAULT NULL,
|
||||
`base_url` VARCHAR(500) DEFAULT NULL,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`priority` TINYINT DEFAULT 0 COMMENT 'Failover priority',
|
||||
`config_data` JSON DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_active` (`is_active`, `priority`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 5. Advanced Search
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_search_history` (
|
||||
`history_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`session_id` VARCHAR(64) DEFAULT NULL,
|
||||
`query` VARCHAR(500) NOT NULL,
|
||||
`filters` JSON DEFAULT NULL,
|
||||
`results_count` INT UNSIGNED DEFAULT 0,
|
||||
`clicked_file_key` VARCHAR(20) DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr_id` (`usr_id`, `created_at`),
|
||||
INDEX `idx_session` (`session_id`),
|
||||
INDEX `idx_query` (`query`(255))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_search_suggestions` (
|
||||
`suggestion_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`query` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`search_count` INT UNSIGNED DEFAULT 1,
|
||||
`last_searched` DATETIME NOT NULL,
|
||||
`is_trending` TINYINT(1) DEFAULT 0,
|
||||
INDEX `idx_count` (`search_count` DESC),
|
||||
INDEX `idx_trending` (`is_trending`, `last_searched`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_search_analytics` (
|
||||
`analytics_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`query` VARCHAR(500) NOT NULL,
|
||||
`results_count` INT UNSIGNED DEFAULT 0,
|
||||
`avg_click_position` FLOAT DEFAULT NULL,
|
||||
`searches` INT UNSIGNED DEFAULT 1,
|
||||
`clicks` INT UNSIGNED DEFAULT 0,
|
||||
`date` DATE NOT NULL,
|
||||
INDEX `idx_query` (`query`(255), `date`),
|
||||
INDEX `idx_date` (`date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 6. Collaborative Features
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_watch_parties` (
|
||||
`party_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`host_id` INT UNSIGNED NOT NULL,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`name` VARCHAR(255) DEFAULT NULL,
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`invite_code` VARCHAR(20) NOT NULL UNIQUE,
|
||||
`max_participants` INT DEFAULT 50,
|
||||
`current_timestamp` INT UNSIGNED DEFAULT 0 COMMENT 'Current playback position in seconds',
|
||||
`is_playing` TINYINT(1) DEFAULT 0,
|
||||
`is_public` TINYINT(1) DEFAULT 1,
|
||||
`status` ENUM('waiting', 'active', 'ended') DEFAULT 'waiting',
|
||||
`started_at` DATETIME DEFAULT NULL,
|
||||
`ended_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_host` (`host_id`),
|
||||
INDEX `idx_invite` (`invite_code`),
|
||||
INDEX `idx_status` (`status`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_watch_party_participants` (
|
||||
`participant_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`party_id` INT UNSIGNED NOT NULL,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`joined_at` DATETIME NOT NULL,
|
||||
`left_at` DATETIME DEFAULT NULL,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
INDEX `idx_party` (`party_id`, `is_active`),
|
||||
INDEX `idx_usr` (`usr_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_playlist_collaborators` (
|
||||
`collaborator_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`pl_id` INT UNSIGNED NOT NULL,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`permission` ENUM('view', 'add', 'edit', 'admin') DEFAULT 'add',
|
||||
`invited_by` INT UNSIGNED NOT NULL,
|
||||
`invited_at` DATETIME NOT NULL,
|
||||
`accepted_at` DATETIME DEFAULT NULL,
|
||||
`status` ENUM('pending', 'accepted', 'declined', 'removed') DEFAULT 'pending',
|
||||
INDEX `idx_playlist` (`pl_id`, `status`),
|
||||
INDEX `idx_usr` (`usr_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_video_annotations` (
|
||||
`annotation_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`timestamp_start` INT UNSIGNED NOT NULL COMMENT 'Start time in seconds',
|
||||
`timestamp_end` INT UNSIGNED DEFAULT NULL COMMENT 'End time in seconds (optional)',
|
||||
`type` ENUM('note', 'link', 'chapter', 'highlight') DEFAULT 'note',
|
||||
`content` TEXT DEFAULT NULL,
|
||||
`url` VARCHAR(500) DEFAULT NULL COMMENT 'For link annotations',
|
||||
`position_x` FLOAT DEFAULT NULL COMMENT 'X coordinate (0-1)',
|
||||
`position_y` FLOAT DEFAULT NULL COMMENT 'Y coordinate (0-1)',
|
||||
`is_public` TINYINT(1) DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_file` (`file_key`, `is_public`),
|
||||
INDEX `idx_usr` (`usr_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 7. AI Features
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_ai_captions` (
|
||||
`caption_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`language` VARCHAR(10) NOT NULL COMMENT 'en, es, fr, etc.',
|
||||
`provider` VARCHAR(50) DEFAULT NULL COMMENT 'whisper, google, aws',
|
||||
`status` ENUM('pending', 'processing', 'completed', 'failed') DEFAULT 'pending',
|
||||
`vtt_file` VARCHAR(500) DEFAULT NULL,
|
||||
`srt_file` VARCHAR(500) DEFAULT NULL,
|
||||
`confidence_score` FLOAT DEFAULT NULL,
|
||||
`processing_time` FLOAT DEFAULT NULL COMMENT 'Seconds',
|
||||
`error_message` TEXT DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`completed_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_file` (`file_key`, `language`),
|
||||
INDEX `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_ai_moderation` (
|
||||
`moderation_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`content_type` ENUM('video', 'image', 'audio', 'text') NOT NULL,
|
||||
`provider` VARCHAR(50) DEFAULT NULL COMMENT 'openai, google, aws',
|
||||
`nsfw_score` FLOAT DEFAULT NULL COMMENT '0-1',
|
||||
`violence_score` FLOAT DEFAULT NULL,
|
||||
`hate_speech_score` FLOAT DEFAULT NULL,
|
||||
`spam_score` FLOAT DEFAULT NULL,
|
||||
`copyright_match` TINYINT(1) DEFAULT 0,
|
||||
`flags` JSON DEFAULT NULL COMMENT 'Detailed flags',
|
||||
`action_taken` ENUM('none', 'flagged', 'removed', 'age_restricted') DEFAULT 'none',
|
||||
`reviewed_by` INT UNSIGNED DEFAULT NULL COMMENT 'Human moderator',
|
||||
`reviewed_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_file` (`file_key`),
|
||||
INDEX `idx_action` (`action_taken`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_ai_thumbnails` (
|
||||
`thumbnail_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`frame_timestamp` INT UNSIGNED NOT NULL COMMENT 'Second in video',
|
||||
`image_path` VARCHAR(500) NOT NULL,
|
||||
`ai_score` FLOAT DEFAULT NULL COMMENT 'AI quality score 0-1',
|
||||
`is_selected` TINYINT(1) DEFAULT 0,
|
||||
`click_rate` FLOAT DEFAULT NULL COMMENT 'CTR if used',
|
||||
`impressions` INT UNSIGNED DEFAULT 0,
|
||||
`clicks` INT UNSIGNED DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_file` (`file_key`),
|
||||
INDEX `idx_score` (`ai_score` DESC)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_ai_tags` (
|
||||
`tag_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`tag` VARCHAR(100) NOT NULL,
|
||||
`confidence` FLOAT DEFAULT NULL,
|
||||
`source` ENUM('ai', 'user', 'hybrid') DEFAULT 'ai',
|
||||
`is_approved` TINYINT(1) DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_file` (`file_key`),
|
||||
INDEX `idx_tag` (`tag`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 8. Advanced Moderation Tools
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_moderation_rules` (
|
||||
`rule_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`type` ENUM('keyword', 'pattern', 'ai', 'copyright', 'spam') NOT NULL,
|
||||
`pattern` TEXT DEFAULT NULL COMMENT 'Regex or keyword list',
|
||||
`action` ENUM('flag', 'remove', 'warn', 'ban') DEFAULT 'flag',
|
||||
`severity` ENUM('low', 'medium', 'high', 'critical') DEFAULT 'medium',
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_by` INT UNSIGNED NOT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_active` (`is_active`, `type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_moderation_actions` (
|
||||
`action_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`target_type` ENUM('video', 'comment', 'user', 'live', 'post') NOT NULL,
|
||||
`target_id` VARCHAR(50) NOT NULL,
|
||||
`rule_id` INT UNSIGNED DEFAULT NULL,
|
||||
`moderator_id` INT UNSIGNED DEFAULT NULL COMMENT 'NULL if automated',
|
||||
`action` ENUM('warned', 'removed', 'age_restricted', 'demonetized', 'banned') NOT NULL,
|
||||
`reason` TEXT DEFAULT NULL,
|
||||
`is_automated` TINYINT(1) DEFAULT 0,
|
||||
`is_appealed` TINYINT(1) DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_target` (`target_type`, `target_id`),
|
||||
INDEX `idx_moderator` (`moderator_id`),
|
||||
INDEX `idx_created` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_moderation_appeals` (
|
||||
`appeal_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`action_id` INT UNSIGNED NOT NULL,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`reason` TEXT NOT NULL,
|
||||
`evidence` JSON DEFAULT NULL COMMENT 'Additional evidence/URLs',
|
||||
`status` ENUM('pending', 'reviewing', 'approved', 'rejected') DEFAULT 'pending',
|
||||
`reviewed_by` INT UNSIGNED DEFAULT NULL,
|
||||
`review_notes` TEXT DEFAULT NULL,
|
||||
`reviewed_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_action` (`action_id`),
|
||||
INDEX `idx_usr` (`usr_id`),
|
||||
INDEX `idx_status` (`status`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_moderation_queue` (
|
||||
`queue_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`target_type` ENUM('video', 'comment', 'user', 'live', 'post') NOT NULL,
|
||||
`target_id` VARCHAR(50) NOT NULL,
|
||||
`reporter_id` INT UNSIGNED DEFAULT NULL,
|
||||
`reason` VARCHAR(255) DEFAULT NULL,
|
||||
`priority` ENUM('low', 'medium', 'high', 'urgent') DEFAULT 'medium',
|
||||
`status` ENUM('pending', 'in_review', 'resolved', 'dismissed') DEFAULT 'pending',
|
||||
`assigned_to` INT UNSIGNED DEFAULT NULL,
|
||||
`resolved_by` INT UNSIGNED DEFAULT NULL,
|
||||
`resolution` TEXT DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`resolved_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_status` (`status`, `priority`, `created_at`),
|
||||
INDEX `idx_assigned` (`assigned_to`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_user_strikes` (
|
||||
`strike_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`action_id` INT UNSIGNED NOT NULL,
|
||||
`type` ENUM('warning', 'strike', 'suspension', 'ban') NOT NULL,
|
||||
`reason` TEXT NOT NULL,
|
||||
`expires_at` DATETIME DEFAULT NULL COMMENT 'For temporary strikes',
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr` (`usr_id`, `is_active`),
|
||||
INDEX `idx_type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 9. Email Notification System
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_email_queue` (
|
||||
`email_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`to_email` VARCHAR(255) NOT NULL,
|
||||
`to_name` VARCHAR(255) DEFAULT NULL,
|
||||
`from_email` VARCHAR(255) DEFAULT NULL,
|
||||
`from_name` VARCHAR(255) DEFAULT NULL,
|
||||
`subject` VARCHAR(500) NOT NULL,
|
||||
`body_html` LONGTEXT DEFAULT NULL,
|
||||
`body_text` TEXT DEFAULT NULL,
|
||||
`template_name` VARCHAR(100) DEFAULT NULL,
|
||||
`template_data` JSON DEFAULT NULL,
|
||||
`priority` TINYINT DEFAULT 5 COMMENT '1=highest, 10=lowest',
|
||||
`status` ENUM('pending', 'sending', 'sent', 'failed', 'bounced') DEFAULT 'pending',
|
||||
`attempts` TINYINT DEFAULT 0,
|
||||
`error_message` TEXT DEFAULT NULL,
|
||||
`send_at` DATETIME DEFAULT NULL COMMENT 'Scheduled send time',
|
||||
`sent_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_status` (`status`, `send_at`),
|
||||
INDEX `idx_usr` (`usr_id`),
|
||||
INDEX `idx_priority` (`priority`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_email_templates` (
|
||||
`template_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(100) NOT NULL UNIQUE,
|
||||
`subject` VARCHAR(500) NOT NULL,
|
||||
`body_html` LONGTEXT NOT NULL,
|
||||
`body_text` TEXT DEFAULT NULL,
|
||||
`variables` JSON DEFAULT NULL COMMENT 'Available variables: {name}, {url}, etc.',
|
||||
`category` VARCHAR(50) DEFAULT NULL COMMENT 'digest, alert, marketing, transactional',
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_name` (`name`),
|
||||
INDEX `idx_category` (`category`, `is_active`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_email_preferences` (
|
||||
`preference_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL UNIQUE,
|
||||
`digest_frequency` ENUM('none', 'daily', 'weekly', 'monthly') DEFAULT 'weekly',
|
||||
`notify_comments` TINYINT(1) DEFAULT 1,
|
||||
`notify_replies` TINYINT(1) DEFAULT 1,
|
||||
`notify_likes` TINYINT(1) DEFAULT 1,
|
||||
`notify_subscribers` TINYINT(1) DEFAULT 1,
|
||||
`notify_uploads` TINYINT(1) DEFAULT 1 COMMENT 'From subscriptions',
|
||||
`notify_live_streams` TINYINT(1) DEFAULT 1,
|
||||
`notify_mentions` TINYINT(1) DEFAULT 1,
|
||||
`notify_milestones` TINYINT(1) DEFAULT 1,
|
||||
`marketing_emails` TINYINT(1) DEFAULT 1,
|
||||
`updated_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_usr` (`usr_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_email_logs` (
|
||||
`log_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`email_id` BIGINT UNSIGNED DEFAULT NULL,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`to_email` VARCHAR(255) NOT NULL,
|
||||
`subject` VARCHAR(500) DEFAULT NULL,
|
||||
`status` ENUM('sent', 'delivered', 'opened', 'clicked', 'bounced', 'complained') NOT NULL,
|
||||
`provider_id` VARCHAR(255) DEFAULT NULL COMMENT 'SendGrid message ID',
|
||||
`event_data` JSON DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_email` (`email_id`),
|
||||
INDEX `idx_usr` (`usr_id`, `created_at`),
|
||||
INDEX `idx_status` (`status`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- 10. Mobile App Support
|
||||
-- =====================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_device_tokens` (
|
||||
`token_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`device_token` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`device_type` ENUM('ios', 'android', 'web') NOT NULL,
|
||||
`device_name` VARCHAR(255) DEFAULT NULL,
|
||||
`app_version` VARCHAR(20) DEFAULT NULL,
|
||||
`os_version` VARCHAR(50) DEFAULT NULL,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`last_used_at` DATETIME DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr` (`usr_id`, `is_active`),
|
||||
INDEX `idx_token` (`device_token`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_push_notifications` (
|
||||
`notification_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED DEFAULT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`body` TEXT NOT NULL,
|
||||
`image_url` VARCHAR(500) DEFAULT NULL,
|
||||
`click_action` VARCHAR(500) DEFAULT NULL COMMENT 'Deep link URL',
|
||||
`data` JSON DEFAULT NULL COMMENT 'Additional data payload',
|
||||
`priority` ENUM('normal', 'high') DEFAULT 'normal',
|
||||
`status` ENUM('pending', 'sent', 'failed') DEFAULT 'pending',
|
||||
`sent_count` INT DEFAULT 0,
|
||||
`delivered_count` INT DEFAULT 0,
|
||||
`clicked_count` INT DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL,
|
||||
`sent_at` DATETIME DEFAULT NULL,
|
||||
INDEX `idx_usr` (`usr_id`),
|
||||
INDEX `idx_status` (`status`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `db_offline_downloads` (
|
||||
`download_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`usr_id` INT UNSIGNED NOT NULL,
|
||||
`file_key` VARCHAR(20) NOT NULL,
|
||||
`quality` VARCHAR(20) DEFAULT NULL COMMENT '720p, 1080p, etc.',
|
||||
`file_size` BIGINT UNSIGNED DEFAULT NULL,
|
||||
`expires_at` DATETIME DEFAULT NULL COMMENT 'Download expiry',
|
||||
`downloaded_at` DATETIME NOT NULL,
|
||||
INDEX `idx_usr` (`usr_id`),
|
||||
INDEX `idx_file` (`file_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =====================================================
|
||||
-- Indexes for Performance
|
||||
-- =====================================================
|
||||
|
||||
-- Add composite indexes for common queries
|
||||
ALTER TABLE `db_analytics_events` ADD INDEX `idx_composite_1` (`file_key`, `event_type`, `created_at`);
|
||||
ALTER TABLE `db_transactions` ADD INDEX `idx_composite_1` (`usr_id`, `type`, `status`, `created_at`);
|
||||
|
||||
-- =====================================================
|
||||
-- Initial Data / Default Settings
|
||||
-- =====================================================
|
||||
|
||||
-- Insert default email templates
|
||||
INSERT INTO `db_email_templates` (`name`, `subject`, `body_html`, `body_text`, `category`, `created_at`) VALUES
|
||||
('welcome', 'Welcome to EasyStream!', '<h1>Welcome {name}!</h1><p>Thank you for joining EasyStream...</p>', 'Welcome {name}! Thank you for joining EasyStream...', 'transactional', NOW()),
|
||||
('new_subscriber', 'You have a new subscriber!', '<h2>Great news!</h2><p>{subscriber_name} subscribed to your channel.</p>', '{subscriber_name} subscribed to your channel.', 'alert', NOW()),
|
||||
('new_comment', 'New comment on your video', '<p>{commenter_name} commented: "{comment}"</p>', '{commenter_name} commented: "{comment}"', 'alert', NOW()),
|
||||
('weekly_digest', 'Your weekly EasyStream digest', '<h2>Here is what happened this week...</h2>', 'Here is what happened this week...', 'digest', NOW());
|
||||
|
||||
-- Insert default moderation rules
|
||||
INSERT INTO `db_moderation_rules` (`name`, `type`, `pattern`, `action`, `severity`, `is_active`, `created_by`, `created_at`) VALUES
|
||||
('Spam Keywords', 'keyword', 'spam,scam,phishing,free money', 'flag', 'medium', 1, 1, NOW()),
|
||||
('Hate Speech', 'keyword', 'offensive,hate,slur', 'remove', 'high', 1, 1, NOW());
|
||||
|
||||
-- =====================================================
|
||||
-- Done!
|
||||
-- =====================================================
|
||||
309
__install/add_template_builder.sql
Normal file
309
__install/add_template_builder.sql
Normal file
@@ -0,0 +1,309 @@
|
||||
-- ============================================================================
|
||||
-- EasyStream Template Builder Database Schema
|
||||
-- ============================================================================
|
||||
-- This schema adds drag-and-drop template builder functionality to EasyStream
|
||||
-- Users can create custom page layouts using a visual drag-and-drop interface
|
||||
-- ============================================================================
|
||||
|
||||
-- Template Builder: Store custom user-created templates
|
||||
CREATE TABLE IF NOT EXISTS `db_templatebuilder_templates` (
|
||||
`template_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` INT(11) UNSIGNED NOT NULL,
|
||||
`template_name` VARCHAR(255) NOT NULL,
|
||||
`template_slug` VARCHAR(255) NOT NULL,
|
||||
`template_type` ENUM('homepage', 'channel', 'browse', 'custom_page', 'landing') DEFAULT 'custom_page',
|
||||
`is_active` TINYINT(1) DEFAULT 0,
|
||||
`is_default` TINYINT(1) DEFAULT 0,
|
||||
`template_structure` LONGTEXT NOT NULL COMMENT 'JSON structure of template layout',
|
||||
`template_settings` TEXT COMMENT 'JSON settings (colors, fonts, spacing)',
|
||||
`custom_css` LONGTEXT COMMENT 'User custom CSS',
|
||||
`custom_js` TEXT COMMENT 'User custom JavaScript',
|
||||
`preview_image` VARCHAR(255) DEFAULT NULL,
|
||||
`views` INT(11) DEFAULT 0,
|
||||
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`template_id`),
|
||||
UNIQUE KEY `unique_slug` (`template_slug`),
|
||||
KEY `idx_user` (`user_id`),
|
||||
KEY `idx_type` (`template_type`),
|
||||
KEY `idx_active` (`is_active`),
|
||||
CONSTRAINT `fk_template_user` FOREIGN KEY (`user_id`) REFERENCES `db_accountuser` (`usr_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='User-created custom templates';
|
||||
|
||||
-- Template Builder: Component library (pre-built blocks users can drag)
|
||||
CREATE TABLE IF NOT EXISTS `db_templatebuilder_components` (
|
||||
`component_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`component_name` VARCHAR(255) NOT NULL,
|
||||
`component_slug` VARCHAR(255) NOT NULL,
|
||||
`component_category` ENUM('header', 'hero', 'video_grid', 'video_list', 'sidebar', 'footer', 'text', 'image', 'custom') DEFAULT 'custom',
|
||||
`component_html` LONGTEXT NOT NULL COMMENT 'Smarty template HTML',
|
||||
`component_css` TEXT COMMENT 'Component-specific CSS',
|
||||
`component_settings_schema` TEXT COMMENT 'JSON schema for configurable settings',
|
||||
`is_system` TINYINT(1) DEFAULT 1 COMMENT 'System component (cannot be deleted)',
|
||||
`thumbnail` VARCHAR(255) DEFAULT NULL,
|
||||
`description` TEXT,
|
||||
`created_by` INT(11) UNSIGNED DEFAULT NULL,
|
||||
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`component_id`),
|
||||
UNIQUE KEY `unique_slug` (`component_slug`),
|
||||
KEY `idx_category` (`component_category`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Reusable template components';
|
||||
|
||||
-- Template Builder: Page assignments (which templates apply to which pages)
|
||||
CREATE TABLE IF NOT EXISTS `db_templatebuilder_assignments` (
|
||||
`assignment_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`template_id` INT(11) UNSIGNED NOT NULL,
|
||||
`page_type` VARCHAR(100) NOT NULL COMMENT 'e.g., tpl_browse, tpl_view, tpl_index',
|
||||
`apply_to` ENUM('global', 'user_only', 'channel') DEFAULT 'user_only',
|
||||
`priority` INT(11) DEFAULT 0,
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`assignment_id`),
|
||||
KEY `idx_template` (`template_id`),
|
||||
KEY `idx_page` (`page_type`),
|
||||
KEY `idx_active` (`is_active`),
|
||||
CONSTRAINT `fk_assignment_template` FOREIGN KEY (`template_id`) REFERENCES `db_templatebuilder_templates` (`template_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Template to page assignments';
|
||||
|
||||
-- Template Builder: Version history for templates
|
||||
CREATE TABLE IF NOT EXISTS `db_templatebuilder_versions` (
|
||||
`version_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`template_id` INT(11) UNSIGNED NOT NULL,
|
||||
`version_number` INT(11) NOT NULL,
|
||||
`template_structure` LONGTEXT NOT NULL,
|
||||
`template_settings` TEXT,
|
||||
`custom_css` LONGTEXT,
|
||||
`custom_js` TEXT,
|
||||
`change_note` VARCHAR(500) DEFAULT NULL,
|
||||
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`version_id`),
|
||||
KEY `idx_template` (`template_id`),
|
||||
KEY `idx_version` (`version_number`),
|
||||
CONSTRAINT `fk_version_template` FOREIGN KEY (`template_id`) REFERENCES `db_templatebuilder_templates` (`template_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Template version history';
|
||||
|
||||
-- Template Builder: User preferences and settings
|
||||
CREATE TABLE IF NOT EXISTS `db_templatebuilder_user_prefs` (
|
||||
`pref_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` INT(11) UNSIGNED NOT NULL,
|
||||
`active_template_homepage` INT(11) UNSIGNED DEFAULT NULL,
|
||||
`active_template_channel` INT(11) UNSIGNED DEFAULT NULL,
|
||||
`active_template_browse` INT(11) UNSIGNED DEFAULT NULL,
|
||||
`builder_mode` ENUM('simple', 'advanced') DEFAULT 'simple',
|
||||
`auto_save` TINYINT(1) DEFAULT 1,
|
||||
`show_grid` TINYINT(1) DEFAULT 1,
|
||||
`preferences` TEXT COMMENT 'JSON additional preferences',
|
||||
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`pref_id`),
|
||||
UNIQUE KEY `unique_user` (`user_id`),
|
||||
CONSTRAINT `fk_prefs_user` FOREIGN KEY (`user_id`) REFERENCES `db_accountuser` (`usr_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='User template builder preferences';
|
||||
|
||||
-- ============================================================================
|
||||
-- Insert Default System Components
|
||||
-- ============================================================================
|
||||
|
||||
-- Component: Video Grid (4 columns)
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Video Grid - 4 Columns', 'video_grid_4col', 'video_grid',
|
||||
'<div class="component-video-grid" data-columns="{{columns}}">
|
||||
<div class="video-grid-container">
|
||||
{{video_items}}
|
||||
</div>
|
||||
</div>',
|
||||
'.component-video-grid .video-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat({{columns}}, 1fr);
|
||||
gap: {{gap}}px;
|
||||
padding: {{padding}}px;
|
||||
}',
|
||||
'{"columns": {"type": "number", "default": 4, "min": 1, "max": 6}, "gap": {"type": "number", "default": 16}, "padding": {"type": "number", "default": 20}}',
|
||||
1,
|
||||
'Responsive video grid with configurable columns');
|
||||
|
||||
-- Component: Hero Section
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Hero Banner', 'hero_banner', 'hero',
|
||||
'<div class="component-hero" style="background-image: url({{background_image}});">
|
||||
<div class="hero-overlay"></div>
|
||||
<div class="hero-content">
|
||||
<h1>{{title}}</h1>
|
||||
<p>{{subtitle}}</p>
|
||||
{if {{show_button}}}
|
||||
<a href="{{button_link}}" class="btn btn-primary">{{button_text}}</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>',
|
||||
'.component-hero {
|
||||
position: relative;
|
||||
height: {{height}}px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.hero-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,{{overlay_opacity}});
|
||||
}
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}',
|
||||
'{"height": {"type": "number", "default": 400}, "overlay_opacity": {"type": "number", "default": 0.5, "min": 0, "max": 1, "step": 0.1}, "title": {"type": "text", "default": "Welcome"}, "subtitle": {"type": "text", "default": ""}, "button_text": {"type": "text", "default": "Get Started"}, "button_link": {"type": "text", "default": "#"}, "show_button": {"type": "boolean", "default": true}}',
|
||||
1,
|
||||
'Hero banner with background image and call-to-action');
|
||||
|
||||
-- Component: Video List (Horizontal)
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Video Horizontal List', 'video_list_horizontal', 'video_list',
|
||||
'<div class="component-video-list-h">
|
||||
<h2 class="list-title">{{title}}</h2>
|
||||
<div class="video-scroll-container">
|
||||
{{video_items}}
|
||||
</div>
|
||||
</div>',
|
||||
'.component-video-list-h .video-scroll-container {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
gap: {{gap}}px;
|
||||
padding: {{padding}}px 0;
|
||||
}
|
||||
.component-video-list-h .video-scroll-container::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
}',
|
||||
'{"title": {"type": "text", "default": "Trending Videos"}, "gap": {"type": "number", "default": 16}, "padding": {"type": "number", "default": 10}}',
|
||||
1,
|
||||
'Horizontally scrolling video list');
|
||||
|
||||
-- Component: Sidebar Widget
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Sidebar Widget', 'sidebar_widget', 'sidebar',
|
||||
'<div class="component-sidebar-widget">
|
||||
<h3>{{widget_title}}</h3>
|
||||
<div class="widget-content">
|
||||
{{widget_content}}
|
||||
</div>
|
||||
</div>',
|
||||
'.component-sidebar-widget {
|
||||
background: {{background_color}};
|
||||
padding: {{padding}}px;
|
||||
border-radius: {{border_radius}}px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.component-sidebar-widget h3 {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: {{title_size}}px;
|
||||
}',
|
||||
'{"widget_title": {"type": "text", "default": "Widget Title"}, "background_color": {"type": "color", "default": "#f5f5f5"}, "padding": {"type": "number", "default": 20}, "border_radius": {"type": "number", "default": 8}, "title_size": {"type": "number", "default": 18}}',
|
||||
1,
|
||||
'Configurable sidebar widget container');
|
||||
|
||||
-- Component: Text Block
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Text Block', 'text_block', 'text',
|
||||
'<div class="component-text-block">
|
||||
{if {{show_heading}}}
|
||||
<h2>{{heading}}</h2>
|
||||
{/if}
|
||||
<div class="text-content">{{content}}</div>
|
||||
</div>',
|
||||
'.component-text-block {
|
||||
padding: {{padding}}px;
|
||||
text-align: {{alignment}};
|
||||
}
|
||||
.component-text-block h2 {
|
||||
color: {{heading_color}};
|
||||
font-size: {{heading_size}}px;
|
||||
}
|
||||
.component-text-block .text-content {
|
||||
font-size: {{text_size}}px;
|
||||
line-height: {{line_height}};
|
||||
color: {{text_color}};
|
||||
}',
|
||||
'{"heading": {"type": "text", "default": "Heading"}, "show_heading": {"type": "boolean", "default": true}, "content": {"type": "textarea", "default": "Your content here..."}, "alignment": {"type": "select", "options": ["left", "center", "right"], "default": "left"}, "padding": {"type": "number", "default": 20}, "heading_size": {"type": "number", "default": 24}, "text_size": {"type": "number", "default": 16}, "line_height": {"type": "number", "default": 1.6, "step": 0.1}, "heading_color": {"type": "color", "default": "#333333"}, "text_color": {"type": "color", "default": "#666666"}}',
|
||||
1,
|
||||
'Customizable text block with heading');
|
||||
|
||||
-- Component: Image Block
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Image Block', 'image_block', 'image',
|
||||
'<div class="component-image-block">
|
||||
<img src="{{image_url}}" alt="{{alt_text}}" />
|
||||
{if {{show_caption}}}
|
||||
<p class="image-caption">{{caption}}</p>
|
||||
{/if}
|
||||
</div>',
|
||||
'.component-image-block {
|
||||
text-align: {{alignment}};
|
||||
padding: {{padding}}px;
|
||||
}
|
||||
.component-image-block img {
|
||||
max-width: {{max_width}}%;
|
||||
height: auto;
|
||||
border-radius: {{border_radius}}px;
|
||||
}
|
||||
.component-image-block .image-caption {
|
||||
margin-top: 10px;
|
||||
font-size: {{caption_size}}px;
|
||||
color: {{caption_color}};
|
||||
}',
|
||||
'{"image_url": {"type": "image", "default": ""}, "alt_text": {"type": "text", "default": "Image"}, "caption": {"type": "text", "default": ""}, "show_caption": {"type": "boolean", "default": false}, "alignment": {"type": "select", "options": ["left", "center", "right"], "default": "center"}, "max_width": {"type": "number", "default": 100, "min": 10, "max": 100}, "border_radius": {"type": "number", "default": 0}, "padding": {"type": "number", "default": 20}, "caption_size": {"type": "number", "default": 14}, "caption_color": {"type": "color", "default": "#999999"}}',
|
||||
1,
|
||||
'Image block with optional caption');
|
||||
|
||||
-- Component: Custom HTML
|
||||
INSERT INTO `db_templatebuilder_components`
|
||||
(`component_name`, `component_slug`, `component_category`, `component_html`, `component_css`, `component_settings_schema`, `is_system`, `description`)
|
||||
VALUES
|
||||
('Custom HTML', 'custom_html', 'custom',
|
||||
'<div class="component-custom-html">
|
||||
{{html_content}}
|
||||
</div>',
|
||||
'.component-custom-html {
|
||||
padding: {{padding}}px;
|
||||
}',
|
||||
'{"html_content": {"type": "code", "default": "<p>Your custom HTML here</p>"}, "padding": {"type": "number", "default": 0}}',
|
||||
1,
|
||||
'Custom HTML/Smarty code block');
|
||||
|
||||
-- ============================================================================
|
||||
-- Add permissions for template builder (optional - if using permissions system)
|
||||
-- ============================================================================
|
||||
|
||||
-- Note: Adjust table name if your permissions table is different
|
||||
-- INSERT INTO `db_permissions` (`permission_name`, `permission_slug`, `description`)
|
||||
-- VALUES
|
||||
-- ('Template Builder Access', 'template_builder_access', 'Can access template builder'),
|
||||
-- ('Template Builder Advanced', 'template_builder_advanced', 'Can use advanced features like custom CSS/JS'),
|
||||
-- ('Template Builder Admin', 'template_builder_admin', 'Can manage system components and global templates');
|
||||
|
||||
-- ============================================================================
|
||||
-- Indexes for performance
|
||||
-- ============================================================================
|
||||
|
||||
-- Additional indexes are already included in table definitions above
|
||||
|
||||
-- ============================================================================
|
||||
-- End of Template Builder Schema
|
||||
-- ============================================================================
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user