update code structure and get session on each query
All checks were successful
Build Docker Image / build (push) Successful in 12m54s
All checks were successful
Build Docker Image / build (push) Successful in 12m54s
This commit is contained in:
19
app/__init__.py
Normal file
19
app/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from flask import Flask
|
||||
|
||||
from app.config import Config
|
||||
from app.database import engine
|
||||
from app.models import Base
|
||||
from app.views import bp
|
||||
|
||||
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(Config)
|
||||
|
||||
# Ensure database tables exist
|
||||
Base.metadata.create_all(engine)
|
||||
|
||||
# Register blueprints
|
||||
app.register_blueprint(bp)
|
||||
|
||||
return app
|
||||
9
app/config.py
Normal file
9
app/config.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import os
|
||||
|
||||
|
||||
class Config:
|
||||
LISTEN_ADDRESS = os.getenv("LISTEN_ADDRESS", "0.0.0.0")
|
||||
LISTEN_PORT = int(os.getenv("LISTEN_PORT", "8080"))
|
||||
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./mpv.db")
|
||||
MPV_SOCKET = os.getenv("MPV_SOCKET", "/tmp/mpvsocket")
|
||||
LOGLEVEL = os.getenv("LOGLEVEL", "INFO").strip().upper()
|
||||
14
app/database.py
Normal file
14
app/database.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from app.config import Config
|
||||
|
||||
engine = create_engine(Config.DATABASE_URL, pool_pre_ping=True)
|
||||
Session = scoped_session(sessionmaker(bind=engine))
|
||||
|
||||
|
||||
def get_db_session():
|
||||
return Session()
|
||||
|
||||
|
||||
def close_db_session(exception=None):
|
||||
Session.remove()
|
||||
28
app/models.py
Normal file
28
app/models.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from sqlalchemy import Column, Integer, String, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class WatchHistory(Base):
|
||||
__tablename__ = "watch_history"
|
||||
whid = Column(Integer, primary_key=True, autoincrement=True)
|
||||
video_url = Column(String(255), nullable=False)
|
||||
video_name = Column(String(255), nullable=False)
|
||||
channel_url = Column(String(255), nullable=False)
|
||||
channel_name = Column(String(255), nullable=False)
|
||||
watch_date = Column(DateTime, nullable=False, server_default=func.now())
|
||||
created_by = Column(
|
||||
String(100), nullable=False, server_default="mpv-youtube-queue-server"
|
||||
)
|
||||
|
||||
|
||||
class SavedQueue(Base):
|
||||
__tablename__ = "saved_queue"
|
||||
sqid = Column(Integer, primary_key=True, autoincrement=True)
|
||||
video_url = Column(String(255), nullable=False)
|
||||
created_date = Column(DateTime, nullable=False, server_default=func.now())
|
||||
created_by = Column(
|
||||
String(100), nullable=False, server_default="mpv-youtube-queue-server"
|
||||
)
|
||||
27
app/mpv.py
Normal file
27
app/mpv.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import socket
|
||||
import time
|
||||
import logging
|
||||
from app.config import Config
|
||||
|
||||
SOCKET_RETRY_DELAY = 5
|
||||
MAX_RETRIES = 10
|
||||
|
||||
|
||||
def send_to_mpv(command):
|
||||
attempts = 0
|
||||
while attempts < MAX_RETRIES:
|
||||
try:
|
||||
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client_socket:
|
||||
client_socket.connect(Config.MPV_SOCKET)
|
||||
client_socket.sendall(command.encode("utf-8"))
|
||||
logging.info("Command sent to mpv successfully.")
|
||||
return True
|
||||
except socket.error as e:
|
||||
attempts += 1
|
||||
logging.error(
|
||||
f"Failed to connect to socket (attempt {attempts}/{MAX_RETRIES}): {e}. Retrying in {SOCKET_RETRY_DELAY} seconds..."
|
||||
)
|
||||
time.sleep(SOCKET_RETRY_DELAY)
|
||||
|
||||
logging.error(f"Exceeded maximum retries ({MAX_RETRIES}). Ignoring the request.")
|
||||
return False
|
||||
101
app/views.py
Normal file
101
app/views.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import logging
|
||||
|
||||
from flask import Blueprint, g, jsonify, request
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from app.database import get_db_session
|
||||
from app.models import SavedQueue, WatchHistory
|
||||
from app.mpv import send_to_mpv
|
||||
|
||||
bp = Blueprint("views", __name__)
|
||||
|
||||
|
||||
@bp.before_request
|
||||
def before_request():
|
||||
g.db_session = get_db_session()
|
||||
|
||||
|
||||
@bp.teardown_app_request
|
||||
def shutdown_session(exception=None):
|
||||
if hasattr(g, "db_session"):
|
||||
g.db_session.close()
|
||||
|
||||
|
||||
@bp.route("/save_queue", methods=["POST"])
|
||||
def save_queue():
|
||||
data = request.get_json()
|
||||
if not data or "urls" not in data:
|
||||
return jsonify(message="Invalid JSON data"), 400
|
||||
|
||||
db_session = g.db_session
|
||||
db_session.query(SavedQueue).delete()
|
||||
|
||||
for url in data["urls"]:
|
||||
new_entry = SavedQueue(video_url=url)
|
||||
db_session.add(new_entry)
|
||||
|
||||
try:
|
||||
db_session.commit()
|
||||
return jsonify(message="Data added to saved queue"), 200
|
||||
except SQLAlchemyError as e:
|
||||
db_session.rollback()
|
||||
logging.error(f"Failed to insert data: {e}")
|
||||
return jsonify(message="Database error"), 500
|
||||
|
||||
|
||||
@bp.route("/load_queue", methods=["GET"])
|
||||
def load_queue():
|
||||
"""
|
||||
Retrieves the saved queue of video URLs.
|
||||
"""
|
||||
logging.debug("Loading saved queue")
|
||||
db_session = g.db_session
|
||||
urls = [entry.video_url for entry in db_session.query(SavedQueue).all()]
|
||||
logging.debug(f"Loaded {len(urls)} URLs from the saved queue")
|
||||
return jsonify(urls), 200
|
||||
|
||||
|
||||
@bp.route("/add_video", methods=["POST"])
|
||||
def add_video():
|
||||
data = request.get_json()
|
||||
if not all(
|
||||
k in data for k in ["video_url", "video_name", "channel_url", "channel_name"]
|
||||
):
|
||||
return jsonify(message="Missing required fields"), 400
|
||||
|
||||
new_entry = WatchHistory(
|
||||
video_url=data["video_url"],
|
||||
video_name=data["video_name"],
|
||||
channel_url=data["channel_url"],
|
||||
channel_name=data["channel_name"],
|
||||
)
|
||||
|
||||
db_session = g.db_session
|
||||
db_session.add(new_entry)
|
||||
|
||||
try:
|
||||
db_session.commit()
|
||||
logging.debug("Video added to watch history")
|
||||
logging.debug(f"URL: {data['video_url']}")
|
||||
logging.debug(f"Video name: {data['video_name']}")
|
||||
logging.debug(f"Channel URL: {data['channel_url']}")
|
||||
logging.debug(f"Channel name: {data['channel_name']}")
|
||||
return jsonify(message="Video added"), 200
|
||||
except SQLAlchemyError as e:
|
||||
db_session.rollback()
|
||||
logging.error(f"Database error: {e}")
|
||||
return jsonify(message="Failed to add video"), 500
|
||||
|
||||
|
||||
@bp.route("/", methods=["GET"])
|
||||
def handle_request():
|
||||
video_url = request.args.get("url")
|
||||
if not video_url:
|
||||
return "Missing 'url' parameter", 400
|
||||
|
||||
command = (
|
||||
f'{{"command": ["script-message", "add_to_youtube_queue", "{video_url}"]}}\n'
|
||||
)
|
||||
if send_to_mpv(command):
|
||||
return "URL added to mpv queue", 200
|
||||
return "Failed to add URL to mpv queue", 500
|
||||
Reference in New Issue
Block a user