Fix/pylint cleanup (#8)
Some checks are pending
CI / build (3.10) (push) Waiting to run
CI / build (3.8) (push) Waiting to run
CI / build (3.9) (push) Waiting to run

* Fix pylint warnings across all 24 Python files in web_server

- Add module, class, and function docstrings (C0114, C0115, C0116)
- Fix import ordering: stdlib before third-party before local (C0411)
- Replace wildcard imports with explicit named imports (W0401)
- Remove trailing whitespace and add missing final newlines (C0303, C0304)
- Replace dict() with dict literals (R1735)
- Remove unused imports and variables (W0611, W0612)
- Narrow broad Exception catches to specific exceptions (W0718)
- Replace f-string logging with lazy % formatting (W1203)
- Fix variable naming: UPPER_CASE for constants, snake_case for locals (C0103)
- Add pylint disable comments for necessary global statements (W0603)
- Fix no-else-return, simplifiable-if-expression, singleton-comparison
- Fix bad indentation in stripe.py (W0311)
- Add encoding="utf-8" to open() calls (W1514)
- Add check=True to subprocess.run() calls (W1510)
- Register Celery task modules via conf.include

* Update `package-lock.json` add peer dependencies
This commit is contained in:
Christopher Ahern
2026-02-07 20:57:28 +00:00
committed by GitHub
parent fed1a2f288
commit 2758be8680
25 changed files with 680 additions and 419 deletions

View File

@@ -1,9 +1,11 @@
from database.database import Database
from typing import Optional
import os, subprocess
"""Stream data retrieval and management utilities."""
import os
import subprocess
from typing import Optional, List
from time import sleep
from utils.path_manager import PathManager
from database.database import Database
def get_streamer_live_status(user_id: int):
"""
@@ -11,8 +13,8 @@ def get_streamer_live_status(user_id: int):
"""
with Database() as db:
is_live = db.fetchone("""
SELECT is_live
FROM users
SELECT is_live
FROM users
WHERE user_id = ?;
""", (user_id,))
@@ -21,17 +23,19 @@ def get_streamer_live_status(user_id: int):
def get_followed_live_streams(user_id: int) -> Optional[List[dict]]:
"""
Searches for streamers who the user followed which are currently live
Returns a list of live streams with the streamer's user id, stream title, and number of viewers
Returns a list of live streams with the streamer's user id,
stream title, and number of viewers
"""
with Database() as db:
live_streams = db.fetchall("""
SELECT users.user_id, streams.title, streams.num_viewers, users.username
FROM streams JOIN users
ON streams.user_id = users.user_id
WHERE users.user_id IN
(SELECT followed_id FROM follows WHERE user_id = ?)
AND users.is_live = 1;
""", (user_id,))
SELECT users.user_id, streams.title,
streams.num_viewers, users.username
FROM streams JOIN users
ON streams.user_id = users.user_id
WHERE users.user_id IN
(SELECT followed_id FROM follows WHERE user_id = ?)
AND users.is_live = 1;
""", (user_id,))
return live_streams
def get_current_stream_data(user_id: int) -> Optional[dict]:
@@ -40,7 +44,8 @@ def get_current_stream_data(user_id: int) -> Optional[dict]:
"""
with Database() as db:
most_recent_stream = db.fetchone("""
SELECT s.user_id, u.username, s.title, s.start_time, s.num_viewers, c.category_name, c.category_id
SELECT s.user_id, u.username, s.title, s.start_time,
s.num_viewers, c.category_name, c.category_id
FROM streams AS s
JOIN categories AS c ON s.category_id = c.category_id
JOIN users AS u ON s.user_id = u.user_id
@@ -51,78 +56,92 @@ def get_current_stream_data(user_id: int) -> Optional[dict]:
def end_user_stream(stream_key, user_id, username):
"""
Utility function to end a user's stream
Parameters:
stream_key: The stream key of the user
user_id: The ID of the user
username: The username of the user
Returns:
bool: True if stream was ended successfully, False otherwise
"""
from flask import current_app
from datetime import datetime
from dateutil import parser
from celery_tasks.streaming import combine_ts_stream
from utils.path_manager import PathManager
path_manager = PathManager()
pm = PathManager()
print(f"Ending stream for user {username} (ID: {user_id})", flush=True)
if not stream_key or not user_id or not username:
print("Cannot end stream - missing required information", flush=True)
return False
return False, "Missing required information"
try:
# Open database connection
with Database() as db:
# Get stream info
stream_info = db.fetchone("""SELECT *
FROM streams
WHERE user_id = ?""", (user_id,))
stream_info = db.fetchone(
"""SELECT *
FROM streams
WHERE user_id = ?""", (user_id,))
# If user is not streaming, just return
if not stream_info:
print(f"User {username} (ID: {user_id}) is not streaming", flush=True)
print(
f"User {username} (ID: {user_id}) "
"is not streaming", flush=True)
return True, "User is not streaming"
# Remove stream from database
db.execute("""DELETE FROM streams
WHERE user_id = ?""", (user_id,))
db.execute(
"""DELETE FROM streams
WHERE user_id = ?""", (user_id,))
# Move stream to vod table
stream_length = int(
(datetime.now() - parser.parse(stream_info.get("start_time"))).total_seconds())
db.execute("""INSERT INTO vods (user_id, title, datetime, category_id, length, views)
VALUES (?, ?, ?, ?, ?, ?)""", (user_id,
stream_info.get("title"),
stream_info.get("start_time"),
stream_info.get("category_id"),
stream_length,
0))
(datetime.now() - parser.parse(
stream_info.get("start_time")
)).total_seconds())
db.execute(
"""INSERT INTO vods
(user_id, title, datetime, category_id,
length, views)
VALUES (?, ?, ?, ?, ?, ?)""",
(user_id,
stream_info.get("title"),
stream_info.get("start_time"),
stream_info.get("category_id"),
stream_length,
0))
vod_id = db.get_last_insert_id()
# Set user as not streaming
db.execute("""UPDATE users
SET is_live = 0
WHERE user_id = ?""", (user_id,))
db.execute(
"""UPDATE users
SET is_live = 0
WHERE user_id = ?""", (user_id,))
# Queue task to combine TS files into MP4
combine_ts_stream.delay(
path_manager.get_stream_path(username),
path_manager.get_vods_path(username),
pm.get_stream_path(username),
pm.get_vods_path(username),
vod_id,
path_manager.get_vod_thumbnail_file_path(username, vod_id)
pm.get_vod_thumbnail_file_path(username, vod_id)
)
print(f"Stream ended for user {username} (ID: {user_id})", flush=True)
print(
f"Stream ended for user {username} (ID: {user_id})",
flush=True)
return True, "Stream ended successfully"
except Exception as e:
print(f"Error ending stream for user {username}: {str(e)}", flush=True)
return False, f"Error ending stream: {str(e)}"
except (ValueError, TypeError, KeyError) as exc:
print(
f"Error ending stream for user {username}: {str(exc)}",
flush=True)
return False, f"Error ending stream: {str(exc)}"
def get_category_id(category_name: str) -> Optional[int]:
"""
@@ -130,8 +149,8 @@ def get_category_id(category_name: str) -> Optional[int]:
"""
with Database() as db:
data = db.fetchone("""
SELECT category_id
FROM categories
SELECT category_id
FROM categories
WHERE category_name = ?;
""", (category_name,))
return data['category_id'] if data else None
@@ -142,7 +161,7 @@ def get_custom_thumbnail_status(user_id: int) -> Optional[dict]:
"""
with Database() as db:
custom_thumbnail = db.fetchone("""
SELECT custom_thumbnail
SELECT custom_thumbnail
FROM streams
WHERE user_id = ?;
""", (user_id,))
@@ -153,7 +172,13 @@ def get_vod(vod_id: int) -> dict:
Returns data of a streamers vod
"""
with Database() as db:
vod = db.fetchone("""SELECT vods.*, username, category_name FROM vods JOIN users ON vods.user_id = users.user_id JOIN categories ON vods.category_id = categories.category_id WHERE vod_id = ?;""", (vod_id,))
vod = db.fetchone(
"""SELECT vods.*, username, category_name
FROM vods
JOIN users ON vods.user_id = users.user_id
JOIN categories
ON vods.category_id = categories.category_id
WHERE vod_id = ?;""", (vod_id,))
return vod
def get_latest_vod(user_id: int):
@@ -161,7 +186,14 @@ def get_latest_vod(user_id: int):
Returns data of the most recent stream by a streamer
"""
with Database() as db:
latest_vod = db.fetchone("""SELECT vods.*, username, category_name FROM vods JOIN users ON vods.user_id = users.user_id JOIN categories ON vods.category_id = categories.category_id WHERE vods.user_id = ? ORDER BY vod_id DESC;""", (user_id,))
latest_vod = db.fetchone(
"""SELECT vods.*, username, category_name
FROM vods
JOIN users ON vods.user_id = users.user_id
JOIN categories
ON vods.category_id = categories.category_id
WHERE vods.user_id = ?
ORDER BY vod_id DESC;""", (user_id,))
return latest_vod
def get_user_vods(user_id: int):
@@ -169,10 +201,17 @@ def get_user_vods(user_id: int):
Returns data of all vods by a streamer
"""
with Database() as db:
vods = db.fetchall("""SELECT vods.*, username, category_name FROM vods JOIN users ON vods.user_id = users.user_id JOIN categories ON vods.category_id = categories.category_id WHERE vods.user_id = ? ORDER BY vod_id DESC;""", (user_id,))
vods = db.fetchall(
"""SELECT vods.*, username, category_name
FROM vods
JOIN users ON vods.user_id = users.user_id
JOIN categories
ON vods.category_id = categories.category_id
WHERE vods.user_id = ?
ORDER BY vod_id DESC;""", (user_id,))
return vods
def generate_thumbnail(stream_file: str, thumbnail_file: str, second_capture) -> None:
def generate_thumbnail(stream_file: str, thumbnail_file: str, second_capture=0) -> None:
"""
Generates the thumbnail of a stream
"""
@@ -192,10 +231,16 @@ def generate_thumbnail(stream_file: str, thumbnail_file: str, second_capture) ->
]
try:
subprocess.run(thumbnail_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
subprocess.run(
thumbnail_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True)
print(f"Thumbnail generated for {stream_file}")
except subprocess.CalledProcessError as e:
print(f"No information available for {stream_file}, aborting thumbnail generation")
except subprocess.CalledProcessError:
print(
f"No information available for {stream_file}, "
"aborting thumbnail generation")
def remove_hls_files(stream_path: str) -> None:
"""
@@ -221,11 +266,13 @@ def get_video_duration(video_path: str) -> int:
]
try:
video_length = subprocess.check_output(video_length_command).decode("utf-8")
video_length = subprocess.check_output(
video_length_command
).decode("utf-8")
print(f"Video length: {video_length}")
return int(float(video_length))
except subprocess.CalledProcessError as e:
print(f"Error getting video length: {e}")
except subprocess.CalledProcessError:
print("Error getting video length")
return 0
def get_stream_tags(user_id: int) -> Optional[List[str]]:
@@ -234,10 +281,10 @@ def get_stream_tags(user_id: int) -> Optional[List[str]]:
"""
with Database() as db:
tags = db.fetchall("""
SELECT tag_name
SELECT tag_name
FROM tags
JOIN stream_tags ON tags.tag_id = stream_tags.tag_id
WHERE user_id = ?;
WHERE user_id = ?;
""", (user_id,))
return tags
@@ -247,9 +294,9 @@ def get_vod_tags(vod_id: int):
"""
with Database() as db:
tags = db.fetchall("""
SELECT tag_name
SELECT tag_name
FROM tags
JOIN vod_tags ON tags.tag_id = vod_tags.tag_id
WHERE vod_id = ?;
WHERE vod_id = ?;
""", (vod_id,))
return tags
return tags