Spaces:
Runtime error
Runtime error
| 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'<iframe width="100%" height="400" src="https://www.youtube.com/embed/{trailer["key"]}" frameborder="0" allowfullscreen></iframe>' | |
| return '<p>No trailer available</p>' | |
| except Exception as e: | |
| print(f"Error fetching trailer: {e}") | |
| return '<p>Error loading trailer</p>' | |
| # 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() |