"""Admidio db functions. Here's some queries that might be relevant: Special fields SELECT usf_id FROM adm_user_fields where usf_name = - PMB_PAID : Date paid - PMB_FEE : The amount to pay - PMB_DUEDATE - the due date Get user: 'SELECT usr_login_name FROM adm_users WHERE usr_id = ' Get Payment Date: 'SELECT usd_value FROM adm_user_data WHERE usd_usr_id = " + body.id + " AND usd_usf_id = 22 Get Payment Amount: 'SELECT usd_value FROM adm_user_data WHERE usd_usr_id = " + body.id + " AND usd_usf_id = 23' paymentAmount[0].usd_value Success: 'INSERT INTO adm_user_data (usd_usr_id, usd_usf_id, usd_value) VALUES (' + user_id + ', 23, "' + date + '") ON DUPLICATE KEY UPDATE usd_value = "' + date + '";' """ import logging from contextlib import contextmanager import mariadb from typing import Final, Iterator LOG = logging.getLogger(__name__) class AdmidioDB: """Low-level admidio class.""" def __init__( self, user: str, password: str, host: str, database: str, port: int = 3306 ) -> None: """Initialize database class.""" def connect() -> mariadb.Connection: connection: mariadb.Connection = mariadb.connect( user=user, password=password, host=host, database=database, port=port, ) return connection self._connect: Final = connect # self.cursor: mariadb.Cursor = connection.cursor() @contextmanager def query(self, commit: bool = False) -> Iterator[mariadb.Cursor]: """Query in context.""" connection = self._connect() cursor = connection.cursor() yield cursor if commit: connection.commit() connection.close() def get_custom_fields(self) -> dict[str, int]: """Get a mapping of custom fields.""" query = "SELECT usf_name, usf_id FROM adm_user_fields" results: dict[str, int] = {} with self.query() as cursor: cursor.execute(query) for row in cursor: usf_name, usf_id = row results[str(usf_name)] = int(usf_id) return results def get_user_id_by_field(self, field: int, value: str) -> int | None: """Get user ID by lookup of custom field.""" # SELECT usd_value, usd_usr_id from adm_user_data WHERE usd_usf_id = '11' query = "SELECT usd_usr_id FROM adm_user_data WHERE usd_usf_id = ? AND usd_value = ? LIMIT 1" with self.query() as cursor: cursor.execute(query, (field, value)) result = cursor.fetchone() if result: return int(result[0]) return None def get_adm_user_data(self, user_id: int) -> dict[int, str]: """Get adm user data. Returns a list of tuples of field ID and value. """ query = f"SELECT usd_usf_id, usd_value FROM adm_user_data WHERE usd_usr_id = ?" with self.query() as cursor: cursor.execute(query, (user_id,)) results = {int(usf_id): str(usd_value) for usf_id, usd_value in cursor} return results def create_user_data(self, user_id: int, usf_id: int, usd_value: str) -> None: """Create or update user data.""" query = ( "INSERT INTO adm_user_data (usd_usr_id, usd_usf_id, usd_value) VALUES (?, ?, ?)" " ON DUPLICATE KEY UPDATE usd_value = ?" ) parameters = (user_id, usf_id, usd_value, usd_value) with self.query(True) as cursor: cursor.execute(query, parameters) LOG.debug( "Ran query %s (%r), last insert ID: %s", query, parameters, cursor.lastrowid, ) def get_roles(self) -> dict[int, str]: """Get roles. dict int for role ID, str for role name. """ query = "SELECT rol_id, rol_name FROM adm_roles" with self.query() as cursor: cursor.execute(query) result = {int(rol_id): str(rol_name) for (rol_id, rol_name) in cursor} return result def get_user_roles(self, user_id: int) -> list[int]: """Get Role ID for a user""" query = "SELECT mem_rol_id FROM adm_members WHERE mem_usr_id ?" with self.query() as cursor: cursor.execute(query, (user_id,)) result = [int(mem_rol_id) for mem_rol_id in cursor] return result def get_role_payments(self) -> dict[int, int]: """Get payment fees for all roles.""" query = "SELECT rol_id, rol_cost FROM adm_roles" role_fees: dict[int, int] = {} with self.query() as cursor: cursor.execute(query) for role_id, role_cost in cursor: if role_cost is not None: role_fees[int(role_id)] = role_cost return role_fees