| import tempfile |
| import os |
| import pickle |
| import streamlit as st |
| import requests |
| from datetime import datetime |
|
|
| |
| with tempfile.TemporaryDirectory() as temp_dir: |
| |
| os.environ['STREAMLIT_CONFIG_DIR'] = temp_dir |
|
|
| |
| st.write(f"Using temporary directory for Streamlit config: {temp_dir}") |
|
|
| |
| st.title("Streamlit App with Temporary Directory") |
| st.text("This application uses a temporary directory to avoid permission issues.") |
|
|
|
|
| |
| st.set_page_config(page_title="🎬 Movie Recommender", page_icon="🎞️", layout="wide") |
|
|
| st.markdown(""" |
| <style> |
| .movie-title { |
| text-align: center; |
| font-weight: bold; |
| font-size: 22px; |
| } |
| .footer { |
| text-align: center; |
| font-size: 12px; |
| color: grey; |
| margin-top: 50px; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| |
| try: |
| movies = pickle.load(open('saved model/movie_list.pkl', 'rb')) |
| similarity = pickle.load(open('saved model/similarity.pkl', 'rb')) |
| except FileNotFoundError: |
| st.error("❌ Required data files (movie_list.pkl and similarity.pkl) not found.") |
| st.stop() |
|
|
| |
| def fetch_poster(movie_id): |
| try: |
| url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US" |
| response = requests.get(url) |
| data = response.json() |
| poster_path = data.get('poster_path') |
| return f"https://image.tmdb.org/t/p/w500/{poster_path}" if poster_path else "https://via.placeholder.com/500x750?text=No+Image" |
| except: |
| return "https://via.placeholder.com/500x750?text=Error" |
|
|
| def fetch_movie_details(movie_id): |
| try: |
| url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US" |
| response = requests.get(url) |
| data = response.json() |
| overview = data.get('overview', 'No overview available.') |
| rating = data.get('vote_average', 'No rating') |
| release_date = data.get('release_date', 'No release date') |
| genres = ', '.join([genre['name'] for genre in data.get('genres', [])]) |
| return overview, rating, release_date, genres |
| except: |
| return "No details available.", "No rating", "No release date", "No genres" |
|
|
| def recommend(movie): |
| if movie not in movies['title'].values: |
| return [], [], [] |
| index = movies[movies['title'] == movie].index[0] |
| distances = sorted(list(enumerate(similarity[index])), reverse=True, key=lambda x: x[1]) |
| recommended_names = [] |
| recommended_posters = [] |
| recommended_ids = [] |
| for i in distances[1:6]: |
| movie_id = movies.iloc[i[0]].movie_id |
| recommended_names.append(movies.iloc[i[0]].title) |
| recommended_posters.append(fetch_poster(movie_id)) |
| recommended_ids.append(movie_id) |
| return recommended_names, recommended_posters, recommended_ids |
|
|
| |
| def page_1(): |
| st.markdown("<h1 style='text-align: center;'>🎬 Movie Recommender</h1>", unsafe_allow_html=True) |
| st.markdown("<hr>", unsafe_allow_html=True) |
|
|
| hour = datetime.now().hour |
| greeting_time = "Good Morning ☀️" if hour < 12 else "Good Evening 🌙" if hour >= 18 else "Good Afternoon 🌤️" |
| st.markdown(f"### {greeting_time}") |
|
|
| user_name = st.text_input("👤 Enter your name:") |
| if st.button("Continue to Movie Selection"): |
| if user_name: |
| st.session_state.name = user_name |
| st.session_state.page = "select_movie" |
| else: |
| st.warning("Please enter your name first 😊") |
|
|
| |
| def page_2(): |
| st.markdown(f"### Hello, {st.session_state.name} 👋", unsafe_allow_html=True) |
|
|
| movie_list = movies['title'].values |
| selected_movie = st.selectbox("🎥 Select a Movie", movie_list) |
|
|
| rating = st.slider("⭐ Your Rating", 1, 10, 1) |
| st.write(f"✅ Your rating: {rating} stars") |
|
|
| |
| if "show_recommendations" not in st.session_state: |
| st.session_state.show_recommendations = False |
| if "show_details" not in st.session_state: |
| st.session_state.show_details = {} |
|
|
| |
| if st.button("🎯 Recommendations"): |
| st.session_state.show_recommendations = not st.session_state.show_recommendations |
|
|
| |
| if st.session_state.show_recommendations: |
| with st.spinner("⏳ Fetching recommendations..."): |
| names, posters, ids = recommend(selected_movie) |
| if names: |
| st.markdown(f"### ✅ Recommended Movies Similar to {selected_movie}:") |
| cols = st.columns(5) |
| for i in range(5): |
| with cols[i]: |
| details_key = f"details_{i}" |
| if details_key not in st.session_state.show_details: |
| st.session_state.show_details[details_key] = False |
|
|
| if st.button(f"Show {names[i]} Details", key=details_key): |
| st.session_state.show_details[details_key] = not st.session_state.show_details[details_key] |
|
|
| if st.session_state.show_details.get(details_key, False): |
| movie_id = ids[i] |
| overview, vote_avg, release_date, genres = fetch_movie_details(movie_id) |
| st.markdown(f"### 📖 Movie Details, {names[i]}:") |
| st.markdown(f"**Overview**: {overview}") |
| st.markdown(f"**Rating**: {vote_avg}/10") |
| st.markdown(f"**Release Date**: {release_date}") |
| st.markdown(f"**Genres**: {genres}") |
|
|
| st.image(posters[i], use_container_width=True) |
| st.markdown(f"<div class='movie-title'>{names[i]}</div>", unsafe_allow_html=True) |
|
|
| else: |
| st.warning("⚠️ No recommendations found.") |
|
|
| |
| if "show_selected_details" not in st.session_state: |
| st.session_state.show_selected_details = False |
|
|
| |
| if st.button(f"📖 Show Details of {selected_movie}"): |
| st.session_state.show_selected_details = not st.session_state.show_selected_details |
|
|
| |
| if st.session_state.show_selected_details: |
| movie_id = movies[movies['title'] == selected_movie].movie_id.iloc[0] |
| overview, vote_avg, release_date, genres = fetch_movie_details(movie_id) |
| st.markdown(f"### 📖 Movie Details, {selected_movie}:") |
| st.markdown(f"**Overview**: {overview}") |
| st.markdown(f"**Rating**: {vote_avg}/10") |
| st.markdown(f"**Release Date**: {release_date}") |
| st.markdown(f"**Genres**: {genres}") |
|
|
|
|
|
|
| if st.button("🔙 Back"): |
| st.session_state.page = "welcome" |
|
|
| |
| if 'page' not in st.session_state: |
| st.session_state.page = "welcome" |
|
|
| if st.session_state.page == "welcome": |
| page_1() |
| elif st.session_state.page == "select_movie": |
| page_2() |
|
|
| |
| st.markdown("<hr>", unsafe_allow_html=True) |
| st.markdown("<div class='footer'>© 2025 • by Youssef • Powered by TMDB API</div>", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
|
|