from flask import Flask, jsonify, request, send_from_directory import os import json import threading from hf_scrapper import download_file, get_system_proxies, get_download_progress from indexer import indexer from tvdb import fetch_and_cache_json import re app = Flask(__name__) # Constants and Configuration CACHE_DIR = os.getenv("CACHE_DIR") INDEX_FILE = os.getenv("INDEX_FILE") TOKEN = os.getenv("TOKEN") FILM_STORE_JSON_PATH = os.path.join(CACHE_DIR, "film_store.json") download_threads = {} # Ensure CACHE_DIR exists if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR) if not os.path.exists(FILM_STORE_JSON_PATH): with open(FILM_STORE_JSON_PATH, 'w') as json_file: json.dump({}, json_file) # Index the file structure indexer() # Load the file structure JSON if not os.path.exists(INDEX_FILE): raise FileNotFoundError(f"{INDEX_FILE} not found. Please make sure the file exists.") with open(INDEX_FILE, 'r') as f: file_structure = json.load(f) # Function Definitions def load_json(file_path): """Load JSON data from a file.""" with open(file_path, 'r') as file: return json.load(file) def find_movie_path(json_data, title): """Find the path of the movie in the JSON data based on the title.""" for directory in json_data: if directory['type'] == 'directory' and directory['path'] == 'films': for sub_directory in directory['contents']: if sub_directory['type'] == 'directory': for item in sub_directory['contents']: if item['type'] == 'file' and title.lower() in item['path'].lower(): return item['path'] return None def get_film_id(title): """Generate a film ID based on the title.""" return title.replace(" ", "_").lower() def prefetch_metadata(): """Prefetch metadata for all items in the file structure.""" for item in file_structure: if 'contents' in item: for sub_item in item['contents']: original_title = sub_item['path'].split('/')[-1] media_type = 'series' if item['path'].startswith('tv') else 'movie' title = original_title year = None # Extract year from the title if available match = re.search(r'\((\d{4})\)', original_title) if match: year_str = match.group(1) if year_str.isdigit() and len(year_str) == 4: title = original_title[:match.start()].strip() year = int(year_str) else: parts = original_title.rsplit(' ', 1) if len(parts) > 1 and parts[-1].isdigit() and len(parts[-1]) == 4: title = parts[0].strip() year = int(parts[-1]) fetch_and_cache_json(original_title, title, media_type, year) def start_prefetching(): """Start the metadata prefetching in a separate thread.""" prefetch_metadata() # Start prefetching metadata thread = threading.Thread(target=start_prefetching) thread.daemon = True thread.start() # API Endpoints @app.route('/api/movie', methods=['GET']) def get_movie(): """Endpoint to get the movie by title.""" title = request.args.get('title') if not title: return jsonify({"error": "Title parameter is required"}), 400 # Load the film store JSON with open(FILM_STORE_JSON_PATH, 'r') as json_file: film_store_data = json.load(json_file) # Check if the film is already cached if title in film_store_data: cache_path = film_store_data[title] if os.path.exists(cache_path): return send_from_directory(os.path.dirname(cache_path), os.path.basename(cache_path)) # If not cached, find the movie path in the index file json_data = load_json(INDEX_FILE) movie_path = find_movie_path(json_data, title) if not movie_path: return jsonify({"error": "Movie not found"}), 404 cache_path = os.path.join(CACHE_DIR, movie_path) file_url = f"https://huggingface.co/Unicone-Studio/jellyfin_media/resolve/main/{movie_path}" proxies = get_system_proxies() film_id = get_film_id(title) # Start the download in a separate thread if not already downloading if film_id not in download_threads or not download_threads[film_id].is_alive(): thread = threading.Thread(target=download_file, args=(file_url, TOKEN, cache_path, proxies, film_id, title)) download_threads[film_id] = thread thread.start() return jsonify({"status": "Download started", "film_id": film_id}) @app.route('/api/progress/', methods=['GET']) def get_progress(film_id): """Endpoint to get the download progress of a movie.""" progress = get_download_progress(film_id) return jsonify({"film_id": film_id, "progress": progress}) @app.route('/api/filmid', methods=['GET']) def get_film_id_by_title(): """Endpoint to get the film ID by providing the movie title.""" title = request.args.get('title') if not title: return jsonify({"error": "Title parameter is required"}), 400 film_id = get_film_id(title) return jsonify({"film_id": film_id}) @app.route('/api/film_store', methods=['GET']) def get_film_store(): """Endpoint to get the film store JSON.""" if os.path.exists(FILM_STORE_JSON_PATH): with open(FILM_STORE_JSON_PATH, 'r') as json_file: film_store_data = json.load(json_file) return jsonify(film_store_data) return jsonify({}), 404 # Main entry point if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=7860)