from flask import Flask, jsonify, request, send_from_directory from flask_cors import CORS import os import json import threading import urllib.parse from Instance import Instance app = Flask(__name__) CORS(app) # Constants and Configuration CACHE_DIR = os.getenv("CACHE_DIR") INDEX_FILE = os.getenv("INDEX_FILE") TOKEN = os.getenv("TOKEN") REPO = os.getenv("REPO") ID = os.getenv("ID") URL = os.getenv("URL") instance = Instance(id=ID, url=URL, cache_dir=CACHE_DIR, index_file=INDEX_FILE, token=TOKEN, repo=REPO) # API Endpoints @app.route('/api/film', methods=['GET']) def get_movie_api(): """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(instance.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)) movie_path = instance.find_movie_path(instance.file_structure, 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/{REPO}/resolve/main/{movie_path}" proxies = instance.get_system_proxies() film_id = instance.get_film_id(title) # Start the download in a separate thread if not already downloading if film_id not in instance.download_threads or not instance.download_threads[film_id].is_alive(): thread = threading.Thread(target=instance.download_film, args=(file_url, TOKEN, cache_path, proxies, film_id, title)) instance.download_threads[film_id] = thread thread.start() return jsonify({"status": "Download started", "film_id": film_id}) @app.route('/api/tv', methods=['GET']) def get_tv_show_api(): """Endpoint to get the TV show by title, season, and episode.""" title = request.args.get('title') season = request.args.get('season') episode = request.args.get('episode') if not title or not season or not episode: return jsonify({"error": "Title, season, and episode parameters are required"}), 400 # Load the TV store JSON with open(instance.TV_STORE_JSON_PATH, 'r') as json_file: tv_store_data = json.load(json_file) # Check if the episode is already cached if title in tv_store_data and season in tv_store_data[title]: for ep in tv_store_data[title][season]: if episode in ep: cache_path = tv_store_data[title][season][ep] if os.path.exists(cache_path): return send_from_directory(os.path.dirname(cache_path), os.path.basename(cache_path)) tv_path = instance.find_tv_path(instance.file_structure, title) if not tv_path: return jsonify({"error": "TV show not found"}), 404 episode_path = None for directory in instance.file_structure: if directory['type'] == 'directory' and directory['path'] == 'tv': for sub_directory in directory['contents']: if sub_directory['type'] == 'directory' and title.lower() in sub_directory['path'].lower(): for season_dir in sub_directory['contents']: if season_dir['type'] == 'directory' and season in season_dir['path']: for episode_file in season_dir['contents']: if episode_file['type'] == 'file' and episode in episode_file['path']: episode_path = episode_file['path'] break if not episode_path: return jsonify({"error": "Episode not found"}), 404 cache_path = os.path.join(CACHE_DIR, episode_path) file_url = f"https://huggingface.co/{REPO}/resolve/main/{episode_path}" proxies = instance.get_system_proxies() episode_id = instance.encode_episodeid(title,season,episode) # Start the download in a separate thread if not already downloading if episode_id not in instance.download_threads or not instance.download_threads[episode_id].is_alive(): thread = threading.Thread(target=instance.download_episode, args=(file_url, TOKEN, cache_path, proxies, episode_id, title)) instance.download_threads[episode_id] = thread thread.start() return jsonify({"status": "Download started", "episode_id": episode_id}) @app.route('/api/progress/', methods=['GET']) def get_progress_api(id): """Endpoint to get the download progress of a movie or TV show episode.""" progress = instance.get_download_progress(id) return jsonify({"id": id, "progress": progress}) @app.route('/api/filmid', methods=['GET']) def get_film_id_by_title_api(): """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 = instance.get_film_id(title) return jsonify({"film_id": film_id}) @app.route('/api/episodeid', methods=['GET']) def get_episode_id_api(): """Endpoint to get the episode ID by providing the TV show title, season, and episode.""" title = request.args.get('title') season = request.args.get('season') episode = request.args.get('episode') if not title or not season or not episode: return jsonify({"error": "Title, season, and episode parameters are required"}), 400 episode_id = instance.encode_episodeid(title,season,episode) return jsonify({"episode_id": episode_id}) @app.route('/api/cache/size', methods=['GET']) def get_cache_size_api(): total_size = 0 for dirpath, dirnames, filenames in os.walk(CACHE_DIR): for f in filenames: fp = os.path.join(dirpath, f) total_size += os.path.getsize(fp) readable_size = instance.bytes_to_human_readable(total_size) return jsonify({"cache_size": readable_size}) @app.route('/api/cache/clear', methods=['POST']) def clear_cache_api(): for dirpath, dirnames, filenames in os.walk(CACHE_DIR): for f in filenames: fp = os.path.join(dirpath, f) os.remove(fp) return jsonify({"status": "Cache cleared"}) @app.route('/api/tv/store', methods=['GET']) def get_tv_store_api(): """Endpoint to get the TV store JSON.""" if os.path.exists(instance.TV_STORE_JSON_PATH): with open(instance.TV_STORE_JSON_PATH, 'r') as json_file: tv_store_data = json.load(json_file) return jsonify(tv_store_data) return jsonify({}), 404 @app.route('/api/film/store', methods=['GET']) def get_film_store_api(): """Endpoint to get the film store JSON.""" if os.path.exists(instance.FILM_STORE_JSON_PATH): with open(instance.FILM_STORE_JSON_PATH, 'r') as json_file: tv_store_data = json.load(json_file) return jsonify(tv_store_data) return jsonify({}), 404 @app.route('/api/film/metadata', methods=['GET']) def get_film_metadata_api(): """Endpoint to get the film metadata by title.""" title = request.args.get('title') if not title: return jsonify({'error': 'No title provided'}), 400 json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json") if os.path.exists(json_cache_path): with open(json_cache_path, 'r') as f: data = json.load(f) return jsonify(data) return jsonify({'error': 'Metadata not found'}), 404 @app.route('/api/tv/metadata', methods=['GET']) def get_tv_metadata_api(): """Endpoint to get the TV show metadata by title.""" title = request.args.get('title') if not title: return jsonify({'error': 'No title provided'}), 400 json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json") if os.path.exists(json_cache_path): with open(json_cache_path, 'r') as f: data = json.load(f) # Add the file structure to the metadata tv_structure_data = instance.get_tv_structure(instance.file_structure, title) if tv_structure_data: data['file_structure'] = tv_structure_data return jsonify(data) return jsonify({'error': 'Metadata not found'}), 404 @app.route("/api/film/all") def get_all_films_api(): return instance.get_all_films(instance.file_structure) @app.route("/api/tv/all") def get_all_tvshows_api(): return instance.get_all_tv_shows(instance.file_structure) # Routes @app.route('/') def index(): return "Server Running ..." # Main entry point if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=7860)