Compare commits

..

No commits in common. "1847403254bf1d8b5202948c97d07d1e3f1d7aec" 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/*
.git
db/*

View File

@ -5,12 +5,6 @@ FROM python:3.10-slim
ENV LISTEN_ADDRESS="0.0.0.0" \
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
WORKDIR /app

View File

@ -1 +1 @@
0.1.0
0.0.2

View File

@ -13,19 +13,6 @@ services:
networks:
- mpv-youtube-queue-server
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:
mpv-youtube-queue-server:
external: true

View File

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

View File

@ -10,7 +10,10 @@ Restart=on-failure
Environment="MPV_SOCKET=/tmp/mpvsocket"
Environment="LISTEN_ADDRESS=0.0.0.0"
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]
WantedBy=multi-user.target

View File

@ -1,18 +1,10 @@
blinker==1.8.2
cffi==1.17.1
click==8.1.7
cryptography==43.0.1
Flask==3.0.3
greenlet==3.0.3
gunicorn==23.0.0
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
oracledb==2.4.1
mysql-connector-python==9.0.0
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

149
server.py
View File

@ -3,17 +3,22 @@ import logging
import os
import socket
import time
import urllib.parse
from datetime import date
import mysql.connector
from flask import Flask, jsonify, request
from sqlalchemy import Column, DateTime, Integer, String, create_engine, exc
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.sql import func
from mysql.connector import Error
# Set up basic logging
logging.basicConfig(
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
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
MAX_RETRIES = 10 # Maximum number of retries to connect to the socket
# Configuration from environment variables
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")
# Configuration
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()
if LOGLEVEL == "DEBUG":
@ -40,29 +50,53 @@ elif LOGLEVEL == "ERROR":
else:
logging.getLogger().setLevel(logging.INFO)
# Set up SQLAlchemy
Base = declarative_base()
engine = create_engine(DATABASE_URL)
Session = sessionmaker(bind=engine)
session = Session()
def get_mysql_connection():
"""Get a MySQL database connection."""
try:
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):
__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"
)
# Ensure tables exist
Base.metadata.create_all(engine)
def ensure_watch_history_table_exists():
"""Ensure the watch_history table exists in the mpv schema, otherwise create it."""
connection = get_mysql_connection()
if connection:
try:
cursor = connection.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS mpv")
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS mpv.watch_history (
whid INT AUTO_INCREMENT PRIMARY KEY,
video_url VARCHAR(255) NOT NULL,
video_name VARCHAR(255) NOT NULL,
channel_url VARCHAR(255) NOT NULL,
channel_name VARCHAR(255) NOT NULL,
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):
@ -95,27 +129,45 @@ def add_video():
video_name: str = data.get("video_name")
channel_url: str = data.get("channel_url")
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"Watch date: {watch_date}")
try:
new_entry = WatchHistory(
video_url=video_url,
video_name=video_name,
channel_url=channel_url,
channel_name=channel_name,
)
session.add(new_entry)
session.commit()
logging.debug(
f"{video_name} by {channel_name} inserted into the database successfully"
)
return jsonify(message="Data added to mpv queue and database"), 200
except exc.SQLAlchemyError as e:
session.rollback()
logging.error(f"Failed to insert data into database: {e}")
return jsonify(message="Failed to add data to database"), 500
# Insert the data into the MySQL database
connection = get_mysql_connection()
if connection:
try:
query = """
INSERT INTO mpv.watch_history (video_url, video_name, channel_url, channel_name, watch_date)
VALUES (%s, %s, %s, %s, %s)
"""
cursor = connection.cursor()
cursor.execute(
query,
(
video_url,
video_name,
channel_url,
channel_name,
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:
logging.error("Missing required data fields")
return jsonify(message="Missing required data fields"), 400
@ -145,9 +197,10 @@ def handle_request():
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:
app.run(host=LISTEN_ADDRESS, port=LISTEN_PORT)
app.run(host=HOST_NAME, port=PORT_NUMBER)
except Exception as e:
logging.exception(f"Error occurred: {e}")
except KeyboardInterrupt: