changes to db and added requirements.txt for setup

This commit is contained in:
Brandon4466
2025-05-31 18:15:25 -07:00
parent cc290d5720
commit b8f1ce3b13
4 changed files with 14872 additions and 18 deletions

83
main.py
View File

@@ -5,12 +5,21 @@ import requests
import time import time
import jwt import jwt
import json import json
import logging # New import for logging
from fastapi import FastAPI, HTTPException, Request, Depends, Header, WebSocket, WebSocketDisconnect, Query from fastapi import FastAPI, HTTPException, Request, Depends, Header, WebSocket, WebSocketDisconnect, Query
from fastapi.responses import StreamingResponse, FileResponse from fastapi.responses import StreamingResponse, FileResponse
from passlib.context import CryptContext from passlib.context import CryptContext
import media_scanner # Import the Rust module import media_scanner # Import the Rust module
from rapidfuzz import fuzz from rapidfuzz import fuzz
# Configure logging
logging.basicConfig(
filename="scan.log", # Log file name
filemode="a", # Append mode
format="%(asctime)s - %(levelname)s - %(message)s",
level=logging.INFO
)
# Configuration # Configuration
MOVIES_DIR = r"Z:\plexmediaserver\movies" # Directory containing movie files MOVIES_DIR = r"Z:\plexmediaserver\movies" # Directory containing movie files
TV_SHOWS_DIR = r"Z:\plexmediaserver\tv" # Directory containing TV shows and episodes TV_SHOWS_DIR = r"Z:\plexmediaserver\tv" # Directory containing TV shows and episodes
@@ -179,6 +188,9 @@ def fetch_movie_details(title, year=None):
response = requests.get('http://www.omdbapi.com/', params=params) response = requests.get('http://www.omdbapi.com/', params=params)
data = response.json() data = response.json()
if data.get('Response') == 'True': if data.get('Response') == 'True':
logging.info(data)
if data['Poster'] == 'N/A':
data['Poster'] = 'https://placehold.co/500x750/jpg?text=No+Poster'
return data return data
else: else:
raise ValueError(f"Movie '{title}' not found.") raise ValueError(f"Movie '{title}' not found.")
@@ -217,11 +229,15 @@ def add_tv_show_to_db(details):
def scan_and_populate(): def scan_and_populate():
init_db() init_db()
processed_shows = set() # Keep track of processed TV shows processed_shows = set() # Keep track of processed TV shows
log_messages = [] # Collect log messages
try: try:
# Use Rust for scanning movies msg = "Scanning movies..."
print("Scanning movies...") print(msg)
logging.info(msg)
movie_files = media_scanner.scan_movies(MOVIES_DIR) movie_files = media_scanner.scan_movies(MOVIES_DIR)
print(f"Found movie files: {movie_files}") msg = f"Found movie files: {movie_files}"
print(msg)
logging.info(msg)
for full_path in movie_files: for full_path in movie_files:
parent = os.path.basename(os.path.dirname(full_path)) parent = os.path.basename(os.path.dirname(full_path))
match = re.match(r"(.+?)\s*\((\d{4})\)$", parent) match = re.match(r"(.+?)\s*\((\d{4})\)$", parent)
@@ -233,20 +249,29 @@ def scan_and_populate():
year = None year = None
rel_path = os.path.relpath(full_path, MOVIES_DIR) rel_path = os.path.relpath(full_path, MOVIES_DIR)
if movie_exists(rel_path): if movie_exists(rel_path):
print(f"Movie already exists: {title} ({year or 'n/a'})") msg = f"Movie already exists: {title} ({year or 'n/a'})"
print(msg)
logging.info(msg)
continue continue
try: try:
details = fetch_movie_details(title, year) details = fetch_movie_details(title, year)
details['filepath'] = rel_path details['filepath'] = rel_path
add_movie_to_db(details) add_movie_to_db(details)
print(f"Added {title} ({year or 'n/a'}) to database.") msg = f"Added {title} ({year or 'n/a'}) to database."
print(msg)
logging.info(msg)
except Exception as e: except Exception as e:
print(f"Skipping {title}: {e}") msg = f"Skipping {title}: {e}"
print(msg)
logging.error(msg)
# Updated logic for scanning TV shows with fuzzy matching msg = "Scanning TV shows..."
print("Scanning TV shows...") print(msg)
logging.info(msg)
tv_show_files = media_scanner.scan_tv_shows(TV_SHOWS_DIR) tv_show_files = media_scanner.scan_tv_shows(TV_SHOWS_DIR)
print(f"Found TV show files: {tv_show_files}") msg = f"Found TV show files: {tv_show_files}"
print(msg)
logging.info(msg)
for full_path in tv_show_files: for full_path in tv_show_files:
# Extract TV show name from the folder structure: "Show Name\Season X\filename" # Extract TV show name from the folder structure: "Show Name\Season X\filename"
show_name = os.path.basename(os.path.dirname(os.path.dirname(full_path))) show_name = os.path.basename(os.path.dirname(os.path.dirname(full_path)))
@@ -254,14 +279,18 @@ def scan_and_populate():
season_dir = os.path.basename(os.path.dirname(full_path)) season_dir = os.path.basename(os.path.dirname(full_path))
season_match = re.search(r"Season\s*(\d+)", season_dir, re.IGNORECASE) season_match = re.search(r"Season\s*(\d+)", season_dir, re.IGNORECASE)
if not season_match: if not season_match:
print(f"Skipping {full_path}: Season number not found in directory '{season_dir}'") msg = f"Skipping {full_path}: Season number not found in directory '{season_dir}'"
print(msg)
logging.warning(msg)
continue continue
season = int(season_match.group(1)) season = int(season_match.group(1))
# Extract episode number solely from the SxxEyy pattern in the filename # Extract episode number solely from the SxxEyy pattern in the filename
basename = os.path.basename(full_path) basename = os.path.basename(full_path)
ep_match = re.search(r"(?i)S(\d{2})E(\d{2})", basename) ep_match = re.search(r"(?i)S(\d{2})E(\d{2})", basename)
if not ep_match: if not ep_match:
print(f"Skipping {full_path}: SxxEyy pattern not found in filename") msg = f"Skipping {full_path}: SxxEyy pattern not found in filename"
print(msg)
logging.warning(msg)
continue continue
episode = int(ep_match.group(2)) episode = int(ep_match.group(2))
# Check and add TV show details if not processed yet # Check and add TV show details if not processed yet
@@ -270,11 +299,17 @@ def scan_and_populate():
try: try:
tv_details = fetch_tv_show_details(show_name) tv_details = fetch_tv_show_details(show_name)
add_tv_show_to_db(tv_details) add_tv_show_to_db(tv_details)
print(f"Added TV show details: {show_name}") msg = f"Added TV show details: {show_name}"
print(msg)
logging.info(msg)
except Exception as e: except Exception as e:
print(f"Skipping TV show details for {show_name}: {e}") msg = f"Skipping TV show details for {show_name}: {e}"
print(msg)
logging.error(msg)
else: else:
print(f"TV show already exists: {show_name}") msg = f"TV show already exists: {show_name}"
print(msg)
logging.info(msg)
processed_shows.add(show_name) processed_shows.add(show_name)
rel_path = os.path.relpath(full_path, TV_SHOWS_DIR) rel_path = os.path.relpath(full_path, TV_SHOWS_DIR)
conn = sqlite3.connect(DB_PATH) conn = sqlite3.connect(DB_PATH)
@@ -296,9 +331,13 @@ def scan_and_populate():
break break
if tv_show_row: if tv_show_row:
tv_show_id = tv_show_row[0] tv_show_id = tv_show_row[0]
print(f"Fuzzy matched '{show_name}' to '{tv_show_row[1]}' with score {similarity}") msg = f"Fuzzy matched '{show_name}' to '{tv_show_row[1]}' with score {similarity}"
print(msg)
logging.info(msg)
else: else:
print(f"TV show id not found for {show_name}") msg = f"TV show id not found for {show_name}"
print(msg)
logging.warning(msg)
conn.close() conn.close()
continue continue
# Use the complete filename (without extension) as the episode title # Use the complete filename (without extension) as the episode title
@@ -309,9 +348,17 @@ def scan_and_populate():
''', (rel_path, tv_show_id, season, episode, title)) ''', (rel_path, tv_show_id, season, episode, title))
conn.commit() conn.commit()
conn.close() conn.close()
print(f"Added episode: {show_name} Season {season} Episode {episode}") msg = f"Added episode: {show_name} Season {season} Episode {episode}"
print(msg)
logging.info(msg)
except Exception as e: except Exception as e:
print(f"Error during scanning: {e}") msg = f"Error during scanning: {e}"
print(msg)
logging.error(msg)
finally:
msg = "Scan and populate completed."
print(msg)
logging.info(msg)
def range_streamer(file_path: str, range_header: str = None, chunk_size: int = 1024*1024): def range_streamer(file_path: str, range_header: str = None, chunk_size: int = 1024*1024):
file_size = os.path.getsize(file_path) file_size = os.path.getsize(file_path)

BIN
movies.db

Binary file not shown.

6
requirements.txt Normal file
View File

@@ -0,0 +1,6 @@
fastapi==0.89.1
passlib==1.7.4
PyJWT==2.7.0
rapidfuzz==3.9.0
Requests==2.31.0
uvicorn==0.20.0

14801
scan.log Normal file

File diff suppressed because one or more lines are too long