diff --git a/VERSION b/VERSION index 0cadbc1..da6b0a8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5.5 +2.5.6 diff --git a/api/web_routes.py b/api/web_routes.py index 6f906c7..0dbbba4 100644 --- a/api/web_routes.py +++ b/api/web_routes.py @@ -82,26 +82,22 @@ async def get_movies_list(dependencies: dict, if has_date is not None: if has_date: - if db.db_type == "postgresql": - where_conditions.append("dateadded IS NOT NULL") - else: - where_conditions.append("dateadded IS NOT NULL AND dateadded != ''") + # PostgreSQL - NULL handling + where_conditions.append("dateadded IS NOT NULL") else: - if db.db_type == "postgresql": - where_conditions.append("dateadded IS NULL") - else: - where_conditions.append("(dateadded IS NULL OR dateadded = '')") + # PostgreSQL - NULL handling + where_conditions.append("dateadded IS NULL") if source_filter: - where_conditions.append("source = ?") + where_conditions.append("source = %s") params.append(source_filter) if search: - where_conditions.append("(imdb_id LIKE ? OR path LIKE ?)") + where_conditions.append("(imdb_id LIKE %s OR path LIKE %s)") params.extend([f"%{search}%", f"%{search}%"]) if imdb_search: - where_conditions.append("imdb_id LIKE ?") + where_conditions.append("imdb_id LIKE %s") params.append(f"%{imdb_search}%") where_clause = " AND ".join(where_conditions) if where_conditions else "1=1" @@ -111,23 +107,14 @@ async def get_movies_list(dependencies: dict, cursor.execute(count_query, params) total_count = db._get_first_value(cursor.fetchone()) - # Get paginated results - if db.db_type == "postgresql": - query = f""" - SELECT imdb_id, path, released, dateadded, source, has_video_file, last_updated - FROM movies - WHERE {where_clause} - ORDER BY last_updated DESC - LIMIT %s OFFSET %s - """ - else: - query = f""" - SELECT imdb_id, path, released, dateadded, source, has_video_file, last_updated - FROM movies - WHERE {where_clause} - ORDER BY last_updated DESC - LIMIT ? OFFSET ? - """ + # Get paginated results - PostgreSQL + query = f""" + SELECT imdb_id, path, released, dateadded, source, has_video_file, last_updated + FROM movies + WHERE {where_clause} + ORDER BY last_updated DESC + LIMIT %s OFFSET %s + """ cursor.execute(query, params + [limit, skip]) movies = [] @@ -171,16 +158,16 @@ async def get_tv_series_list(dependencies: dict, having_conditions = [] if search: - where_conditions.append("(s.imdb_id LIKE ? OR s.path LIKE ?)") + where_conditions.append("(s.imdb_id LIKE %s OR s.path LIKE %s)") params.extend([f"%{search}%", f"%{search}%"]) if imdb_search: - where_conditions.append("s.imdb_id LIKE ?") + where_conditions.append("s.imdb_id LIKE %s") params.append(f"%{imdb_search}%") if source_filter: # Need to check episodes for source filter - where_conditions.append("e.source = ?") + where_conditions.append("e.source = %s") params.append(source_filter) if date_filter: @@ -219,38 +206,22 @@ async def get_tv_series_list(dependencies: dict, # Get series with episode statistics having_part = f" HAVING {having_clause}" if having_clause else "" - if db.db_type == "postgresql": - query = f""" - SELECT - s.imdb_id, - s.path, - s.last_updated, - COUNT(e.episode) as total_episodes, - COUNT(CASE WHEN e.dateadded IS NOT NULL THEN 1 END) as episodes_with_dates, - COUNT(CASE WHEN e.has_video_file = TRUE THEN 1 END) as episodes_with_video - FROM series s - LEFT JOIN episodes e ON s.imdb_id = e.imdb_id - WHERE {where_clause} - GROUP BY s.imdb_id, s.path, s.last_updated{having_part} - ORDER BY s.last_updated DESC - LIMIT %s OFFSET %s - """ - else: - query = f""" - SELECT - s.imdb_id, - s.path, - s.last_updated, - COUNT(e.episode) as total_episodes, - COUNT(CASE WHEN e.dateadded IS NOT NULL AND e.dateadded != '' THEN 1 END) as episodes_with_dates, - COUNT(CASE WHEN e.has_video_file = 1 THEN 1 END) as episodes_with_video - FROM series s - LEFT JOIN episodes e ON s.imdb_id = e.imdb_id - WHERE {where_clause} - GROUP BY s.imdb_id, s.path, s.last_updated{having_part} - ORDER BY s.last_updated DESC - LIMIT ? OFFSET ? - """ + # PostgreSQL query + query = f""" + SELECT + s.imdb_id, + s.path, + s.last_updated, + COUNT(e.episode) as total_episodes, + COUNT(CASE WHEN e.dateadded IS NOT NULL THEN 1 END) as episodes_with_dates, + COUNT(CASE WHEN e.has_video_file = TRUE THEN 1 END) as episodes_with_video + FROM series s + LEFT JOIN episodes e ON s.imdb_id = e.imdb_id + WHERE {where_clause} + GROUP BY s.imdb_id, s.path, s.last_updated{having_part} + ORDER BY s.last_updated DESC + LIMIT %s OFFSET %s + """ cursor.execute(query, params + [limit, skip]) series = [] @@ -287,10 +258,8 @@ async def get_series_sources(dependencies: dict): """) rows = cursor.fetchall() - if db.db_type == "postgresql": - sources = [list(row.values())[0] for row in rows] - else: - sources = [row[0] for row in rows] + # PostgreSQL RealDictCursor returns dict-like objects + sources = [list(row.values())[0] for row in rows] return {"sources": sources} @@ -360,11 +329,8 @@ async def get_series_episodes(dependencies: dict, imdb_id: str): with db.get_connection() as conn: cursor = conn.cursor() - # Get series info - if db.db_type == "postgresql": - cursor.execute("SELECT * FROM series WHERE imdb_id = %s", (imdb_id,)) - else: - cursor.execute("SELECT * FROM series WHERE imdb_id = ?", (imdb_id,)) + # Get series info - PostgreSQL + cursor.execute("SELECT * FROM series WHERE imdb_id = %s", (imdb_id,)) series_row = cursor.fetchone() if not series_row: raise HTTPException(status_code=404, detail="Series not found") @@ -375,21 +341,13 @@ async def get_series_episodes(dependencies: dict, imdb_id: str): except: series_info['title'] = imdb_id - # Get episodes - if db.db_type == "postgresql": - cursor.execute(""" - SELECT season, episode, aired, dateadded, source, has_video_file, last_updated - FROM episodes - WHERE imdb_id = %s - ORDER BY season, episode - """, (imdb_id,)) - else: - cursor.execute(""" - SELECT season, episode, aired, dateadded, source, has_video_file, last_updated - FROM episodes - WHERE imdb_id = ? - ORDER BY season, episode - """, (imdb_id,)) + # Get episodes - PostgreSQL + cursor.execute(""" + SELECT season, episode, aired, dateadded, source, has_video_file, last_updated + FROM episodes + WHERE imdb_id = %s + ORDER BY season, episode + """, (imdb_id,)) episodes = [] for row in cursor.fetchall(): @@ -411,21 +369,13 @@ async def get_missing_dates_report(dependencies: dict): with db.get_connection() as conn: cursor = conn.cursor() - # Movies without dates - PostgreSQL compatible - if db.db_type == "postgresql": - cursor.execute(""" - SELECT imdb_id, path, released, source, last_updated - FROM movies - WHERE dateadded IS NULL OR source = 'no_valid_date_source' - ORDER BY last_updated DESC - """) - else: - cursor.execute(""" - SELECT imdb_id, path, released, source, last_updated - FROM movies - WHERE dateadded IS NULL OR dateadded = '' OR source = 'no_valid_date_source' - ORDER BY last_updated DESC - """) + # Movies without dates - PostgreSQL + cursor.execute(""" + SELECT imdb_id, path, released, source, last_updated + FROM movies + WHERE dateadded IS NULL OR source = 'no_valid_date_source' + ORDER BY last_updated DESC + """) movies_missing = [] for row in cursor.fetchall(): movie = dict(row) @@ -437,23 +387,14 @@ async def get_missing_dates_report(dependencies: dict): movie['source_description'] = map_source_to_description(movie.get('source')) movies_missing.append(movie) - # Episodes without dates - PostgreSQL compatible - if db.db_type == "postgresql": - cursor.execute(""" - SELECT e.imdb_id, e.season, e.episode, e.aired, e.source, e.last_updated, s.path - FROM episodes e - JOIN series s ON e.imdb_id = s.imdb_id - WHERE e.dateadded IS NULL OR e.source = 'no_valid_date_source' - ORDER BY e.last_updated DESC - """) - else: - cursor.execute(""" - SELECT e.imdb_id, e.season, e.episode, e.aired, e.source, e.last_updated, s.path - FROM episodes e - JOIN series s ON e.imdb_id = s.imdb_id - WHERE e.dateadded IS NULL OR e.dateadded = '' OR e.source = 'no_valid_date_source' - ORDER BY e.last_updated DESC - """) + # Episodes without dates - PostgreSQL + cursor.execute(""" + SELECT e.imdb_id, e.season, e.episode, e.aired, e.source, e.last_updated, s.path + FROM episodes e + JOIN series s ON e.imdb_id = s.imdb_id + WHERE e.dateadded IS NULL OR e.source = 'no_valid_date_source' + ORDER BY e.last_updated DESC + """) episodes_missing = [] for row in cursor.fetchall(): episode = dict(row) @@ -465,25 +406,15 @@ async def get_missing_dates_report(dependencies: dict): episode['source_description'] = map_source_to_description(episode.get('source')) episodes_missing.append(episode) - # Summary statistics - PostgreSQL compatible - if db.db_type == "postgresql": - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL") - movies_with_dates = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM movies") - total_movies = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL") - episodes_with_dates = db._get_first_value(cursor.fetchone()) - else: - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL AND dateadded != ''") - movies_with_dates = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM movies") - total_movies = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL AND dateadded != ''") - episodes_with_dates = db._get_first_value(cursor.fetchone()) + # Summary statistics - PostgreSQL + cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL") + movies_with_dates = db._get_first_value(cursor.fetchone()) + + cursor.execute("SELECT COUNT(*) FROM movies") + total_movies = db._get_first_value(cursor.fetchone()) + + cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL") + episodes_with_dates = db._get_first_value(cursor.fetchone()) cursor.execute("SELECT COUNT(*) FROM episodes") total_episodes = db._get_first_value(cursor.fetchone()) @@ -512,31 +443,18 @@ async def get_dashboard_stats(dependencies: dict): with db.get_connection() as conn: cursor = conn.cursor() - # Enhanced statistics - PostgreSQL compatible - if db.db_type == "postgresql": - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL") - movies_with_dates = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NULL OR source = 'no_valid_date_source'") - movies_without_dates = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL") - episodes_with_dates = db._get_first_value(cursor.fetchone()) - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NULL OR source = 'no_valid_date_source'") - episodes_without_dates = db._get_first_value(cursor.fetchone()) - else: - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL AND dateadded != ''") - movies_with_dates = cursor.fetchone()[0] - - cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NULL OR dateadded = '' OR source = 'no_valid_date_source'") - movies_without_dates = cursor.fetchone()[0] - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL AND dateadded != ''") - episodes_with_dates = cursor.fetchone()[0] - - cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NULL OR dateadded = '' OR source = 'no_valid_date_source'") - episodes_without_dates = cursor.fetchone()[0] + # Enhanced statistics - PostgreSQL + cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NOT NULL") + movies_with_dates = db._get_first_value(cursor.fetchone()) + + cursor.execute("SELECT COUNT(*) FROM movies WHERE dateadded IS NULL OR source = 'no_valid_date_source'") + movies_without_dates = db._get_first_value(cursor.fetchone()) + + cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NOT NULL") + episodes_with_dates = db._get_first_value(cursor.fetchone()) + + cursor.execute("SELECT COUNT(*) FROM episodes WHERE dateadded IS NULL OR source = 'no_valid_date_source'") + episodes_without_dates = db._get_first_value(cursor.fetchone()) cursor.execute("SELECT COUNT(*) FROM movies WHERE source = 'no_valid_date_source'") movies_no_valid_source = db._get_first_value(cursor.fetchone()) @@ -545,16 +463,10 @@ async def get_dashboard_stats(dependencies: dict): episodes_no_valid_source = db._get_first_value(cursor.fetchone()) # Recent activity (last 7 days) - if db.db_type == "postgresql": - cursor.execute(""" - SELECT COUNT(*) FROM processing_history - WHERE processed_at > NOW() - INTERVAL '7 days' - """) - else: - cursor.execute(""" - SELECT COUNT(*) FROM processing_history - WHERE processed_at > datetime('now', '-7 days') - """) + cursor.execute(""" + SELECT COUNT(*) FROM processing_history + WHERE processed_at > NOW() - INTERVAL '7 days' + """) recent_activity = db._get_first_value(cursor.fetchone()) # Source distribution for movies @@ -565,10 +477,7 @@ async def get_dashboard_stats(dependencies: dict): GROUP BY source ORDER BY count DESC """) - if db.db_type == "postgresql": - movie_sources = [{"source": list(row.values())[0], "source_description": map_source_to_description(list(row.values())[0]), "count": list(row.values())[1]} for row in cursor.fetchall()] - else: - movie_sources = [{"source": row[0], "source_description": map_source_to_description(row[0]), "count": row[1]} for row in cursor.fetchall()] + movie_sources = [{"source": list(row.values())[0], "source_description": map_source_to_description(list(row.values())[0]), "count": list(row.values())[1]} for row in cursor.fetchall()] # Source distribution for episodes cursor.execute(""" @@ -578,10 +487,7 @@ async def get_dashboard_stats(dependencies: dict): GROUP BY source ORDER BY count DESC """) - if db.db_type == "postgresql": - episode_sources = [{"source": list(row.values())[0], "source_description": map_source_to_description(list(row.values())[0]), "count": list(row.values())[1]} for row in cursor.fetchall()] - else: - episode_sources = [{"source": row[0], "source_description": map_source_to_description(row[0]), "count": row[1]} for row in cursor.fetchall()] + episode_sources = [{"source": list(row.values())[0], "source_description": map_source_to_description(list(row.values())[0]), "count": list(row.values())[1]} for row in cursor.fetchall()] # Calculate total missing dates (movies + episodes) total_missing_dates = movies_without_dates + episodes_without_dates @@ -753,11 +659,11 @@ async def bulk_update_source(dependencies: dict, media_type: str, old_source: st if media_type == "movies": # Update movies - cursor.execute("UPDATE movies SET source = ? WHERE source = ?", (new_source, old_source)) + cursor.execute("UPDATE movies SET source = %s WHERE source = %s", (new_source, old_source)) updated_count = cursor.rowcount # Add history entries - cursor.execute("SELECT imdb_id FROM movies WHERE source = ?", (new_source,)) + cursor.execute("SELECT imdb_id FROM movies WHERE source = %s", (new_source,)) for row in cursor.fetchall(): db.add_processing_history( imdb_id=row[0], @@ -767,11 +673,11 @@ async def bulk_update_source(dependencies: dict, media_type: str, old_source: st ) else: # Update episodes - cursor.execute("UPDATE episodes SET source = ? WHERE source = ?", (new_source, old_source)) + cursor.execute("UPDATE episodes SET source = %s WHERE source = %s", (new_source, old_source)) updated_count = cursor.rowcount # Add history entries - cursor.execute("SELECT imdb_id, season, episode FROM episodes WHERE source = ?", (new_source,)) + cursor.execute("SELECT imdb_id, season, episode FROM episodes WHERE source = %s", (new_source,)) for row in cursor.fetchall(): db.add_processing_history( imdb_id=row[0],