import os import gradio as gr import pandas as pd import requests from typing import List, Dict, Any # TMDB API Configuration - Using environment variables for security TMDB_API_KEY = os.getenv("TMDB_API_KEY", "2818694258d166d0644b0f75a1b93e59") TMDB_API_TOKEN = os.getenv("TMDB_API_TOKEN", "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyODE4Njk0MjU4ZDE2NmQwNjQ0YjBmNzVhMWI5M2U1OSIsIm5iZiI6MTczMDYxNjE4Mi4xODY5MDI4LCJzdWIiOiI2NzI3MWExYjM5OGM5MDQzZjgwZDEwOGEiLCJzY29wZXMiOlsiYXBpX3JlYWQiXSwidmVyc2lvbiI6MX0.G-pLEQKK3o5ISpb0CEztamPFGlsmpnPqPagawMve9dY") TMDB_BASE_URL = "https://api.themoviedb.org/3" TMDB_IMAGE_BASE_URL = "https://image.tmdb.org/t/p/w500" def fetch_genres() -> List[Dict[str, Any]]: """Fetch movie genres from TMDB""" headers = { "Authorization": f"Bearer {TMDB_API_TOKEN}", "accept": "application/json" } try: response = requests.get(f"{TMDB_BASE_URL}/genre/movie/list", headers=headers) response.raise_for_status() return response.json()["genres"] except Exception as e: print(f"Error fetching genres: {e}") return [] def fetch_movies_by_genre(genre_id: str = None) -> pd.DataFrame: """Fetch movies from TMDB, optionally filtered by genre""" headers = { "Authorization": f"Bearer {TMDB_API_TOKEN}", "accept": "application/json" } params = { "include_adult": False, "include_video": True, "language": "en-US", "page": 1, "sort_by": "popularity.desc" } if genre_id and genre_id != "All": params["with_genres"] = genre_id try: response = requests.get(f"{TMDB_BASE_URL}/discover/movie", headers=headers, params=params) response.raise_for_status() movies = response.json()["results"] movie_data = { "title": [], "poster_url": [], "overview": [], "rating": [], "id": [] } for movie in movies: movie_data["title"].append(movie["title"]) movie_data["poster_url"].append( f"{TMDB_IMAGE_BASE_URL}{movie['poster_path']}" if movie.get('poster_path') else None ) movie_data["overview"].append(movie.get("overview", "No overview available")) movie_data["rating"].append(movie.get("vote_average", 0)) movie_data["id"].append(movie["id"]) return pd.DataFrame(movie_data) except Exception as e: print(f"Error fetching movies: {e}") return pd.DataFrame(columns=["title", "poster_url", "overview", "rating", "id"]) def get_movie_trailer(movie_id: int) -> str: """Fetch movie trailer URL from TMDB""" headers = { "Authorization": f"Bearer {TMDB_API_TOKEN}", "accept": "application/json" } try: response = requests.get( f"{TMDB_BASE_URL}/movie/{movie_id}/videos", headers=headers ) response.raise_for_status() videos = response.json().get("results", []) trailer = next( (v for v in videos if v["type"] == "Trailer" and v["site"] == "YouTube"), None ) if trailer: return f'' return '
No trailer available
' except Exception as e: print(f"Error fetching trailer: {e}") return 'Error loading trailer
' # Initialize global variables genres = fetch_genres() genre_map = {str(g["id"]): g["name"] for g in genres} genre_map["All"] = "All" content_df = fetch_movies_by_genre() def list_movies(selected_genre: str) -> List[str]: """Update movie list based on selected genre""" global content_df content_df = fetch_movies_by_genre(selected_genre if selected_genre != "All" else None) return content_df["poster_url"].tolist() def get_movie_info(evt: gr.SelectData) -> tuple: """Get selected movie information""" selected_idx = evt.index if selected_idx >= len(content_df): return None, None, None selected_movie = content_df.iloc[selected_idx] trailer_html = get_movie_trailer(selected_movie["id"]) return ( gr.HTML(value=trailer_html), selected_movie["title"], f"{selected_movie['title']}\n\nRating: {selected_movie['rating']}/10\n\n{selected_movie['overview']}" ) def rate_movie(movie_title: str, rating: float) -> str: """Handle movie rating submission""" if not movie_title: return "Please select a movie first!" content_df.loc[content_df["title"] == movie_title, "rating"] = rating return f"Thank you for rating {movie_title}! New rating: {rating}/5" # Gradio UI with gr.Blocks(theme=gr.themes.Soft()) as movie_app: gr.Markdown(""" # 🎬 Movie Explorer Browse popular movies, watch trailers, and explore different genres! """) with gr.Row(): genre_dropdown = gr.Dropdown( choices=list(genre_map.items()), value="All", label="Filter by Genre" ) with gr.Row(): gallery = gr.Gallery( value=content_df["poster_url"].tolist(), label="Movie Gallery", show_label=True, columns=[4], height="auto", allow_preview=False ) with gr.Row(): trailer_html = gr.HTML(label="Trailer") with gr.Row(): with gr.Column(): selected_movie_title = gr.Textbox(label="Selected Movie", interactive=False) movie_info = gr.TextArea(label="Movie Information", interactive=False) with gr.Column(): rating_input = gr.Slider(minimum=1, maximum=5, step=0.5, label="Rate This Movie") rate_button = gr.Button("Submit Rating") rating_output = gr.Textbox(label="Rating Status") # Event handlers genre_dropdown.change( fn=list_movies, inputs=genre_dropdown, outputs=gallery ) gallery.select( fn=get_movie_info, outputs=[trailer_html, selected_movie_title, movie_info] ) rate_button.click( fn=rate_movie, inputs=[selected_movie_title, rating_input], outputs=rating_output ) if __name__ == "__main__": movie_app.launch()