changes to db and added requirements.txt for setup
This commit is contained in:
83
main.py
83
main.py
@@ -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)
|
||||||
|
|||||||
6
requirements.txt
Normal file
6
requirements.txt
Normal 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
|
||||||
Reference in New Issue
Block a user