#!/usr/bin/env python3 """ TikTok Database Adapter for Unified Database Provides compatibility layer between TikTok module and unified database """ from typing import Optional, Dict from datetime import datetime import json class TikTokDatabaseAdapter: """Adapter to make unified database work with TikTok module""" def __init__(self, unified_db): """Initialize adapter with unified database instance""" self.unified_db = unified_db self.platform = 'tiktok' def get_file_hash(self, file_path: str) -> Optional[str]: """Calculate SHA256 hash of a file (delegates to UnifiedDatabase)""" return self.unified_db.get_file_hash(file_path) def get_download_by_file_hash(self, file_hash: str) -> Optional[Dict]: """Get download record by file hash (delegates to UnifiedDatabase)""" return self.unified_db.get_download_by_file_hash(file_hash) def record_download(self, video_id: str, username: str, filename: str, post_date: Optional[datetime] = None, metadata: Dict = None, file_path: str = None): """Record a TikTok download in the unified database""" # Convert TikTok's video_id to a URL format for unified database # For carousel photos, append filename to make URL unique (otherwise url_hash collision) url = f"https://www.tiktok.com/@{username}/video/{video_id}#{filename}" # Calculate file hash if file_path provided file_hash = None if file_path: try: from pathlib import Path if Path(file_path).exists(): file_hash = self.unified_db.get_file_hash(file_path) except Exception: pass # If hash fails, continue without it # Detect content type from file extension from pathlib import Path ext = Path(filename).suffix.lower() image_exts = {'.jpg', '.jpeg', '.png', '.gif', '.heic', '.heif', '.webp', '.bmp', '.tiff'} content_type = 'image' if ext in image_exts else 'video' return self.unified_db.record_download( url=url, platform=self.platform, source=username, content_type=content_type, filename=filename, post_date=post_date, metadata=metadata, file_hash=file_hash, file_path=file_path ) def is_downloaded(self, video_id: str, username: str = None) -> bool: """Check if a video has been downloaded""" # Check if ANY file from this video_id has been downloaded # (For carousels, URLs include #filename so we need to search by video_id pattern) try: import sqlite3 with self.unified_db.get_connection() as conn: cursor = conn.cursor() # Search for URLs containing this video_id if username: url_pattern = f"https://www.tiktok.com/@{username}/video/{video_id}%" else: url_pattern = f"%/video/{video_id}%" cursor.execute( "SELECT 1 FROM downloads WHERE url LIKE ? AND platform = ? LIMIT 1", (url_pattern, self.platform) ) return cursor.fetchone() is not None except Exception: return False def is_already_downloaded(self, video_id: str) -> bool: """Check if a video has already been downloaded (alias for compatibility)""" return self.is_downloaded(video_id) def get_download_info(self, video_id: str) -> Optional[Dict]: """Get download information for a video""" # This is a simplified lookup - may need to search by video_id in URL results = self.unified_db.get_downloads(platform=self.platform, limit=1000) for download in results: if video_id in download.get('url', ''): return download return None def cleanup_old_downloads(self, days: int = 180): """Clean up old download records""" return self.unified_db.cleanup_old_downloads(days=days, platform=self.platform)