Compare commits

..

No commits in common. "4b4e11054e45936a104a5a2ed0c9cf84b0cd16f8" and "497320c0823f010216cec19305d8c129ca4a6a22" have entirely different histories.

8 changed files with 115 additions and 86 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.env .env
env/* env/*
.git .git
db/*

View File

@ -5,12 +5,6 @@ FROM python:3.10-slim
ENV LISTEN_ADDRESS="0.0.0.0" \ ENV LISTEN_ADDRESS="0.0.0.0" \
LISTEN_PORT=8080 LISTEN_PORT=8080
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Set the working directory in the container # Set the working directory in the container
WORKDIR /app WORKDIR /app

View File

@ -1 +1 @@
0.1.0 0.0.2

View File

@ -13,19 +13,6 @@ services:
networks: networks:
- mpv-youtube-queue-server - mpv-youtube-queue-server
restart: unless-stopped restart: unless-stopped
db:
image: lscr.io/linuxserver/mariadb:latest
container_name: mpv-youtube-queue-db
networks:
- mpv-youtube-queue-server
volumes:
- ./db:/config
environment:
- MYSQL_DATABASE=mpv
- MYSQL_USER=mpvuser
- MYSQL_PASSWORD=SecretPassword
ports:
- 3306:3306
networks: networks:
mpv-youtube-queue-server: mpv-youtube-queue-server:
external: true external: true

View File

@ -1,11 +1,12 @@
LISTEN_ADDRESS=0.0.0.0 # Lisen on all interfaces LISTEN_ADDRESS=0.0.0.0 # Lisen on all interfaces
LISTEN_PORT=8080 # Internal port number LISTEN_PORT=8080 # Internal port number
MPV_SOCKET=/tmp/mpvsocket # Path to mpv socket MPV_SOCKET=/tmp/mpvsocket # Path to mpv socket
LOGLEVEL=info
# Options: # MySQL connection info
# mysql+pymysql://<user>:<password>@<host>[:<port>]/<dbname> - works with MySQL and Mariadb MYSQL_HOST=localhost
# postgresql+psycopg2://user:password@host:port/dbname[?key=value&key=value...] MYSQL_USER=mpvuser
# sqlite:///path MYSQL_PASSWORD=SecretPassword
# oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]] MYSQL_DATABASE=mpv
DATABASE_URL=mysql+pymysql://user:password@localhost:3306/mpv MYSQL_PORT=3306
LOGLEVEL=info

View File

@ -10,7 +10,10 @@ Restart=on-failure
Environment="MPV_SOCKET=/tmp/mpvsocket" Environment="MPV_SOCKET=/tmp/mpvsocket"
Environment="LISTEN_ADDRESS=0.0.0.0" Environment="LISTEN_ADDRESS=0.0.0.0"
Environment="LISTEN_PORT=42069" Environment="LISTEN_PORT=42069"
Environment="DATABASE_URL=mysql+mysqldb://user:password@localhost:3306/mpv" Environment="MYSQL_HOST=http://localhost"
Environment="MYSQL_USER=mpvuser"
Environment="MYSQL_PASSWORD=SecretPassword"
Environment="MYSQL_PORT=3306"
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@ -1,18 +1,10 @@
blinker==1.8.2 blinker==1.8.2
cffi==1.17.1
click==8.1.7 click==8.1.7
cryptography==43.0.1
Flask==3.0.3 Flask==3.0.3
greenlet==3.0.3
gunicorn==23.0.0 gunicorn==23.0.0
itsdangerous==2.2.0 itsdangerous==2.2.0
Jinja2==3.1.4 Jinja2==3.1.4
MarkupSafe==2.1.5 MarkupSafe==2.1.5
oracledb==2.4.1 mysql-connector-python==9.0.0
packaging==24.1 packaging==24.1
psycopg2-binary==2.9.9
pycparser==2.22
PyMySQL==1.1.1
SQLAlchemy==2.0.34
typing_extensions==4.12.2
Werkzeug==3.0.4 Werkzeug==3.0.4

149
server.py
View File

@ -3,17 +3,22 @@ import logging
import os import os
import socket import socket
import time import time
import urllib.parse
from datetime import date
import mysql.connector
from flask import Flask, jsonify, request from flask import Flask, jsonify, request
from sqlalchemy import Column, DateTime, Integer, String, create_engine, exc from mysql.connector import Error
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.sql import func
# Set up basic logging # Set up basic logging
logging.basicConfig( logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
) )
# Ensure Flask doesn't duplicate log messages
log = logging.getLogger("werkzeug")
log.setLevel(logging.ERROR)
# Flask app # Flask app
app = Flask(__name__) app = Flask(__name__)
@ -24,11 +29,16 @@ app.logger.setLevel(logging.getLogger().level)
SOCKET_RETRY_DELAY = 5 # Time in seconds between retries to connect to the socket SOCKET_RETRY_DELAY = 5 # Time in seconds between retries to connect to the socket
MAX_RETRIES = 10 # Maximum number of retries to connect to the socket MAX_RETRIES = 10 # Maximum number of retries to connect to the socket
# Configuration from environment variables # Configuration
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: str = os.getenv("MPV_SOCKET", "/tmp/mpvsocket") MPV_SOCKET: str = os.getenv("MPV_SOCKET", "/tmp/mpvsocket")
HOST_NAME: str = os.getenv("HOST_NAME", "0.0.0.0")
PORT_NUMBER: int = int(os.getenv("PORT_NUMBER", "8080"))
# MySQL Configuration
MYSQL_HOST: str = os.getenv("MYSQL_HOST", "localhost")
MYSQL_DATABASE: str = os.getenv("MYSQL_DATABASE", "your_database")
MYSQL_USER: str = os.getenv("MYSQL_USER", "your_username")
MYSQL_PASSWORD: str = os.getenv("MYSQL_PASSWORD", "your_password")
MYSQL_PORT: int = int(os.getenv("MYSQL_PORT", "3306"))
LOGLEVEL = os.getenv("LOGLEVEL", "INFO").strip().upper() LOGLEVEL = os.getenv("LOGLEVEL", "INFO").strip().upper()
if LOGLEVEL == "DEBUG": if LOGLEVEL == "DEBUG":
@ -40,29 +50,53 @@ elif LOGLEVEL == "ERROR":
else: else:
logging.getLogger().setLevel(logging.INFO) logging.getLogger().setLevel(logging.INFO)
# Set up SQLAlchemy
Base = declarative_base() def get_mysql_connection():
engine = create_engine(DATABASE_URL) """Get a MySQL database connection."""
Session = sessionmaker(bind=engine) try:
session = Session() logging.debug(
f"Connection information: {MYSQL_HOST}, {MYSQL_USER}, {MYSQL_PORT}"
)
connection = mysql.connector.connect(
host=MYSQL_HOST,
user=MYSQL_USER,
password=MYSQL_PASSWORD,
port=MYSQL_PORT,
)
if connection.is_connected():
logging.info("Connected to MySQL database")
return connection
except Error as e:
logging.error(f"Error while connecting to MySQL: {e}")
return None
class WatchHistory(Base): def ensure_watch_history_table_exists():
__tablename__ = "watch_history" """Ensure the watch_history table exists in the mpv schema, otherwise create it."""
connection = get_mysql_connection()
whid = Column(Integer, primary_key=True, autoincrement=True) if connection:
video_url = Column(String(255), nullable=False) try:
video_name = Column(String(255), nullable=False) cursor = connection.cursor()
channel_url = Column(String(255), nullable=False) cursor.execute("CREATE DATABASE IF NOT EXISTS mpv")
channel_name = Column(String(255), nullable=False) cursor.execute(
watch_date = Column(DateTime, nullable=False, server_default=func.now()) """
created_by = Column( CREATE TABLE IF NOT EXISTS mpv.watch_history (
String(100), nullable=False, server_default="mpv-youtube-queue-server" whid INT AUTO_INCREMENT PRIMARY KEY,
) video_url VARCHAR(255) NOT NULL,
video_name VARCHAR(255) NOT NULL,
channel_url VARCHAR(255) NOT NULL,
# Ensure tables exist channel_name VARCHAR(255) NOT NULL,
Base.metadata.create_all(engine) watch_date DATE NOT NULL
)
"""
)
connection.commit()
logging.info("Ensured watch_history table exists")
except Error as e:
logging.error(f"Failed to ensure watch_history table exists: {e}")
finally:
cursor.close()
connection.close()
def send_to_mpv(command): def send_to_mpv(command):
@ -95,27 +129,45 @@ def add_video():
video_name: str = data.get("video_name") video_name: str = data.get("video_name")
channel_url: str = data.get("channel_url") channel_url: str = data.get("channel_url")
channel_name: str = data.get("channel_name") channel_name: str = data.get("channel_name")
watch_date: date = date.today().strftime("%Y-%m-%d")
if video_url and video_name and channel_url and channel_name: if video_url and video_name and channel_url and channel_name and watch_date:
logging.debug(f"Received data: {data}") logging.debug(f"Received data: {data}")
logging.debug(f"Watch date: {watch_date}")
try: # Insert the data into the MySQL database
new_entry = WatchHistory( connection = get_mysql_connection()
video_url=video_url, if connection:
video_name=video_name, try:
channel_url=channel_url, query = """
channel_name=channel_name, INSERT INTO mpv.watch_history (video_url, video_name, channel_url, channel_name, watch_date)
) VALUES (%s, %s, %s, %s, %s)
session.add(new_entry) """
session.commit() cursor = connection.cursor()
logging.debug( cursor.execute(
f"{video_name} by {channel_name} inserted into the database successfully" query,
) (
return jsonify(message="Data added to mpv queue and database"), 200 video_url,
except exc.SQLAlchemyError as e: video_name,
session.rollback() channel_url,
logging.error(f"Failed to insert data into database: {e}") channel_name,
return jsonify(message="Failed to add data to database"), 500 watch_date,
),
)
connection.commit()
logging.info("Data inserted into MySQL database")
return (
jsonify(message="Data added to mpv queue and database"),
200,
)
except Error as e:
logging.error(f"Failed to insert data into MySQL database: {e}")
return jsonify(message="Failed to add data to database"), 500
finally:
cursor.close()
connection.close()
else:
return jsonify(message="Failed to connect to MySQL database"), 500
else: else:
logging.error("Missing required data fields") logging.error("Missing required data fields")
return jsonify(message="Missing required data fields"), 400 return jsonify(message="Missing required data fields"), 400
@ -145,9 +197,10 @@ def handle_request():
if __name__ == "__main__": if __name__ == "__main__":
logging.info(f"Starting server on {LISTEN_ADDRESS}:{LISTEN_PORT}...") logging.info(f"Starting server on {HOST_NAME}:{PORT_NUMBER}...")
ensure_watch_history_table_exists()
try: try:
app.run(host=LISTEN_ADDRESS, port=LISTEN_PORT) app.run(host=HOST_NAME, port=PORT_NUMBER)
except Exception as e: except Exception as e:
logging.exception(f"Error occurred: {e}") logging.exception(f"Error occurred: {e}")
except KeyboardInterrupt: except KeyboardInterrupt: