diff --git a/backend/Dockerfile b/Dockerfile similarity index 100% rename from backend/Dockerfile rename to Dockerfile diff --git a/backend/app.py b/backend/app.py index a36000c..7511e4e 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template, Response, abort, request, redirect, send_from_directory +from flask import Flask, render_template, Response, abort, request, redirect, send_from_directory, jsonify import helpers import database import data_adapters @@ -131,8 +131,8 @@ def get_song_completions(input_string=""): input_string = request.args.get('search', input_string) if input_string != "": print(input_string) - list = database.get_song_completions(input_string=input_string) - return Response(json.dumps(list, ensure_ascii=False).encode('utf-8'), mimetype='text/json') + result = [list(x) for x in database.get_song_completions(input_string=input_string)] + return jsonify(result) else: return 400 diff --git a/backend/database.py b/backend/database.py index 8fe2cd2..f34d63e 100644 --- a/backend/database.py +++ b/backend/database.py @@ -1,6 +1,10 @@ # -*- coding: utf_8 -*- +from types import NoneType +from MySQLdb import Connection +from sqlalchemy import create_engine import sqlite3 +import mariadb import pandas from io import StringIO @@ -9,23 +13,28 @@ entry_table = "entries" index_label = "Id" done_table = "done_songs" +connection = None -def open_db(): - conn = sqlite3.connect("/tmp/karaoqueue.db") - conn.execute('PRAGMA encoding = "UTF-8";') - return conn + +def open_db() -> Connection: + global connection + if (not connection): + engine = create_engine( + "mysql://ek0ur6p6ky9gdmif:jk571ov6g38g5iqv@eporqep6b4b8ql12.chr7pe7iynqr.eu-west-1.rds.amazonaws.com:3306/xdfmpudc3remzgj0") + connection = engine.connect() + # cur.execute('PRAGMA encoding = "UTF-8";') + return connection def import_songs(song_csv): print("Start importing Songs...") df = pandas.read_csv(StringIO(song_csv), sep=';') conn = open_db() - cur = conn.cursor() df.to_sql(song_table, conn, if_exists='replace', index=False) - cur.execute("SELECT Count(Id) FROM songs") + cur = conn.execute("SELECT Count(Id) FROM songs") num_songs = cur.fetchone()[0] - conn.close() + # conn.close() print("Imported songs ({} in Database)".format(num_songs)) return("Imported songs ({} in Database)".format(num_songs)) @@ -34,157 +43,143 @@ def create_entry_table(): conn = open_db() conn.execute('CREATE TABLE IF NOT EXISTS '+entry_table + ' (ID INTEGER PRIMARY KEY NOT NULL, Song_Id INTEGER NOT NULL, Name VARCHAR(255), Client_Id VARCHAR(36), Transferred INTEGER DEFAULT 0)') - conn.close() + # conn.close() def create_done_song_table(): conn = open_db() conn.execute('CREATE TABLE IF NOT EXISTS '+done_table + ' (Song_Id INTEGER PRIMARY KEY NOT NULL, Plays INTEGER)') - conn.close() + # conn.close() def create_song_table(): conn = open_db() - conn.execute("CREATE TABLE IF NOT EXISTS \""+song_table+"""\" ( - "Id" INTEGER, - "Title" TEXT, - "Artist" TEXT, - "Year" INTEGER, - "Duo" INTEGER, - "Explicit" INTEGER, - "Date Added" TEXT, - "Styles" TEXT, - "Languages" TEXT + conn.execute("CREATE TABLE IF NOT EXISTS `"+song_table+"""` ( + `Id` INTEGER, + `Title` TEXT, + `Artist` TEXT, + `Year` INTEGER, + `Duo` INTEGER, + `Explicit` INTEGER, + `Date Added` TEXT, + `Styles` TEXT, + `Languages` TEXT )""") - conn.close() + # conn.close() def create_list_view(): conn = open_db() - conn.execute("""CREATE VIEW IF NOT EXISTS [Liste] AS - SELECT Name, Title, Artist, entries.Id, songs.Id, entries.Transferred + conn.execute("""CREATE OR REPLACE VIEW `Liste` AS + SELECT Name, Title, Artist, entries.Id AS entry_ID, songs.Id AS song_ID, entries.Transferred FROM entries, songs - WHERE entries.Song_Id=songs.Id""") - conn.close() + WHERE entries.Song_Id=Song_ID""") + # conn.close() def create_done_song_view(): conn = open_db() - conn.execute("""CREATE VIEW IF NOT EXISTS [Abspielliste] AS + conn.execute("""CREATE OR REPLACE VIEW `Abspielliste` AS SELECT Artist || \" - \" || Title AS Song, Plays AS Wiedergaben FROM songs, done_songs WHERE done_songs.Song_Id=songs.Id""") - conn.close() + # conn.close() def get_list(): conn = open_db() - conn.row_factory = sqlite3.Row - cur = conn.cursor() - cur.execute("SELECT * FROM Liste") + cur = conn.execute("SELECT * FROM Liste") return cur.fetchall() def get_played_list(): conn = open_db() - cur = conn.cursor() - cur.execute("SELECT * FROM Abspielliste") + cur = conn.execute("SELECT * FROM Abspielliste") return cur.fetchall() def get_song_list(): conn = open_db() - cur = conn.cursor() - cur.execute("SELECT Artist || \" - \" || Title AS Song, Id FROM songs;") + cur = conn.execute( + "SELECT Artist || \" - \" || Title AS Song, Id FROM songs;") return cur.fetchall() def get_song_completions(input_string): conn = open_db() - cur = conn.cursor() # Don't look, it burns... prepared_string = "%{0}%".format( input_string).upper() # "Test" -> "%TEST%" print(prepared_string) - cur.execute( - "SELECT Title || \" - \" || Artist AS Song, Id FROM songs WHERE REPLACE(REPLACE(REPLACE(REPLACE(UPPER( SONG ),'ö','Ö'),'ü','Ü'),'ä','Ä'),'ß','ẞ') LIKE (?) LIMIT 20;", (prepared_string,)) + cur = conn.execute( + "SELECT CONCAT(Artist,\" - \",Title) AS Song, Id FROM songs WHERE CONCAT(Artist,\" - \",Title) LIKE (%s) LIMIT 20;", [prepared_string]) return cur.fetchall() def add_entry(name, song_id, client_id): conn = open_db() - cur = conn.cursor() - cur.execute( - "INSERT INTO entries (Song_Id,Name,Client_Id) VALUES(?,?,?);", (song_id, name, client_id)) - conn.commit() - conn.close() + conn.execute( + "INSERT INTO entries (Song_Id,Name,Client_Id) VALUES(%s,%s,%s);", (song_id, name, client_id)) + # conn.close() return def add_sung_song(entry_id): conn = open_db() - cur = conn.cursor() - cur.execute("""SELECT Song_Id FROM entries WHERE Id=?""", (entry_id,)) + cur = conn.execute( + """SELECT Song_Id FROM entries WHERE Id=?""", (entry_id,)) song_id = cur.fetchone()[0] - cur.execute("""INSERT OR REPLACE INTO done_songs (Song_Id, Plays) + conn.execute("""INSERT OR REPLACE INTO done_songs (Song_Id, Plays) VALUES("""+str(song_id)+""", COALESCE( (SELECT Plays FROM done_songs WHERE Song_Id="""+str(song_id)+"), 0) + 1)" - ) - conn.commit() + ) delete_entry(entry_id) - conn.close() + # conn.close() return True def toggle_transferred(entry_id): conn = open_db() - cur = conn.cursor() - cur.execute("SELECT Transferred FROM entries WHERE ID =?", (entry_id,)) + cur = conn.execute( + "SELECT Transferred FROM entries WHERE ID =?", (entry_id,)) marked = cur.fetchall()[0][0] if(marked == 0): - cur.execute( + conn.execute( "UPDATE entries SET Transferred = 1 WHERE ID =?", (entry_id,)) else: - cur.execute( + conn.execute( "UPDATE entries SET Transferred = 0 WHERE ID =?", (entry_id,)) - conn.commit() - conn.close() + # conn.close() return True def check_entry_quota(client_id): conn = open_db() - cur = conn.cursor() - cur.execute( + cur = conn.execute( "SELECT Count(*) FROM entries WHERE entries.Client_Id = ?", (client_id,)) return cur.fetchall()[0][0] def check_queue_length(): conn = open_db() - cur = conn.cursor() - cur.execute("SELECT Count(*) FROM entries") + cur = conn.execute("SELECT Count(*) FROM entries") return cur.fetchall()[0][0] def clear_played_songs(): conn = open_db() - cur = conn.cursor() - cur.execute("DELETE FROM done_songs") - conn.commit() - conn.close() + conn.execute("DELETE FROM done_songs") + # conn.close() return True def delete_entry(id): conn = open_db() - cur = conn.cursor() - cur.execute("DELETE FROM entries WHERE id=?", (id,)) - conn.commit() - conn.close() + conn.execute("DELETE FROM entries WHERE id=?", (id,)) + # conn.close() return True @@ -194,19 +189,15 @@ def delete_entries(ids): idlist.append((x,)) try: conn = open_db() - cur = conn.cursor() - cur.executemany("DELETE FROM entries WHERE id=?", idlist) - conn.commit() - conn.close() + cur = conn.execute("DELETE FROM entries WHERE id=?", idlist) + # conn.close() return cur.rowcount - except sqlite3.Error as error: + except mariadb.Error as error: return -1 def delete_all_entries(): conn = open_db() - cur = conn.cursor() - cur.execute("DELETE FROM entries") - conn.commit() - conn.close() + conn.execute("DELETE FROM entries") + # conn.close() return True diff --git a/backend/requirements.txt b/backend/requirements.txt index 04324d8..adb164c 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -2,4 +2,7 @@ requests pandas Flask-BasicAuth bs4 -gunicorn \ No newline at end of file +gunicorn +mariadb +SQLAlchemy +mysqlclient \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..7ef04ae --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,11 @@ +version: "3.9" +services: + db: + image: mariadb + restart: always + environment: + MARIADB_ROOT_PASSWORD: dpMAZj*Mc4%FZM!V + MARIADB_ROOT_HOST: localhost + MARIADB_DATABASE: karaoqueue + MARIADB_USER: karaoqueue + MARIADB_PASSWORD: a5G@P*^tCW$$w@wE \ No newline at end of file