"""Archive API endpoints with SQLite backend.""" import os from flask import Blueprint, request, Response, send_file from utils import make_response, make_error_response from models import ArchiveItem archive_bp = Blueprint('archive', __name__, url_prefix='/api') @archive_bp.route('/archive', methods=['GET']) def get_archive(): """Get archived videos with pagination and filtering.""" from app import archive_db try: page = int(request.args.get('page', 1)) limit = int(request.args.get('limit', 24)) search = request.args.get('search') category = request.args.get('category') start_date = request.args.get('startDate') end_date = request.args.get('endDate') videos, total = archive_db.get_videos( page=page, limit=limit, search=search, category=category, start_date=start_date, end_date=end_date ) items = [] for v in videos: items.append({ "videoId": v.video_id, "title": v.title, "url": v.url, "description": v.description, "thumbnail": v.thumbnail, "channel": v.channel, "views": v.views, "duration": v.duration, "category": v.category, "downloadPath": v.download_path, "networkSharePath": v.network_share_path, "fileSize": v.file_size, "downloadDate": v.download_date.isoformat() if v.download_date else "", "type": v.item_type, }) return make_response({ "archive": items, "items": items, "total": total, "page": page, "hasMore": page * limit < total, }) except Exception as e: return make_error_response(f"Failed to get archive: {str(e)}", 500) @archive_bp.route('/archive/', methods=['GET']) def get_archive_item(video_id): """Get a single archive item.""" from app import archive_db try: video = archive_db.get_video(video_id) if not video: return make_error_response(f"Video {video_id} not found in archive", 404) return make_response({ "videoId": video.video_id, "title": video.title, "url": video.url, "description": video.description, "thumbnail": video.thumbnail, "channel": video.channel, "views": video.views, "duration": video.duration, "category": video.category, "downloadPath": video.download_path, "networkSharePath": video.network_share_path, "fileSize": video.file_size, "downloadDate": video.download_date.isoformat() if video.download_date else "", "type": video.item_type, }) except Exception as e: return make_error_response(f"Failed to get archive item: {str(e)}", 500) @archive_bp.route('/archive//stream', methods=['GET']) def stream_video(video_id): """Stream a downloaded video file.""" from app import archive_db try: video = archive_db.get_video(video_id) if not video or not video.download_path: return make_error_response(f"Video {video_id} not found or has no file", 404) if not os.path.exists(video.download_path): return make_error_response(f"Video file not found: {video.download_path}", 404) return send_file( video.download_path, mimetype='video/mp4', as_attachment=False, conditional=True, ) except Exception as e: return make_error_response(f"Failed to stream video: {str(e)}", 500) @archive_bp.route('/archive/', methods=['DELETE']) def remove_from_archive(video_id): """Remove a video from the archive.""" from app import archive_db try: removed = archive_db.delete_video(video_id) if not removed: return make_error_response(f"Video {video_id} not found in archive", 404) return make_response({"message": f"Video {video_id} removed from archive"}) except Exception as e: return make_error_response(f"Failed to remove from archive: {str(e)}", 500) @archive_bp.route('/archive', methods=['DELETE']) def clear_archive(): """Clear the entire archive.""" from app import archive_db try: count = archive_db.clear_archive() return make_response({ "message": "Archive cleared", "count": count }) except Exception as e: return make_error_response(f"Failed to clear archive: {str(e)}", 500) @archive_bp.route('/archive/stats', methods=['GET']) def get_archive_stats(): """Get archive statistics.""" from app import archive_db try: stats = archive_db.get_stats() return make_response(stats) except Exception as e: return make_error_response(f"Failed to get archive stats: {str(e)}", 500) @archive_bp.route('/archive/categories', methods=['GET']) def get_archive_categories(): """Get unique categories from the archive.""" from app import archive_db try: categories = archive_db.get_categories() # Flatten SQLAlchemy row tuples to plain strings flat = [c[0] if isinstance(c, (tuple, list)) else c for c in categories] return make_response(flat) except Exception as e: return make_error_response(f"Failed to get categories: {str(e)}", 500) @archive_bp.route('/archive/export', methods=['GET']) def export_archive(): """Export archive data as JSON or CSV.""" from app import archive_db try: fmt = request.args.get('format', 'json') if fmt not in ('json', 'csv'): return make_error_response("Format must be 'json' or 'csv'", 400) data = archive_db.export_archive(fmt) if fmt == 'json': mimetype = 'application/json' filename = 'archive.json' else: mimetype = 'text/csv' filename = 'archive.csv' return Response( data, mimetype=mimetype, headers={"Content-Disposition": f"attachment; filename={filename}"} ) except Exception as e: return make_error_response(f"Failed to export archive: {str(e)}", 500) @archive_bp.route('/archive/import', methods=['POST']) def import_archive(): """Import archive data from a JSON file.""" from app import archive_db try: if 'file' not in request.files: return make_error_response("No file provided", 400) file = request.files['file'] if not file.filename.endswith('.json'): return make_error_response("Only JSON files are supported", 400) import json data = json.loads(file.read()) items = data.get('items', data if isinstance(data, list) else []) imported = 0 for item in items: video_id = item.get('videoId', item.get('video_id', '')) if not video_id: continue archive_item = ArchiveItem( video_id=video_id, title=item.get('title', 'Unknown'), url=item.get('url', ''), description=item.get('description', ''), thumbnail=item.get('thumbnail', ''), channel=item.get('channel', ''), views=item.get('views', 0) or 0, duration=item.get('duration', ''), category=item.get('category', ''), download_path=item.get('downloadPath', item.get('download_path', '')), network_share_path=item.get('networkSharePath', item.get('network_share_path')), file_size=item.get('fileSize', item.get('file_size', 0)) or 0, download_date=item.get('downloadDate', item.get('download_date', '')), item_type=item.get('type', 'video'), ) archive_db.add_video(archive_item) imported += 1 return make_response({ "success": True, "imported": imported }) except Exception as e: return make_error_response(f"Failed to import archive: {str(e)}", 500)