diff --git a/database.py b/database.py index ac42c4b..081a8df 100644 --- a/database.py +++ b/database.py @@ -1,5 +1,7 @@ import psycopg2 import psycopg2.extensions +import psycopg2.errors +import unidecode import constants from config import read_db_config @@ -30,6 +32,11 @@ class DBConnectionManager: self.connect() return self._conn + def get_new_cursor(self) -> psycopg2.extensions.cursor: + if self._conn is None: + self.connect() + return self._conn.cursor() + # Global instance that will hold our DB connection conn_manager = DBConnectionManager() @@ -60,3 +67,54 @@ def init_database(): cur.execute(f.read()) conn.commit() logger.verbose("Initialized DB tables.") + + +def add_player_name(player_name: str): + conn = conn_manager.get_connection() + cur = conn.cursor() + try: + cur.execute("INSERT INTO users (player_name) VALUES (%s)", (player_name,)) + conn.commit() + except psycopg2.errors.UniqueViolation: + logger.warn("Player name {} already exists in the database, aborting insertion.".format(player_name)) + conn.rollback() + + +def add_user_name_to_player(hanabi_username: str, player_name: str): + normalized_username = unidecode.unidecode(hanabi_username).lower() + cur = conn_manager.get_new_cursor() + cur.execute("SELECT id FROM users WHERE player_name = (%s)", (player_name,)) + user_id = cur.fetchone() + if user_id is None: + logger.error("Display name {} not found in database, cannot add username to it.".format(player_name)) + return + else: + cur.execute("SELECT username, player_name from user_accounts " + "INNER JOIN users" + " ON user_accounts.user_id = users.id " + "WHERE " + " normalized_username = (%s)", + (normalized_username,) + ) + res = cur.fetchone() + if res is not None: + existing_username, existing_player_name = res + if existing_player_name == player_name: + logger.warn("Hanabi username {} is already registered to player {}, attempted to re-register it.".format( + existing_username, existing_player_name + )) + else: + logger.error("Hanabi username {} is already associated to player {}, cannot register it to player {}.".format( + res[0], res[1], player_name + )) + return + cur.execute( + "INSERT INTO user_accounts (username, normalized_username, user_id) VALUES (%s, %s, %s)", + (hanabi_username, normalized_username, user_id) + ) + conn_manager.get_connection().commit() + + +def add_player(player_name: str, user_name: str): + add_player_name(player_name) + add_user_name_to_player(user_name, player_name) diff --git a/install/database_schema.sql b/install/database_schema.sql index 1cda409..0f3bea5 100644 --- a/install/database_schema.sql +++ b/install/database_schema.sql @@ -68,8 +68,7 @@ DROP TABLE IF EXISTS users CASCADE; CREATE TABLE users ( id SERIAL PRIMARY KEY, - name TEXT NOT NULL, - discord_tag TEXT + player_name TEXT NOT NULL UNIQUE ); @@ -246,7 +245,7 @@ DROP TABLE IF EXISTS variant_base_ratings CASCADE; CREATE TABLE variant_base_ratings ( /* Note that a variant already includes the number of suits, so we do not have to add this here. */ variant_id SMALLINT, - player_count SMALLINT NOT NULL + player_count SMALLINT NOT NULL, rating REAL NOT NULL, PRIMARY KEY (variant_id, player_count) ); diff --git a/requirements.txt b/requirements.txt index 3d6d08a..519bc15 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ platformdirs PyYAML verboselogs python-dateutil +unidecode