from flask import Flask, jsonify, render_template, redirect, request, send_file import os import json import requests import urllib.parse from datetime import datetime, timedelta from threading import Thread from hf_scraper import get_system_proxies from indexer import indexer from dotenv import load_dotenv load_dotenv() INDEX_FILE = os.getenv("INDEX_FILE") TOKEN = os.getenv("TOKEN") REPO = os.getenv("REPO") THETVDB_API_KEY = os.getenv("THETVDB_API_KEY") THETVDB_API_URL = os.getenv("THETVDB_API_URL") CACHE_DIR = os.getenv("CACHE_DIR") TOKEN_EXPIRY = None THETVDB_TOKEN = None proxies = get_system_proxies() if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR) indexer() # Check if INDEX_FILE exists 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) def authenticate_thetvdb(): global THETVDB_TOKEN, TOKEN_EXPIRY auth_url = f"{THETVDB_API_URL}/login" auth_data = { "apikey": THETVDB_API_KEY } try: response = requests.post(auth_url, json=auth_data, proxies=proxies) response.raise_for_status() response_data = response.json() print("Auth Response Data:", response_data) # Debugging print statement THETVDB_TOKEN = response_data['data']['token'] TOKEN_EXPIRY = datetime.now() + timedelta(days=30) # token is valid for 1 month except requests.RequestException as e: print(f"Authentication failed: {e}") THETVDB_TOKEN = None TOKEN_EXPIRY = None def get_thetvdb_token(): global THETVDB_TOKEN, TOKEN_EXPIRY if not THETVDB_TOKEN or datetime.now() >= TOKEN_EXPIRY: authenticate_thetvdb() return THETVDB_TOKEN def fetch_and_cache_image(title, media_type, year=None): if year: search_url = f"{THETVDB_API_URL}/search?query={title}&type={media_type}&year={year}" else: search_url = f"{THETVDB_API_URL}/search?query={title}&type={media_type}" token = get_thetvdb_token() if not token: print("Authentication failed") return headers = { "Authorization": f"Bearer {token}", "accept": "application/json", } try: response = requests.get(search_url, headers=headers, proxies=proxies) response.raise_for_status() data = response.json() if 'data' in data and data['data']: img_url = data['data'][0].get('thumbnail') if img_url: img_content = requests.get(img_url, proxies=proxies).content cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.jpg") with open(cache_path, 'wb') as f: f.write(img_content) # Save JSON response to cache json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json") with open(json_cache_path, 'w') as f: json.dump(data, f) except requests.RequestException as e: print(f"Error fetching data: {e}") def prefetch_images(): for item in file_structure: if 'contents' in item: for sub_item in item['contents']: title = sub_item['path'].split('/')[-1] media_type = 'series' if item['path'].startswith('tv') else 'movie' year = None if any(char.isdigit() for char in title): # Strip year from title if present parts = title.split() year_str = parts[-1] if year_str.isdigit() and len(year_str) == 4: title = ' '.join(parts[:-1]) year = int(year_str) fetch_and_cache_image(title, media_type, year) # Run prefetch_images in a background thread def start_prefetching(): prefetch_images() # Start prefetching before running the Flask app thread = Thread(target=start_prefetching) thread.daemon = True thread.start() app = Flask(__name__) @app.route('/') def home(): return render_template('index.html') @app.route('/films') def list_films(): films = [item for item in file_structure if item['path'].startswith('films')] return jsonify([sub_item for film in films for sub_item in film['contents']]) @app.route('/tv') def list_tv(): tv_shows = [item for item in file_structure if item['path'].startswith('tv')] return jsonify([sub_item for show in tv_shows for sub_item in show['contents']]) @app.route('/play/') def play(file_path): file_url = f"https://huggingface.co/{REPO}/resolve/main/{file_path}" return redirect(file_url) @app.route('/get_image') def get_image(): title = request.args.get('title') if not title: return jsonify({'error': 'No title provided'}), 400 cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.jpg") if os.path.exists(cache_path): return send_file(cache_path, mimetype='image/jpeg') # If image is not found in cache, return a placeholder return send_file('path/to/placeholder.jpg', mimetype='image/jpeg') # Ensure you have a placeholder image if __name__ == '__main__': app.run(debug=True, host="0.0.0.0", port=7860)