diff --git a/curr.txt b/curr.txt deleted file mode 100644 index e69de29..0000000 diff --git a/database_testing.py b/database_testing.py deleted file mode 100644 index 7e6cdcb..0000000 --- a/database_testing.py +++ /dev/null @@ -1,18 +0,0 @@ -from src.backend.database import Database -from src.logic.dataclass import ApparatData - -apparat = ApparatData() -apparat.appname = "testapparat123" -apparat.appnr = 155 -apparat.dauerapp = True -apparat.profname = "Mustermanns, Max" -apparat.subject = "Physik" -apparat.semester = "SoSe 2021" - - -files = {"name": "test.png", "type": "png", "path": r"C:\Users\aky547\Desktop\test.png"} -db = Database() -# print(db.recreate_file("testfile.pdf",files,3)) -# db.insert_file(files,3) -# recreate_file("test.pdf",files,1))#insert_file(files,1)) -db.get_apparats_name(70) diff --git a/db_testing.py b/db_testing.py deleted file mode 100644 index 4d963d3..0000000 --- a/db_testing.py +++ /dev/null @@ -1,45 +0,0 @@ -from codebase import Database -from codebase.pickles import load_pickle, make_pickle -from omegaconf import OmegaConf -from webrequest import BibTextTransformer, WebRequest - -config = OmegaConf.load("config.yaml") -db = Database() -# # # f = db.get_media(1, 1) -# # # dataclass_objects = [] - -# # # for dataclass_str in f: -# # # print(f"dataclass {dataclass_str}") -# # # # dataclass_obj = ast.literal_eval(dataclass_str[0]) -# # # dataclass_objects.append(dataclass_str) - -# # # cla = BookData().from_string(dataclass_objects[0]) -# # # print(type(cla)) -# # book = ( -# # BibTextTransformer("ARRAY") -# # .get_data(WebRequest().get_ppn("ST 250 U42 (15)").get_data()) -# # .return_data() -# # ) -# # print(book) - -# # bpickle = make_pickle(book) -# # print(bpickle) - -# # print(load_pickle(bpickle)) - - -# # # print(pickle.dumps(book), type(pickle.dumps(book))) - -# # # db.add_medium(book, "2", "1") -# # # db.get_app_data("1", "Testapparat") - -# # books = db.get_media(1, 1, 0) - -# # print(len(books)) -# book = db.get_specific_book(16) - -# print(book) - - -if __name__ == "__main__": - print(db.get_media(15, 2)) diff --git a/dbfunctions b/dbfunctions deleted file mode 100644 index 1ad65f3..0000000 Binary files a/dbfunctions and /dev/null differ diff --git a/docs - Kopie/database.html b/docs - Kopie/database.html deleted file mode 100644 index b3ff3a4..0000000 --- a/docs - Kopie/database.html +++ /dev/null @@ -1,4266 +0,0 @@ - - - - - - -database API documentation - - - - - - - - - - - -
-
-
-

Module database

-
-
-
- -Expand source code - -
import datetime
-import os
-import re
-import sqlite3 as sql
-import tempfile
-from src.logic.log import MyLogger
-#from icecream import ic
-from typing import List, Tuple, Dict, Any, Optional, Union
-from pathlib import Path
-from omegaconf import OmegaConf
-from src.backend.db import CREATE_TABLE_APPARAT, CREATE_TABLE_MESSAGES, CREATE_TABLE_MEDIA, CREATE_TABLE_APPKONTOS, CREATE_TABLE_FILES, CREATE_TABLE_PROF, CREATE_TABLE_USER, CREATE_TABLE_SUBJECTS
-from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
-from src.logic.dataclass import ApparatData, BookData
-from src.errors import NoResultError, AppPresentError
-from src.utils import load_pickle, dump_pickle,create_blob
-config = OmegaConf.load("config.yaml")
-logger = MyLogger(__name__)
-
-
-class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        #ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        #ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id:Union[str,int]):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-        """Instert a list of files into the database
-
-        Args:
-            file (list[dict]): a list containing all the files to be inserted
-            Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-            app_id (int): the id of the apparat
-            prof_id (str): the id of the professor
-        """
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-        """Recreate a file from the database
-
-        Args:
-            filename (str): the name of the file
-            app_id (Union[str,int]): the id of the apparat
-            filetype (str): the extension of the file to be created
-
-        Returns:
-            str: The filename of the recreated file 
-        """
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-        """Get all the files associated with the apparat and the professor
-
-        Args:
-            app_id (Union[str,int]): The id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-        """
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self)->list[str]:
-        """Return all the unique semesters in the database
-
-        Returns:
-            list: a list of strings containing the semesters
-        """
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        """Get all the subjects in the database
-
-        Returns:
-            list[tuple]: a list of tuples containing the subjects
-        """
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-        """add a Message to the database
-
-        Args:
-            message (dict): the message to be added
-            user (str): the user who added the message
-            app_id (Union[str,int]): the id of the apparat
-        """
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-    def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-        """Get all the messages for a specific date
-
-        Args:
-            date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-        
-        Returns:
-            list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-        """
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        """Delete a message from the database
-
-        Args:
-            message_id (str): the id of the message
-        """
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-        """Get a professor name based on the id
-
-        Args:
-            prof_id (Union[str,int]): The id of the professor
-            add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-        Returns:
-            str: The name of the professor
-        """
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:Union[str,int])->str:
-        """get the title of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-        """
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str)->tuple:
-        """get all the data of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            tuple: the data of the professor
-        """
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str)->Optional[int]:
-        """Get the id of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            Optional[int]: the id of the professor, if the professor is not found, None is returned
-        """
-        
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-        """A customisable function to get specific data of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-            fields (List[str]): a list of fields to be returned
-
-        Returns:
-            tuple: a tuple containing the requested data
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        """Get mail, telephone number and title of a professor based on the name
-
-        Args:
-            profname (str): name of the professor
-
-        Returns:
-            tuple: the mail, telephone number and title of the professor
-        """
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        """Create a professor in the database
-
-        Args:
-            prof_details (dict): a dictionary containing the details of the professor
-        """
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self)->list[tuple]:
-        """Return all the professors in the database
-
-        Returns:
-            list[tuple]: a list containing all the professors in individual tuples
-        """
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0)->list[tuple]:
-        """Get all the apparats in the database
-
-        Args:
-            deleted (int, optional): Switch the result to use . Defaults to 0.
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-        """Get the Apparat data based on the apparat number and the name
-
-        Args:
-            appnr (str): the apparat number
-            appname (str): the name of the apparat
-
-        Raises:
-            NoResultError: an error is raised if no result is found
-
-        Returns:
-            ApparatData: the appended data of the apparat wrapped in an ApparatData object
-        """
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """Get a list of all the apparat numbers in the database that are currently in use
-
-        Returns:
-            List[int]: the list of used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-        """Set the new semester date for an apparat
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            newDate (str): the new date
-            dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-        """
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-    def getApparatId(self, apparat_name)->Optional[int]:
-        """get the id of an apparat based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-        Returns:
-            Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-        """
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->int:
-        """create the apparat in the database
-
-        Args:
-            apparat (ApparatData): the wrapped metadata of the apparat
-
-        Raises:
-            AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-        Returns:
-            Optional[int]: the id of the apparat
-        """
-                
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            raise AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        #ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-        """Get all apparats based on the professor id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict[list]:
-        """get all apparats based on the semester
-
-        Args:
-            semester (str): the selected semester
-
-        Returns:
-            dict[list]: a list off all created and deleted apparats for the selected semester
-        """
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        """get a list of all apparats created and deleted by semester
-
-        Returns:
-            tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, app_id:Union[str,int], semester:str):
-        """Delete an apparat from the database
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-            semester (str): the semester the apparat should be deleted from
-        """
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-    def isEternal(self, id):
-        """check if the apparat is eternal (dauerapparat)
-
-        Args:
-            id (int): the id of the apparat to be checked
-
-        Returns:
-            int: the state of the apparat
-        """
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-        """get the name of the apparat based on the id
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the name of the apparat
-        """
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        """Update an apparat in the database
-
-        Args:
-            apparat_data (ApparatData): the new metadata of the apparat
-        """
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name:str):
-        """check if the apparat is already present in the database based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-        """a check to see if the apparat is already present in the database, based on the id
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        """Take n amount of kwargs and return the result of the query
-        """
-        def __query(query):
-            """execute the query and return the result
-
-            Args:
-                query (str): the constructed query
-
-            Returns:
-                list: the result of the query
-            """
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        """Get a single user from the database"""
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self)->list[tuple]:
-        """Return a list of tuples of all the users in the database"""
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        """try to login the user.
-        The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-        Args:
-            user (str): username that tries to login
-            hashed_password (str): the password the user tries to login with
-
-        Returns:
-            bool: True if the login was successful, False if not
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        """change the password of a user.
-        The password will be added with the salt and then committed to the database
-
-        Args:
-            user (str): username
-            new_password (str): the hashed password
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        """get the role of the user
-
-        Args:
-            user (str): username
-
-        Returns:
-            str: the name of the role
-        """
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self)->list[tuple]:
-        """get all the roles in the database
-
-        Returns:
-            list[str]: a list of all the roles
-        """
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user)->bool:
-        """a check to see if the username is already present in the database
-
-        Args:
-            user (str): the username
-
-        Returns:
-            bool: True if the username is present, False if not
-        """
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """create an user from the AdminCommands class.
-
-        Args:
-            user (str): the username of the user
-            password (str): a hashed password
-            role (str): the role of the user
-            salt (str): a salt for the password
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        """delete an unser
-
-        Args:
-            user (str): username of the user
-        """
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        """changge the data of a user
-
-        Args:
-            username (str): the username of the user
-            data (dict[str, str]): the data to be changed
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str)->tuple:
-        """get a faculty member based on the name
-
-        Args:
-            name (str): the name to be searched for
-
-        Returns:
-            tuple: a tuple containing the data of the faculty member
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-        """update the data of a faculty member
-
-        Args:
-            data (dict): a dictionary containing the data to be updated
-            oldlname (str): the old last name of the faculty member
-            oldfname (str): the old first name of the faculty member
-        """
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        """get a list of all faculty members
-
-        Returns:
-            list[tuple]: a list of tuples containing the faculty members
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Database -(db_path: str = None) -
-
-

Initialize the database and create the tables if they do not exist.

-

Default constructor for the database class

-

Args

-
-
db_path : str, optional
-
Optional Path for testing / specific purposes. Defaults to None.
-
-
- -Expand source code - -
class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        #ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        #ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id:Union[str,int]):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-        """Instert a list of files into the database
-
-        Args:
-            file (list[dict]): a list containing all the files to be inserted
-            Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-            app_id (int): the id of the apparat
-            prof_id (str): the id of the professor
-        """
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-        """Recreate a file from the database
-
-        Args:
-            filename (str): the name of the file
-            app_id (Union[str,int]): the id of the apparat
-            filetype (str): the extension of the file to be created
-
-        Returns:
-            str: The filename of the recreated file 
-        """
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-        """Get all the files associated with the apparat and the professor
-
-        Args:
-            app_id (Union[str,int]): The id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-        """
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self)->list[str]:
-        """Return all the unique semesters in the database
-
-        Returns:
-            list: a list of strings containing the semesters
-        """
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        """Get all the subjects in the database
-
-        Returns:
-            list[tuple]: a list of tuples containing the subjects
-        """
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-        """add a Message to the database
-
-        Args:
-            message (dict): the message to be added
-            user (str): the user who added the message
-            app_id (Union[str,int]): the id of the apparat
-        """
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-    def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-        """Get all the messages for a specific date
-
-        Args:
-            date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-        
-        Returns:
-            list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-        """
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        """Delete a message from the database
-
-        Args:
-            message_id (str): the id of the message
-        """
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-        """Get a professor name based on the id
-
-        Args:
-            prof_id (Union[str,int]): The id of the professor
-            add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-        Returns:
-            str: The name of the professor
-        """
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:Union[str,int])->str:
-        """get the title of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-        """
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str)->tuple:
-        """get all the data of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            tuple: the data of the professor
-        """
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str)->Optional[int]:
-        """Get the id of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            Optional[int]: the id of the professor, if the professor is not found, None is returned
-        """
-        
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-        """A customisable function to get specific data of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-            fields (List[str]): a list of fields to be returned
-
-        Returns:
-            tuple: a tuple containing the requested data
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        """Get mail, telephone number and title of a professor based on the name
-
-        Args:
-            profname (str): name of the professor
-
-        Returns:
-            tuple: the mail, telephone number and title of the professor
-        """
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        """Create a professor in the database
-
-        Args:
-            prof_details (dict): a dictionary containing the details of the professor
-        """
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self)->list[tuple]:
-        """Return all the professors in the database
-
-        Returns:
-            list[tuple]: a list containing all the professors in individual tuples
-        """
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0)->list[tuple]:
-        """Get all the apparats in the database
-
-        Args:
-            deleted (int, optional): Switch the result to use . Defaults to 0.
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-        """Get the Apparat data based on the apparat number and the name
-
-        Args:
-            appnr (str): the apparat number
-            appname (str): the name of the apparat
-
-        Raises:
-            NoResultError: an error is raised if no result is found
-
-        Returns:
-            ApparatData: the appended data of the apparat wrapped in an ApparatData object
-        """
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """Get a list of all the apparat numbers in the database that are currently in use
-
-        Returns:
-            List[int]: the list of used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-        """Set the new semester date for an apparat
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            newDate (str): the new date
-            dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-        """
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-    def getApparatId(self, apparat_name)->Optional[int]:
-        """get the id of an apparat based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-        Returns:
-            Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-        """
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->int:
-        """create the apparat in the database
-
-        Args:
-            apparat (ApparatData): the wrapped metadata of the apparat
-
-        Raises:
-            AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-        Returns:
-            Optional[int]: the id of the apparat
-        """
-                
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            raise AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        #ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-        """Get all apparats based on the professor id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict[list]:
-        """get all apparats based on the semester
-
-        Args:
-            semester (str): the selected semester
-
-        Returns:
-            dict[list]: a list off all created and deleted apparats for the selected semester
-        """
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        """get a list of all apparats created and deleted by semester
-
-        Returns:
-            tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, app_id:Union[str,int], semester:str):
-        """Delete an apparat from the database
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-            semester (str): the semester the apparat should be deleted from
-        """
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-    def isEternal(self, id):
-        """check if the apparat is eternal (dauerapparat)
-
-        Args:
-            id (int): the id of the apparat to be checked
-
-        Returns:
-            int: the state of the apparat
-        """
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-        """get the name of the apparat based on the id
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the name of the apparat
-        """
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        """Update an apparat in the database
-
-        Args:
-            apparat_data (ApparatData): the new metadata of the apparat
-        """
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name:str):
-        """check if the apparat is already present in the database based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-        """a check to see if the apparat is already present in the database, based on the id
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        """Take n amount of kwargs and return the result of the query
-        """
-        def __query(query):
-            """execute the query and return the result
-
-            Args:
-                query (str): the constructed query
-
-            Returns:
-                list: the result of the query
-            """
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        """Get a single user from the database"""
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self)->list[tuple]:
-        """Return a list of tuples of all the users in the database"""
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        """try to login the user.
-        The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-        Args:
-            user (str): username that tries to login
-            hashed_password (str): the password the user tries to login with
-
-        Returns:
-            bool: True if the login was successful, False if not
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        """change the password of a user.
-        The password will be added with the salt and then committed to the database
-
-        Args:
-            user (str): username
-            new_password (str): the hashed password
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        """get the role of the user
-
-        Args:
-            user (str): username
-
-        Returns:
-            str: the name of the role
-        """
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self)->list[tuple]:
-        """get all the roles in the database
-
-        Returns:
-            list[str]: a list of all the roles
-        """
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user)->bool:
-        """a check to see if the username is already present in the database
-
-        Args:
-            user (str): the username
-
-        Returns:
-            bool: True if the username is present, False if not
-        """
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """create an user from the AdminCommands class.
-
-        Args:
-            user (str): the username of the user
-            password (str): a hashed password
-            role (str): the role of the user
-            salt (str): a salt for the password
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        """delete an unser
-
-        Args:
-            user (str): username of the user
-        """
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        """changge the data of a user
-
-        Args:
-            username (str): the username of the user
-            data (dict[str, str]): the data to be changed
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str)->tuple:
-        """get a faculty member based on the name
-
-        Args:
-            name (str): the name to be searched for
-
-        Returns:
-            tuple: a tuple containing the data of the faculty member
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-        """update the data of a faculty member
-
-        Args:
-            data (dict): a dictionary containing the data to be updated
-            oldlname (str): the old last name of the faculty member
-            oldfname (str): the old first name of the faculty member
-        """
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        """get a list of all faculty members
-
-        Returns:
-            list[tuple]: a list of tuples containing the faculty members
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-

Methods

-
-
-def addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.

-

Args

-
-
bookdata : BookData
-
The metadata of the book to be added
-
app_id : str
-
The apparat id where the book should be added to
-
prof_id : str
-
The id of the professor where the book should be added to.
-
-
- -Expand source code - -
def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-    """
-    Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-    Args:
-        bookdata (BookData): The metadata of the book to be added
-        app_id (str): The apparat id where the book should be added to
-        prof_id (str): The id of the professor where the book should be added to.
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    t_query = (
-        f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-    )
-    # print(t_query)
-    result = cursor.execute(t_query).fetchall()
-    result = [load_pickle(i[0]) for i in result]
-    if bookdata in result:
-        print("Bookdata already in database")
-        # check if the book was deleted in the apparat
-        query = (
-            "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-        )
-        params = (app_id, prof_id, dump_pickle(bookdata))
-        result = cursor.execute(query, params).fetchone()
-        if result[0] == 1:
-            print("Book was deleted, updating bookdata")
-            query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            cursor.execute(query, params)
-            conn.commit()
-        return
-
-    query = (
-        "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-    )
-    converted = dump_pickle(bookdata)
-    params = (converted, app_id, prof_id, 0)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def addMessage(self, message: dict, user: str, app_id: Union[str, int]) -
-
-

add a Message to the database

-

Args

-
-
message : dict
-
the message to be added
-
user : str
-
the user who added the message
-
app_id : Union[str,int]
-
the id of the apparat
-
-
- -Expand source code - -
def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-    """add a Message to the database
-
-    Args:
-        message (dict): the message to be added
-        user (str): the user who added the message
-        app_id (Union[str,int]): the id of the apparat
-    """
-    def __getUserId(user):
-        return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-    user_id = __getUserId(user)
-    self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-
-
-
-def changePassword(self, user, new_password) -
-
-

change the password of a user. -The password will be added with the salt and then committed to the database

-

Args

-
-
user : str
-
username
-
new_password : str
-
the hashed password
-
-
- -Expand source code - -
def changePassword(self, user, new_password):
-    """change the password of a user.
-    The password will be added with the salt and then committed to the database
-
-    Args:
-        user (str): username
-        new_password (str): the hashed password
-    """
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    new_password = salt + new_password
-    self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-
-
-
-def checkApparatExists(self, apparat_name: str) -
-
-

check if the apparat is already present in the database based on the name

-

Args

-
-
apparat_name : str
-
the name of the apparat
-
-

Returns

-
-
bool
-
True if the apparat is present, False if not
-
-
- -Expand source code - -
def checkApparatExists(self, apparat_name:str):
-    """check if the apparat is already present in the database based on the name
-
-    Args:
-        apparat_name (str): the name of the apparat
-
-    Returns:
-        bool: True if the apparat is present, False if not
-    """
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-
-
-
-def checkApparatExistsById(self, app_id: Union[str, int]) ‑> bool -
-
-

a check to see if the apparat is already present in the database, based on the id

-

Args

-
-
app_id : Union[str, int]
-
the id of the apparat
-
-

Returns

-
-
bool
-
True if the apparat is present, False if not
-
-
- -Expand source code - -
def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-    """a check to see if the apparat is already present in the database, based on the id
-
-    Args:
-        app_id (Union[str, int]): the id of the apparat
-
-    Returns:
-        bool: True if the apparat is present, False if not
-    """
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-
-
-
-def checkUsername(self, user) ‑> bool -
-
-

a check to see if the username is already present in the database

-

Args

-
-
user : str
-
the username
-
-

Returns

-
-
bool
-
True if the username is present, False if not
-
-
- -Expand source code - -
def checkUsername(self, user)->bool:
-    """a check to see if the username is already present in the database
-
-    Args:
-        user (str): the username
-
-    Returns:
-        bool: True if the username is present, False if not
-    """
-    data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-    return True if data is not None else False
-
-
-
-def close_connection(self, conn: sqlite3.Connection) -
-
-

closes the connection to the database

-

Args:

-
- conn (sql.Connection): the connection to be closed
-
-
- -Expand source code - -
def close_connection(self, conn: sql.Connection):
-    """
-    closes the connection to the database
-    
-    Args:
-    ----
-        - conn (sql.Connection): the connection to be closed
-    """
-    conn.close()
-
-
-
-def connect(self) ‑> sqlite3.Connection -
-
-

Connect to the database

-

Returns

-
-
sql.Connection
-
The active connection to the database
-
-
- -Expand source code - -
def connect(self)->sql.Connection:
-    """
-    Connect to the database
-
-    Returns:
-        sql.Connection: The active connection to the database
-    """
-    return sql.connect(self.db_path)
-
-
-
-def createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> int -
-
-

create the apparat in the database

-

Args

-
-
apparat : ApparatData
-
the wrapped metadata of the apparat
-
-

Raises

-
-
AppPresentError
-
an error describing that the apparats chosen id is already present in the database
-
-

Returns

-
-
Optional[int]
-
the id of the apparat
-
-
- -Expand source code - -
def createApparat(self, apparat:ApparatData)->int:
-    """create the apparat in the database
-
-    Args:
-        apparat (ApparatData): the wrapped metadata of the apparat
-
-    Raises:
-        AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-    Returns:
-        Optional[int]: the id of the apparat
-    """
-            
-    prof_id = self.getProfId(apparat.profname)
-    app_id = self.getApparatId(apparat.appname)
-    if app_id:
-        raise AppPresentError(app_id)
-
-    self.createProf(apparat.get_prof_details())
-    prof_id = self.getProfId(apparat.profname)
-    #ic(prof_id)
-    query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-    logger.log_info(query)
-    self.query_db(query)
-    return self.getApparatId(apparat.appname)
-
-
-
-def createProf(self, prof_details: dict) -
-
-

Create a professor in the database

-

Args

-
-
prof_details : dict
-
a dictionary containing the details of the professor
-
-
- -Expand source code - -
def createProf(self, prof_details:dict):
-    """Create a professor in the database
-
-    Args:
-        prof_details (dict): a dictionary containing the details of the professor
-    """
-    prof_title = prof_details["prof_title"]
-    prof_fname = prof_details["profname"].split(",")[1]
-    prof_fname = prof_fname.strip()
-    prof_lname = prof_details["profname"].split(",")[0]
-    prof_lname = prof_lname.strip()
-    prof_fullname = prof_details["profname"].replace(",", "")
-    prof_mail = prof_details["prof_mail"]
-    prof_tel = prof_details["prof_tel"]
-    params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-    query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-    self.insertInto(query=query, params=params)
-
-
-
-def createUser(self, user, password, role, salt) -
-
-

create an user from the AdminCommands class.

-

Args

-
-
user : str
-
the username of the user
-
password : str
-
a hashed password
-
role : str
-
the role of the user
-
salt : str
-
a salt for the password
-
-
- -Expand source code - -
def createUser(self, user, password, role, salt):
-    """create an user from the AdminCommands class.
-
-    Args:
-        user (str): the username of the user
-        password (str): a hashed password
-        role (str): the role of the user
-        salt (str): a salt for the password
-    """
-    self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-
-
-
-def create_tables(self) -
-
-

Create the tables in the database

-
- -Expand source code - -
def create_tables(self):
-    """
-    Create the tables in the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    cursor.execute(CREATE_TABLE_APPARAT)
-    cursor.execute(CREATE_TABLE_MESSAGES)
-    cursor.execute(CREATE_TABLE_MEDIA)
-    cursor.execute(CREATE_TABLE_APPKONTOS)
-    cursor.execute(CREATE_TABLE_FILES)
-    cursor.execute(CREATE_TABLE_PROF)
-    cursor.execute(CREATE_TABLE_USER)
-    cursor.execute(CREATE_TABLE_SUBJECTS)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def deleteApparat(self, app_id: Union[str, int], semester: str) -
-
-

Delete an apparat from the database

-

Args

-
-
app_id : Union[str, int]
-
the id of the apparat
-
semester : str
-
the semester the apparat should be deleted from
-
-
- -Expand source code - -
def deleteApparat(self, app_id:Union[str,int], semester:str):
-    """Delete an apparat from the database
-
-    Args:
-        app_id (Union[str, int]): the id of the apparat
-        semester (str): the semester the apparat should be deleted from
-    """
-    self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-
-
-
-def deleteBook(self, book_id) -
-
-

Delete a book from the database

-

Args

-
-
book_id : str
-
ID of the book
-
-
- -Expand source code - -
def deleteBook(self, book_id):
-    """
-    Delete a book from the database
-
-    Args:
-        book_id (str): ID of the book
-    """
-    self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-
-
-def deleteMessage(self, message_id) -
-
-

Delete a message from the database

-

Args

-
-
message_id : str
-
the id of the message
-
-
- -Expand source code - -
def deleteMessage(self, message_id):
-    """Delete a message from the database
-
-    Args:
-        message_id (str): the id of the message
-    """
-    self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-
-
-def deleteUser(self, user) -
-
-

delete an unser

-

Args

-
-
user : str
-
username of the user
-
-
- -Expand source code - -
def deleteUser(self, user):
-    """delete an unser
-
-    Args:
-        user (str): username of the user
-    """
-    self.query_db("DELETE FROM user WHERE username=?", (user,))
-
-
-
-def getAllAparats(self, deleted=0) ‑> list[tuple] -
-
-

Get all the apparats in the database

-

Args

-
-
deleted : int, optional
-
Switch the result to use . Defaults to 0.
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the apparats
-
-
- -Expand source code - -
def getAllAparats(self,deleted=0)->list[tuple]:
-    """Get all the apparats in the database
-
-    Args:
-        deleted (int, optional): Switch the result to use . Defaults to 0.
-
-    Returns:
-        list[tuple]: a list of tuples containing the apparats
-    """
-    return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-
-
-
-def getApparatCountBySemester(self) ‑> tuple[list[str], list[int]] -
-
-

get a list of all apparats created and deleted by semester

-

Returns

-
-
tuple[list[str],list[int]]
-
a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-
-
- -Expand source code - -
def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-    """get a list of all apparats created and deleted by semester
-
-    Returns:
-        tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    semesters = self.getSemersters()
-    created = []
-    deleted = []
-    for semester in semesters:
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-        result = cursor.execute(query).fetchone()
-        created.append(result[0])
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-        result = cursor.execute(query).fetchone()
-        deleted.append(result[0])
-    # store data in a tuple
-    ret = []
-    e_tuple = ()
-    for sem in semesters:
-        e_tuple = (
-            sem,
-            created[semesters.index(sem)],
-            deleted[semesters.index(sem)],
-        )
-        ret.append(e_tuple)
-    self.close_connection(conn)
-    return ret 
-
-
-
-def getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData -
-
-

Get the Apparat data based on the apparat number and the name

-

Args

-
-
appnr : str
-
the apparat number
-
appname : str
-
the name of the apparat
-
-

Raises

-
-
NoResultError
-
an error is raised if no result is found
-
-

Returns

-
-
ApparatData
-
the appended data of the apparat wrapped in an ApparatData object
-
-
- -Expand source code - -
def getApparatData(self, appnr, appname)->ApparatData:
-    """Get the Apparat data based on the apparat number and the name
-
-    Args:
-        appnr (str): the apparat number
-        appname (str): the name of the apparat
-
-    Raises:
-        NoResultError: an error is raised if no result is found
-
-    Returns:
-        ApparatData: the appended data of the apparat wrapped in an ApparatData object
-    """
-    result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-    if result is None:
-        raise NoResultError("No result found")
-    apparat = ApparatData()
-    apparat.appname = result[1]
-    apparat.appnr = result[4]
-    apparat.dauerapp = True if result[7] == 1 else False
-    prof_data = self.getProfData(self.getProfNameById(result[2]))
-    apparat.profname = self.getProfNameById(result[2])
-    apparat.prof_mail = prof_data[0]
-    apparat.prof_tel = prof_data[1]
-    apparat.prof_title = prof_data[2]
-    apparat.app_fach = result[3]
-    apparat.erstellsemester = result[5]
-    apparat.semester = result[8]
-    apparat.deleted = result[9]
-    apparat.apparat_adis_id = result[11]
-    apparat.prof_adis_id = result[12]
-    return apparat
-
-
-
-def getApparatId(self, apparat_name) ‑> Optional[int] -
-
-

get the id of an apparat based on the name

-

Args

-
-
apparat_name : str
-
the name of the apparat e.g. "Semesterapparat 1"
-
-

Returns

-
-
Optional[int]
-
the id of the apparat, if the apparat is not found, None is returned
-
-
- -Expand source code - -
def getApparatId(self, apparat_name)->Optional[int]:
-    """get the id of an apparat based on the name
-
-    Args:
-        apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-    Returns:
-        Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-    """
-    data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getApparatName(self, app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

get the name of the apparat based on the id

-

Args

-
-
app_id : Union[str,int]
-
the id of the apparat
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
str
-
the name of the apparat
-
-
- -Expand source code - -
def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-    """get the name of the apparat based on the id
-
-    Args:
-        app_id (Union[str,int]): the id of the apparat
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        str: the name of the apparat
-    """
-    return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-
-
-
-def getApparatsByProf(self, prof_id: Union[str, int]) ‑> list[tuple] -
-
-

Get all apparats based on the professor id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the apparats
-
-
- -Expand source code - -
def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-    """Get all apparats based on the professor id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        list[tuple]: a list of tuples containing the apparats
-    """
-    return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-
-
-
-def getApparatsBySemester(self, semester: str) ‑> dict[list] -
-
-

get all apparats based on the semester

-

Args

-
-
semester : str
-
the selected semester
-
-

Returns

-
-
dict[list]
-
a list off all created and deleted apparats for the selected semester
-
-
- -Expand source code - -
def getApparatsBySemester(self, semester:str)->dict[list]:
-    """get all apparats based on the semester
-
-    Args:
-        semester (str): the selected semester
-
-    Returns:
-        dict[list]: a list off all created and deleted apparats for the selected semester
-    """
-    data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-    conn = self.connect()
-    cursor = conn.cursor()
-    c_tmp = []
-    for i in data:
-        c_tmp.append((i[0], self.getProfNameById(i[1])))
-    query = (
-        f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-    )
-    result = cursor.execute(query).fetchall()
-    d_tmp = []
-    for i in result:
-        d_tmp.append((i[0], self.getProfNameById(i[1])))
-    # group the apparats by prof
-    c_ret = {}
-    for i in c_tmp:
-        if i[1] not in c_ret.keys():
-            c_ret[i[1]] = [i[0]]
-        else:
-            c_ret[i[1]].append(i[0])
-    d_ret = {}
-    for i in d_tmp:
-        if i[1] not in d_ret.keys():
-            d_ret[i[1]] = [i[0]]
-        else:
-            d_ret[i[1]].append(i[0])
-    self.close_connection(conn)
-    return {"created": c_ret, "deleted": d_ret}
-
-
-
-def getBlob(self, filename, app_id: Union[str, int]) -
-
-

Get a blob from the database

-

Args

-
-
filename : str
-
The name of the file
-
app_id : str
-
ID of the apparat
-
-

Returns

-
-
bytes
-
The file stored in
-
-
- -Expand source code - -
def getBlob(self, filename, app_id:Union[str,int]):
-    """
-    Get a blob from the database
-
-    Args:
-        filename (str): The name of the file
-        app_id (str): ID of the apparat
-
-    Returns:
-        bytes: The file stored in 
-    """
-    return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-
-
-
-def getBook(self, book_id: int) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the id in the database

-

Args

-
-
book_id : int
-
The id of the book
-
-

Returns

-
-
BookData
-
The metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBook(self,book_id:int)->BookData:
-    """
-    Get the book based on the id in the database
-
-    Args:
-        book_id (int): The id of the book
-
-    Returns:
-        BookData: The metadata of the book wrapped in a BookData object
-    """
-    return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-
-
-
-def getBookBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
BookData
-
The total metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-    """
-    Get the book based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        BookData: The total metadata of the book wrapped in a BookData object
-    """
-    result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [load_pickle(i[0]) for i in result]
-    book = [i for i in books if i.signature == signature][0]
-    return book
-
-
-
-def getBookId(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) ‑> int -
-
-

Get the id of a book based on the metadata of the book

-

Args

-
-
bookdata : BookData
-
The wrapped metadata of the book
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
-

Returns

-
-
int
-
ID of the book
-
-
- -Expand source code - -
def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-    """
-    Get the id of a book based on the metadata of the book
-
-    Args:
-        bookdata (BookData): The wrapped metadata of the book
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-
-    Returns:
-        int: ID of the book
-    """
-    result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-    return result[0]
-
-
-
-def getBookIdBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> int -
-
-

Get a book id based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
int
-
The id of the book
-
-
- -Expand source code - -
def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-    """
-    Get a book id based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        int: The id of the book
-    """
-    result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [(load_pickle(i[0]),i[1]) for i in result]
-    book = [i for i in books if i[0].signature == signature][0][1]
-    return book
-
-
-
-def getBooks(self, app_id: Union[str, int], prof_id: Union[str, int], deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]] -
-
-

Get the Books based on the apparat id and the professor id

-

Args

-
-
app_id : str
-
The ID of the apparat
-
prof_id : str
-
The ID of the professor
-
deleted : int, optional
-
The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-

Returns

-
-
list[dict[int, BookData, int]]
-
A list of dictionaries containing the id, the metadata of the book and the availability of the book
-
-
- -Expand source code - -
def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-    """
-    Get the Books based on the apparat id and the professor id
-
-    Args:
-        app_id (str): The ID of the apparat
-        prof_id (str): The ID of the professor
-        deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-    Returns:
-        list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-    """
-    qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-    ret_result = []
-    for result_a in qdata:
-        data = {"id": int, "bookdata": BookData, "available": int}
-        data["id"] = result_a[0]
-        data["bookdata"] = load_pickle(result_a[1])
-        data["available"] = result_a[2]
-        ret_result.append(data)
-    return ret_result
-
-
-
-def getFacultyMember(self, name: str) ‑> tuple -
-
-

get a faculty member based on the name

-

Args

-
-
name : str
-
the name to be searched for
-
-

Returns

-
-
tuple
-
a tuple containing the data of the faculty member
-
-
- -Expand source code - -
def getFacultyMember(self, name:str)->tuple:
-    """get a faculty member based on the name
-
-    Args:
-        name (str): the name to be searched for
-
-    Returns:
-        tuple: a tuple containing the data of the faculty member
-    """
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-
-
-
-def getFacultyMembers(self) -
-
-

get a list of all faculty members

-

Returns

-
-
list[tuple]
-
a list of tuples containing the faculty members
-
-
- -Expand source code - -
def getFacultyMembers(self):
-    """get a list of all faculty members
-
-    Returns:
-        list[tuple]: a list of tuples containing the faculty members
-    """
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-def getFiles(self, app_id: Union[str, int], prof_id: int) ‑> list[tuple] -
-
-

Get all the files associated with the apparat and the professor

-

Args

-
-
app_id : Union[str,int]
-
The id of the apparat
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-
-
- -Expand source code - -
def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-    """Get all the files associated with the apparat and the professor
-
-    Args:
-        app_id (Union[str,int]): The id of the apparat
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-    """
-    return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-
-
-def getLastBookId(self) ‑> int -
-
-

Get the last book id in the database

-

Returns

-
-
int
-
ID of the last book in the database
-
-
- -Expand source code - -
def getLastBookId(self)->int:
-    """
-    Get the last book id in the database
-
-    Returns:
-        int: ID of the last book in the database
-    """
-    return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-
-
-
-def getMessages(self, date: str) ‑> list[dict[str, str, str, str]] -
-
-

Get all the messages for a specific date

-

Args

-
-
date : str
-
a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-
-

Returns

-
-
list[dict[str, str, str, str]]
-
a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-
-
- -Expand source code - -
def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-    """Get all the messages for a specific date
-
-    Args:
-        date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-    
-    Returns:
-        list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-    """
-    def __get_user_name(user_id):
-        return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-    messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-    ret = [
-        {
-            "message": i[2],
-            "user": __get_user_name(i[4]),
-            "appnr": i[5],
-            "id": i[0]
-        }
-        for i in messages
-    ]
-    return ret
-
-
-
-def getProfByName(self, prof_name: str) ‑> tuple -
-
-

get all the data of a professor based on the name

-

Args

-
-
prof_name : str
-
the name of the professor
-
-

Returns

-
-
tuple
-
the data of the professor
-
-
- -Expand source code - -
def getProfByName(self, prof_name:str)->tuple:
-    """get all the data of a professor based on the name
-
-    Args:
-        prof_name (str): the name of the professor
-
-    Returns:
-        tuple: the data of the professor
-    """
-    return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-
-
-
-def getProfData(self, profname: str) -
-
-

Get mail, telephone number and title of a professor based on the name

-

Args

-
-
profname : str
-
name of the professor
-
-

Returns

-
-
tuple
-
the mail, telephone number and title of the professor
-
-
- -Expand source code - -
def getProfData(self, profname:str):
-    """Get mail, telephone number and title of a professor based on the name
-
-    Args:
-        profname (str): name of the professor
-
-    Returns:
-        tuple: the mail, telephone number and title of the professor
-    """
-    data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-    return data
-
-
-
-def getProfId(self, prof_name: str) ‑> Optional[int] -
-
-

Get the id of a professor based on the name

-

Args

-
-
prof_name : str
-
the name of the professor
-
-

Returns

-
-
Optional[int]
-
the id of the professor, if the professor is not found, None is returned
-
-
- -Expand source code - -
def getProfId(self, prof_name:str)->Optional[int]:
-    """Get the id of a professor based on the name
-
-    Args:
-        prof_name (str): the name of the professor
-
-    Returns:
-        Optional[int]: the id of the professor, if the professor is not found, None is returned
-    """
-    
-    data = self.getProfByName(prof_name.replace(",", ""))
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getProfNameById(self, prof_id: Union[str, int], add_title: bool = False) ‑> str -
-
-

Get a professor name based on the id

-

Args

-
-
prof_id : Union[str,int]
-
The id of the professor
-
add_title : bool, optional
-
wether to add the title or no. Defaults to False.
-
-

Returns

-
-
str
-
The name of the professor
-
-
- -Expand source code - -
def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-    """Get a professor name based on the id
-
-    Args:
-        prof_id (Union[str,int]): The id of the professor
-        add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-    Returns:
-        str: The name of the professor
-    """
-    prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-    if add_title:
-        return f"{self.getTitleById(prof_id)}{prof[0]}"
-    else:
-        return prof[0]
-
-
-
-def getProfs(self) ‑> list[tuple] -
-
-

Return all the professors in the database

-

Returns

-
-
list[tuple]
-
a list containing all the professors in individual tuples
-
-
- -Expand source code - -
def getProfs(self)->list[tuple]:
-    """Return all the professors in the database
-
-    Returns:
-        list[tuple]: a list containing all the professors in individual tuples
-    """
-    return self.query_db("SELECT * FROM prof")
-
-
-
-def getRole(self, user) -
-
-

get the role of the user

-

Args

-
-
user : str
-
username
-
-

Returns

-
-
str
-
the name of the role
-
-
- -Expand source code - -
def getRole(self, user):
-    """get the role of the user
-
-    Args:
-        user (str): username
-
-    Returns:
-        str: the name of the role
-    """
-    return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-
-
-
-def getRoles(self) ‑> list[tuple] -
-
-

get all the roles in the database

-

Returns

-
-
list[str]
-
a list of all the roles
-
-
- -Expand source code - -
def getRoles(self)->list[tuple]:
-    """get all the roles in the database
-
-    Returns:
-        list[str]: a list of all the roles
-    """
-    return self.query_db("SELECT role FROM user")
-
-
-
-def getSemersters(self) ‑> list[str] -
-
-

Return all the unique semesters in the database

-

Returns

-
-
list
-
a list of strings containing the semesters
-
-
- -Expand source code - -
def getSemersters(self)->list[str]:
-    """Return all the unique semesters in the database
-
-    Returns:
-        list: a list of strings containing the semesters
-    """
-    data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-    return [i[0] for i in data]
-
-
-
-def getSpecificProfData(self, prof_id: Union[str, int], fields: List[str]) ‑> tuple -
-
-

A customisable function to get specific data of a professor based on the id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
fields : List[str]
-
a list of fields to be returned
-
-

Returns

-
-
tuple
-
a tuple containing the requested data
-
-
- -Expand source code - -
def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-    """A customisable function to get specific data of a professor based on the id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-        fields (List[str]): a list of fields to be returned
-
-    Returns:
-        tuple: a tuple containing the requested data
-    """
-    query = "SELECT "
-    for field in fields:
-        query += f"{field},"
-    query = query[:-1]
-    query += " FROM prof WHERE id=?"
-    return self.query_db(query, (prof_id,), one=True)[0]
-
-
-
-def getSubjects(self) -
-
-

Get all the subjects in the database

-

Returns

-
-
list[tuple]
-
a list of tuples containing the subjects
-
-
- -Expand source code - -
def getSubjects(self):
-    """Get all the subjects in the database
-
-    Returns:
-        list[tuple]: a list of tuples containing the subjects
-    """
-    return self.query_db("SELECT * FROM subjects")
-
-
-
-def getTitleById(self, prof_id: Union[str, int]) ‑> str -
-
-

get the title of a professor based on the id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
str
-
the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-
-
- -Expand source code - -
def getTitleById(self, prof_id:Union[str,int])->str:
-    """get the title of a professor based on the id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-    """
-    title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-    return f"{title} " if title is not None else ""
-
-
-
-def getUnavailableApparatNumbers(self) ‑> List[int] -
-
-

Get a list of all the apparat numbers in the database that are currently in use

-

Returns

-
-
List[int]
-
the list of used apparat numbers
-
-
- -Expand source code - -
def getUnavailableApparatNumbers(self)->List[int]:
-    """Get a list of all the apparat numbers in the database that are currently in use
-
-    Returns:
-        List[int]: the list of used apparat numbers
-    """
-    numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-    numbers = [i[0] for i in numbers]
-    logger.log_info(f"Currently used apparat numbers: {numbers}")
-    return numbers
-
-
-
-def getUser(self) -
-
-

Get a single user from the database

-
- -Expand source code - -
def getUser(self):
-    """Get a single user from the database"""
-    return self.query_db("SELECT * FROM user", one=True)
-
-
-
-def getUsers(self) ‑> list[tuple] -
-
-

Return a list of tuples of all the users in the database

-
- -Expand source code - -
def getUsers(self)->list[tuple]:
-    """Return a list of tuples of all the users in the database"""
-    return self.query_db("SELECT * FROM user")
-
-
-
-def get_db_contents(self) ‑> Optional[List[Tuple]] -
-
-

Get the contents of the

-

Returns

-
-
Union[List[Tuple], None]
-
description
-
-
- -Expand source code - -
def get_db_contents(self)->Union[List[Tuple], None]:
-    """
-    Get the contents of the 
-
-    Returns:
-        Union[List[Tuple], None]: _description_
-    """
-    try:
-        with sql.connect(self.db_path) as conn:
-            cursor = conn.cursor()
-            cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-            return cursor.fetchall()
-    except sql.OperationalError:
-        return None
-
-
-
-def insertFile(self, file: list[dict], app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

Instert a list of files into the database

-

Args

-
-
file : list[dict]
-
a list containing all the files to be inserted
-
Structured
-
[{"name": "filename", "path": "path", "type": "filetype"}]
-
app_id : int
-
the id of the apparat
-
prof_id : str
-
the id of the professor
-
-
- -Expand source code - -
def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-    """Instert a list of files into the database
-
-    Args:
-        file (list[dict]): a list containing all the files to be inserted
-        Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-        app_id (int): the id of the apparat
-        prof_id (str): the id of the professor
-    """
-    for f in file:
-        filename = f["name"]
-        path = f["path"]
-        filetyp = f["type"]
-        if path == "Database":
-            continue
-        blob = create_blob(path)
-        query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-        self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-
-
-
-def insertInto(self, query: str, params: Tuple) ‑> None -
-
-

Insert sent data into the database

-

Args

-
-
query : str
-
The query to be executed
-
params : Tuple
-
the parameters to be inserted into the database
-
-
- -Expand source code - -
def insertInto(self, query:str, params:Tuple) -> None:
-    """
-    Insert sent data into the database
-
-    Args:
-        query (str): The query to be executed
-        params (Tuple): the parameters to be inserted into the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Inserting {params} into database with query {query}")
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def isEternal(self, id) -
-
-

check if the apparat is eternal (dauerapparat)

-

Args

-
-
id : int
-
the id of the apparat to be checked
-
-

Returns

-
-
int
-
the state of the apparat
-
-
- -Expand source code - -
def isEternal(self, id):
-    """check if the apparat is eternal (dauerapparat)
-
-    Args:
-        id (int): the id of the apparat to be checked
-
-    Returns:
-        int: the state of the apparat
-    """
-    return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-
-
-
-def login(self, user, hashed_password) -
-
-

try to login the user. -The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database

-

Args

-
-
user : str
-
username that tries to login
-
hashed_password : str
-
the password the user tries to login with
-
-

Returns

-
-
bool
-
True if the login was successful, False if not
-
-
- -Expand source code - -
def login(self, user, hashed_password):
-    """try to login the user.
-    The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-    Args:
-        user (str): username that tries to login
-        hashed_password (str): the password the user tries to login with
-
-    Returns:
-        bool: True if the login was successful, False if not
-    """
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    if salt is None:
-        return False
-    hashed_password = salt + hashed_password
-    password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-    if password == hashed_password:
-        return True
-    else:
-        return False
-
-
-
-def query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]] -
-
-

Query the Database for the sent query.

-

Args

-
-
query : str
-
The query to be executed
-
args : Tuple, optional
-
The arguments for the query. Defaults to ().
-
one : bool, optional
-
Return the first result only. Defaults to False.
-
-

Returns

-

Union[Typle|List[Tuple]]: Returns the result of the query

-
- -Expand source code - -
def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-    """
-    Query the Database for the sent query.
-
-    Args:
-        query (str): The query to be executed
-        args (Tuple, optional): The arguments for the query. Defaults to ().
-        one (bool, optional): Return the first result only. Defaults to False.
-
-    Returns:
-        Union[Typle|List[Tuple]]: Returns the result of the query
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Querying database with query {query}, args: {args}")
-    cursor.execute(query, args)
-    rv = cursor.fetchall()
-    conn.commit()
-    self.close_connection(conn)
-    return (rv[0] if rv else None) if one else rv
-
-
-
-def recreateFile(self, filename: str, app_id: Union[str, int], filetype: str) ‑> str -
-
-

Recreate a file from the database

-

Args

-
-
filename : str
-
the name of the file
-
app_id : Union[str,int]
-
the id of the apparat
-
filetype : str
-
the extension of the file to be created
-
-

Returns

-
-
str
-
The filename of the recreated file
-
-
- -Expand source code - -
def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-    """Recreate a file from the database
-
-    Args:
-        filename (str): the name of the file
-        app_id (Union[str,int]): the id of the apparat
-        filetype (str): the extension of the file to be created
-
-    Returns:
-        str: The filename of the recreated file 
-    """
-    blob = self.getBlob(filename, app_id)
-    tempdir = config.database.tempdir
-    tempdir = tempdir.replace("~", str(Path.home()))
-    tempdir_path = Path(tempdir)        
-    if not os.path.exists(tempdir_path):
-        os.mkdir(tempdir_path)
-    file = tempfile.NamedTemporaryFile(
-        delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-    )
-    file.write(blob)
-    print("file created")
-    return file.name
-
-
-
-def searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]] -
-
-

Search a book in the database based on the sent data.

-

Args

-
-
data : dict[str, str]
-
A dictionary containing the data to be searched for. The dictionary can contain the following:
-
-
    -
  • signature: The signature of the book
  • -
  • title: The title of the book
  • -
-

Returns

-
-
list[tuple[BookData, int]]
-
A list of tuples containing the wrapped Metadata and the id of the book
-
-
- -Expand source code - -
def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-    """
-    Search a book in the database based on the sent data.
-
-    Args:
-        data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-        - signature: The signature of the book
-        - title: The title of the book
-
-    Returns:
-        list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-    """
-    rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-    #ic(rdata, len(rdata))
-    mode = 0
-    if len(data)== 1:
-        if "signature" in data.keys():
-            mode = 1
-        elif "title" in data.keys():
-            mode = 2
-    elif len(data) == 2:
-        mode = 3
-    else:
-        return None
-    ret = []
-    for book in rdata:
-        bookdata = load_pickle(book[1])
-        app_id = book[2]
-        prof_id = book[3]
-        if mode == 1:
-            if data["signature"] in bookdata.signature:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 2:
-            if data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 3:
-            if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-    #ic(ret)
-    return ret
-
-
-
-def setAvailability(self, book_id: str, available: str) -
-
-

Set the availability of a book in the database

-

Args

-
-
book_id : str
-
The id of the book
-
available : str
-
The availability of the book
-
-
- -Expand source code - -
def setAvailability(self, book_id:str, available:str):
-    """
-    Set the availability of a book in the database
-
-    Args:
-        book_id (str): The id of the book
-        available (str): The availability of the book
-    """
-    self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-
-
-
-def setNewSemesterDate(self, app_id: Union[str, int], newDate, dauerapp=False) -
-
-

Set the new semester date for an apparat

-

Args

-
-
app_id : Union[str,int]
-
the id of the apparat
-
newDate : str
-
the new date
-
dauerapp : bool, optional
-
if the apparat was changed to dauerapparat. Defaults to False.
-
-
- -Expand source code - -
def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-    """Set the new semester date for an apparat
-
-    Args:
-        app_id (Union[str,int]): the id of the apparat
-        newDate (str): the new date
-        dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-    """
-    date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-    if dauerapp:
-        self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-    else:
-        self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-
-
-
-def statistic_request(self, **kwargs: Any) -
-
-

Take n amount of kwargs and return the result of the query

-
- -Expand source code - -
def statistic_request(self, **kwargs: Any):
-    """Take n amount of kwargs and return the result of the query
-    """
-    def __query(query):
-        """execute the query and return the result
-
-        Args:
-            query (str): the constructed query
-
-        Returns:
-            list: the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        result = cursor.execute(query).fetchall()
-        for result_a in result:
-            orig_value = result_a
-            prof_name = self.getProfNameById(result_a[2])
-            # replace the prof_id with the prof_name
-            result_a = list(result_a)
-            result_a[2] = prof_name
-            result_a = tuple(result_a)
-            result[result.index(orig_value)] = result_a
-        self.close_connection(conn)
-        return result
-    if "deletable" in kwargs.keys():
-        query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-        return __query(query)
-    if "dauer" in kwargs.keys():
-        kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-    query = "SELECT * FROM semesterapparat WHERE "
-    for key, value in kwargs.items() if kwargs.items() is not None else {}:
-        print(key, value)
-        query += f"{key}='{value}' AND "
-        print(query)
-    # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-    if "deletesemester" in kwargs.keys():
-        query = query.replace(
-            f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-        )
-    if "endsemester" in kwargs.keys():
-        if "erstellsemester" in kwargs.keys():
-            query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-            query = query.replace(
-                f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-            )
-        else:
-            query = query.replace(
-                f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-            )
-            print("replaced")
-        query = query.replace(
-            "xyz",
-            f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-        )
-    # remove all x="" parts from the query where x is a key in kwargs
-    query = query[:-5]
-    print(query)
-    return __query(query)
-
-
-
-def updateApparat(self, apparat_data: src.logic.dataclass.ApparatData) -
-
-

Update an apparat in the database

-

Args

-
-
apparat_data : ApparatData
-
the new metadata of the apparat
-
-
- -Expand source code - -
def updateApparat(self, apparat_data:ApparatData):
-    """Update an apparat in the database
-
-    Args:
-        apparat_data (ApparatData): the new metadata of the apparat
-    """
-    query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-    params = (
-        apparat_data.appname,
-        apparat_data.app_fach,
-        apparat_data.dauerapp,
-        self.getProfId(apparat_data.profname),
-        apparat_data.appnr,        
-    )
-    self.query_db(query, params)
-
-
-
-def updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData) -
-
-

Update the bookdata in the database

-

Args

-
-
book_id : str
-
The id of the book
-
bookdata : BookData
-
The new metadata of the book
-
-
- -Expand source code - -
def updateBookdata(self, book_id, bookdata:BookData):
-    """
-    Update the bookdata in the database
-
-    Args:
-        book_id (str): The id of the book
-        bookdata (BookData): The new metadata of the book
-    """
-    self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-
-
-
-def updateFacultyMember(self, data: dict, oldlname: str, oldfname: str) -
-
-

update the data of a faculty member

-

Args

-
-
data : dict
-
a dictionary containing the data to be updated
-
oldlname : str
-
the old last name of the faculty member
-
oldfname : str
-
the old first name of the faculty member
-
-
- -Expand source code - -
def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-    """update the data of a faculty member
-
-    Args:
-        data (dict): a dictionary containing the data to be updated
-        oldlname (str): the old last name of the faculty member
-        oldfname (str): the old first name of the faculty member
-    """
-    placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-    query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-    data["oldlname"] = oldlname
-    data["oldfname"] = oldfname
-    self.query_db(query, data)
-
-
-
-def updateUser(self, username, data: dict[str, str]) -
-
-

changge the data of a user

-

Args

-
-
username : str
-
the username of the user
-
data : dict[str, str]
-
the data to be changed
-
-
- -Expand source code - -
def updateUser(self, username, data:dict[str, str]):
-    """changge the data of a user
-
-    Args:
-        username (str): the username of the user
-        data (dict[str, str]): the data to be changed
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    query = "UPDATE user SET "
-    for key,value in data.items():
-        if key == "username":
-            continue
-        query += f"{key}='{value}',"
-    query = query[:-1]
-    query += " WHERE username=?"
-    params = (username,)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs - Kopie/database.md b/docs - Kopie/database.md deleted file mode 100644 index c518b09..0000000 --- a/docs - Kopie/database.md +++ /dev/null @@ -1,327 +0,0 @@ -Module database -=============== - -Classes -------- - -`Database(db_path: str = None)` -: Initialize the database and create the tables if they do not exist. - - Default constructor for the database class - - Args: - db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None. - - ### Methods - - `addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: str, prof_id: str)` - : Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. - - Args: - bookdata (BookData): The metadata of the book to be added - app_id (str): The apparat id where the book should be added to - prof_id (str): The id of the professor where the book should be added to. - - `addMessage(self, message: dict, user, appnr)` - : - - `changePassword(self, user, new_password)` - : - - `checkApparatExists(self, apparat_name)` - : - - `checkApparatExistsById(self, apparat_id)` - : - - `checkUsername(self, user)` - : - - `close_connection(self, conn: sqlite3.Connection)` - : closes the connection to the database - - Args: - ---- - - conn (sql.Connection): the connection to be closed - - `connect(self) ‑> sqlite3.Connection` - : Connect to the database - - Returns: - sql.Connection: The active connection to the database - - `createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> Union[src.errors.DatabaseErrors.AppPresentError, ForwardRef(None), int]` - : - - `createProf(self, prof_details: dict)` - : - - `createUser(self, user, password, role, salt)` - : Create a user based on passed data. - - Args: - ---- - - username (str): Username to be used - - password (str): the salted password - - role (str): Role of the user - - salt (str): a random salt for the user - - `create_tables(self)` - : Create the tables in the database - - `deleteApparat(self, appnr, semester)` - : - - `deleteBook(self, book_id)` - : Delete a book from the database - - Args: - book_id (str): ID of the book - - `deleteMessage(self, message_id)` - : - - `deleteUser(self, user)` - : - - `getAllAparats(self, deleted=0)` - : - - `getApparatCountBySemester(self) ‑> tuple[list[str], list[int]]` - : - - `getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData` - : - - `getApparatId(self, apparat_name)` - : - - `getApparatName(self, app_id, prof_id)` - : - - `getApparatsByProf(self, prof_id: int) ‑> list[tuple]` - : - - `getApparatsBySemester(self, semester: str) ‑> dict` - : - - `getBlob(self, filename, app_id)` - : Get a blob from the database - - Args: - filename (str): The name of the file - app_id (str): ID of the apparat - - Returns: - bytes: The file stored in - - `getBook(self, book_id: int) ‑> src.logic.dataclass.BookData` - : Get the book based on the id in the database - - Args: - book_id (int): The id of the book - - Returns: - BookData: The metadata of the book wrapped in a BookData object - - `getBookBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> src.logic.dataclass.BookData` - : Get the book based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - BookData: The total metadata of the book wrapped in a BookData object - - `getBookId(self, bookdata: src.logic.dataclass.BookData, app_id, prof_id) ‑> int` - : Get the id of a book based on the metadata of the book - - Args: - bookdata (BookData): The wrapped metadata of the book - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - - Returns: - int: ID of the book - - `getBookIdBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> int` - : Get a book id based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - int: The id of the book - - `getBooks(self, app_id, prof_id, deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]]` - : Get the Books based on the apparat id and the professor id - - Args: - app_id (str): The ID of the apparat - prof_id (str): The ID of the professor - deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. - - Returns: - list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book - - `getFacultyMember(self, name: str)` - : - - `getFacultyMembers(self)` - : - - `getFiles(self, app_id: int, prof_id: int) ‑> list[tuple]` - : - - `getLastBookId(self) ‑> int` - : Get the last book id in the database - - Returns: - int: ID of the last book in the database - - `getMessages(self, date: str)` - : - - `getProfByName(self, prof_name: str)` - : - - `getProfData(self, profname: str)` - : - - `getProfId(self, prof_name: str)` - : getProfId _summary_ - - :param prof_name: _description_ - :type prof_name: str - :return: _description_ - :rtype: _type_ - - `getProfNameById(self, prof_id: int, add_title: bool = False)` - : - - `getProfs(self)` - : - - `getRole(self, user)` - : - - `getRoles(self)` - : - - `getSemersters(self)` - : - - `getSpecificProfData(self, prof_id: int, fields: List[str])` - : getSpecificProfData _summary_ - - - - Args: - ---- - - prof_id (int): _description_ - - fields (List[str]): _description_ - - Returns: - ------- - - _type_: _description_ - - `getSubjects(self)` - : - - `getTitleById(self, prof_id: int)` - : - - `getUnavailableApparatNumbers(self) ‑> List[int]` - : getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers - - - - Returns: - ------- - - number(List[int]): a list of all currently used apparat numbers - - `getUser(self)` - : - - `getUsers(self)` - : - - `get_db_contents(self) ‑> Optional[List[Tuple]]` - : Get the contents of the - - Returns: - Union[List[Tuple], None]: _description_ - - `insertFile(self, file: list[dict], app_id: int, prof_id)` - : - - `insertInto(self, query: str, params: Tuple) ‑> None` - : Insert sent data into the database - - Args: - query (str): The query to be executed - params (Tuple): the parameters to be inserted into the database - - `isEternal(self, id)` - : - - `login(self, user, hashed_password)` - : - - `query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]]` - : Query the Database for the sent query. - - Args: - query (str): The query to be executed - args (Tuple, optional): The arguments for the query. Defaults to (). - one (bool, optional): Return the first result only. Defaults to False. - - Returns: - Union[Typle|List[Tuple]]: Returns the result of the query - - `recreateFile(self, filename, app_id, filetype)` - : - - `searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]]` - : Search a book in the database based on the sent data. - - Args: - data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - - signature: The signature of the book - - title: The title of the book - - Returns: - list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book - - `setAvailability(self, book_id: str, available: str)` - : Set the availability of a book in the database - - Args: - book_id (str): The id of the book - available (str): The availability of the book - - `setNewSemesterDate(self, appnr, newDate, dauerapp=False)` - : - - `statistic_request(self, **kwargs: Any)` - : - - `updateApparat(self, apparat_data: src.logic.dataclass.ApparatData)` - : - - `updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData)` - : Update the bookdata in the database - - Args: - book_id (str): The id of the book - bookdata (BookData): The new metadata of the book - - `updateFacultyMember(self, data, oldlname, oldfname)` - : - - `updateUser(self, username, data: dict[str, str])` - : \ No newline at end of file diff --git a/docs - Kopie/db.html b/docs - Kopie/db.html deleted file mode 100644 index f2b125f..0000000 --- a/docs - Kopie/db.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - -db API documentation - - - - - - - - - - - -
-
-
-

Module db

-
-
-

Module db provides the database schema for the semesterapparat application.

-
-
-
- -Expand source code - -
CREATE_TABLE_APPARAT = """CREATE TABLE semesterapparat (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    name TEXT,
-    prof_id INTEGER,
-    fach TEXT,
-    appnr INTEGER,
-    erstellsemester TEXT,
-    verlängert_am TEXT,
-    dauer BOOLEAN,
-    verlängerung_bis TEXT,
-    deletion_status INTEGER,
-    deleted_date TEXT,
-    apparat_id_adis INTEGER,
-    prof_id_adis INTEGER,
-    konto INTEGER REFERENCES app_kontos (id),
-    FOREIGN KEY (prof_id) REFERENCES prof (id)
-  )"""
-CREATE_TABLE_MEDIA = """CREATE TABLE media (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    bookdata BLOB,
-    app_id INTEGER,
-    prof_id INTEGER,
-    deleted INTEGER DEFAULT (0),
-    available BOOLEAN,
-    reservation BOOLEAN,
-    FOREIGN KEY (prof_id) REFERENCES prof (id),
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-  )"""
-CREATE_TABLE_APPKONTOS = """CREATE TABLE app_kontos (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    app_id INTEGER,
-    konto INTEGER,
-    passwort TEXT,
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-    )"""
-CREATE_TABLE_FILES = """CREATE TABLE files (
-    id INTEGER PRIMARY KEY,
-    filename TEXT,
-    fileblob BLOB,
-    app_id INTEGER,
-    filetyp TEXT,
-    prof_id INTEGER REFERENCES prof (id),
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-    )"""
-CREATE_TABLE_MESSAGES = """CREATE TABLE messages (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    created_at date NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    message TEXT NOT NULL,
-    remind_at date NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    user_id INTEGER NOT NULL,
-    appnr INTEGER,
-    FOREIGN KEY (user_id) REFERENCES user (id)
-  )"""
-CREATE_TABLE_PROF = """CREATE TABLE prof (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    titel TEXT,
-    fname TEXT,
-    lname TEXT,
-    fullname TEXT NOT NULL UNIQUE,
-    mail TEXT,
-    telnr TEXT
-  )"""
-CREATE_TABLE_USER = """CREATE TABLE user (
-    id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
-    created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    username TEXT NOT NULL UNIQUE,
-    password TEXT NOT NULL,
-    salt TEXT NOT NULL,
-    role TEXT NOT NULL,
-    email TEXT UNIQUE,
-    name TEXT
-  )"""
-CREATE_TABLE_SUBJECTS = """CREATE TABLE subjects (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    name TEXT NOT NULL UNIQUE
-)"""
-
-
-
-
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs - Kopie/db.md b/docs - Kopie/db.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs - Kopie/index.md b/docs - Kopie/index.md deleted file mode 100644 index a77c9f7..0000000 --- a/docs - Kopie/index.md +++ /dev/null @@ -1,18 +0,0 @@ -# Welcome to MkDocs - -For full documentation visit [mkdocs.org](https://www.mkdocs.org). - -## Commands - -* `mkdocs new [dir-name]` - Create a new project. -* `mkdocs serve` - Start the live-reloading docs server. -* `mkdocs build` - Build the documentation site. -* `mkdocs -h` - Print help message and exit. - -## Project layout - - mkdocs.yml # The configuration file. - docs/ - index.md # The documentation homepage. - database.md # Documentation of the Database and it's tables - ... # Other markdown pages, images and other files. diff --git a/docs/database.html b/docs/database.html deleted file mode 100644 index 7be3ffd..0000000 --- a/docs/database.html +++ /dev/null @@ -1,4266 +0,0 @@ - - - - - - -database API documentation - - - - - - - - - - - -
-
-
-

Module database

-
-
-
- -Expand source code - -
import datetime
-import os
-import re
-import sqlite3 as sql
-import tempfile
-from src.logic.log import MyLogger
-from icecream import ic
-from typing import List, Tuple, Dict, Any, Optional, Union
-from pathlib import Path
-from omegaconf import OmegaConf
-from src.backend.db import CREATE_TABLE_APPARAT, CREATE_TABLE_MESSAGES, CREATE_TABLE_MEDIA, CREATE_TABLE_APPKONTOS, CREATE_TABLE_FILES, CREATE_TABLE_PROF, CREATE_TABLE_USER, CREATE_TABLE_SUBJECTS
-from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
-from src.logic.dataclass import ApparatData, BookData
-from src.errors import NoResultError, AppPresentError
-from src.utils import load_pickle, dump_pickle,create_blob
-config = OmegaConf.load("config.yaml")
-logger = MyLogger(__name__)
-
-
-class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id:Union[str,int]):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-        """Instert a list of files into the database
-
-        Args:
-            file (list[dict]): a list containing all the files to be inserted
-            Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-            app_id (int): the id of the apparat
-            prof_id (str): the id of the professor
-        """
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-        """Recreate a file from the database
-
-        Args:
-            filename (str): the name of the file
-            app_id (Union[str,int]): the id of the apparat
-            filetype (str): the extension of the file to be created
-
-        Returns:
-            str: The filename of the recreated file 
-        """
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-        """Get all the files associated with the apparat and the professor
-
-        Args:
-            app_id (Union[str,int]): The id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-        """
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self)->list[str]:
-        """Return all the unique semesters in the database
-
-        Returns:
-            list: a list of strings containing the semesters
-        """
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        """Get all the subjects in the database
-
-        Returns:
-            list[tuple]: a list of tuples containing the subjects
-        """
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-        """add a Message to the database
-
-        Args:
-            message (dict): the message to be added
-            user (str): the user who added the message
-            app_id (Union[str,int]): the id of the apparat
-        """
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-    def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-        """Get all the messages for a specific date
-
-        Args:
-            date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-        
-        Returns:
-            list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-        """
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        """Delete a message from the database
-
-        Args:
-            message_id (str): the id of the message
-        """
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-        """Get a professor name based on the id
-
-        Args:
-            prof_id (Union[str,int]): The id of the professor
-            add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-        Returns:
-            str: The name of the professor
-        """
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:Union[str,int])->str:
-        """get the title of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-        """
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str)->tuple:
-        """get all the data of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            tuple: the data of the professor
-        """
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str)->Optional[int]:
-        """Get the id of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            Optional[int]: the id of the professor, if the professor is not found, None is returned
-        """
-        
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-        """A customisable function to get specific data of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-            fields (List[str]): a list of fields to be returned
-
-        Returns:
-            tuple: a tuple containing the requested data
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        """Get mail, telephone number and title of a professor based on the name
-
-        Args:
-            profname (str): name of the professor
-
-        Returns:
-            tuple: the mail, telephone number and title of the professor
-        """
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        """Create a professor in the database
-
-        Args:
-            prof_details (dict): a dictionary containing the details of the professor
-        """
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self)->list[tuple]:
-        """Return all the professors in the database
-
-        Returns:
-            list[tuple]: a list containing all the professors in individual tuples
-        """
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0)->list[tuple]:
-        """Get all the apparats in the database
-
-        Args:
-            deleted (int, optional): Switch the result to use . Defaults to 0.
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-        """Get the Apparat data based on the apparat number and the name
-
-        Args:
-            appnr (str): the apparat number
-            appname (str): the name of the apparat
-
-        Raises:
-            NoResultError: an error is raised if no result is found
-
-        Returns:
-            ApparatData: the appended data of the apparat wrapped in an ApparatData object
-        """
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """Get a list of all the apparat numbers in the database that are currently in use
-
-        Returns:
-            List[int]: the list of used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-        """Set the new semester date for an apparat
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            newDate (str): the new date
-            dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-        """
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-    def getApparatId(self, apparat_name)->Optional[int]:
-        """get the id of an apparat based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-        Returns:
-            Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-        """
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->int:
-        """create the apparat in the database
-
-        Args:
-            apparat (ApparatData): the wrapped metadata of the apparat
-
-        Raises:
-            AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-        Returns:
-            Optional[int]: the id of the apparat
-        """
-                
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            raise AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-        """Get all apparats based on the professor id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict[list]:
-        """get all apparats based on the semester
-
-        Args:
-            semester (str): the selected semester
-
-        Returns:
-            dict[list]: a list off all created and deleted apparats for the selected semester
-        """
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        """get a list of all apparats created and deleted by semester
-
-        Returns:
-            tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, app_id:Union[str,int], semester:str):
-        """Delete an apparat from the database
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-            semester (str): the semester the apparat should be deleted from
-        """
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-    def isEternal(self, id):
-        """check if the apparat is eternal (dauerapparat)
-
-        Args:
-            id (int): the id of the apparat to be checked
-
-        Returns:
-            int: the state of the apparat
-        """
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-        """get the name of the apparat based on the id
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the name of the apparat
-        """
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        """Update an apparat in the database
-
-        Args:
-            apparat_data (ApparatData): the new metadata of the apparat
-        """
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name:str):
-        """check if the apparat is already present in the database based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-        """a check to see if the apparat is already present in the database, based on the id
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        """Take n amount of kwargs and return the result of the query
-        """
-        def __query(query):
-            """execute the query and return the result
-
-            Args:
-                query (str): the constructed query
-
-            Returns:
-                list: the result of the query
-            """
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        """Get a single user from the database"""
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self)->list[tuple]:
-        """Return a list of tuples of all the users in the database"""
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        """try to login the user.
-        The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-        Args:
-            user (str): username that tries to login
-            hashed_password (str): the password the user tries to login with
-
-        Returns:
-            bool: True if the login was successful, False if not
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        """change the password of a user.
-        The password will be added with the salt and then committed to the database
-
-        Args:
-            user (str): username
-            new_password (str): the hashed password
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        """get the role of the user
-
-        Args:
-            user (str): username
-
-        Returns:
-            str: the name of the role
-        """
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self)->list[tuple]:
-        """get all the roles in the database
-
-        Returns:
-            list[str]: a list of all the roles
-        """
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user)->bool:
-        """a check to see if the username is already present in the database
-
-        Args:
-            user (str): the username
-
-        Returns:
-            bool: True if the username is present, False if not
-        """
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """create an user from the AdminCommands class.
-
-        Args:
-            user (str): the username of the user
-            password (str): a hashed password
-            role (str): the role of the user
-            salt (str): a salt for the password
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        """delete an unser
-
-        Args:
-            user (str): username of the user
-        """
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        """changge the data of a user
-
-        Args:
-            username (str): the username of the user
-            data (dict[str, str]): the data to be changed
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str)->tuple:
-        """get a faculty member based on the name
-
-        Args:
-            name (str): the name to be searched for
-
-        Returns:
-            tuple: a tuple containing the data of the faculty member
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-        """update the data of a faculty member
-
-        Args:
-            data (dict): a dictionary containing the data to be updated
-            oldlname (str): the old last name of the faculty member
-            oldfname (str): the old first name of the faculty member
-        """
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        """get a list of all faculty members
-
-        Returns:
-            list[tuple]: a list of tuples containing the faculty members
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Database -(db_path: str = None) -
-
-

Initialize the database and create the tables if they do not exist.

-

Default constructor for the database class

-

Args

-
-
db_path : str, optional
-
Optional Path for testing / specific purposes. Defaults to None.
-
-
- -Expand source code - -
class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id:Union[str,int]):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-        """Instert a list of files into the database
-
-        Args:
-            file (list[dict]): a list containing all the files to be inserted
-            Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-            app_id (int): the id of the apparat
-            prof_id (str): the id of the professor
-        """
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-        """Recreate a file from the database
-
-        Args:
-            filename (str): the name of the file
-            app_id (Union[str,int]): the id of the apparat
-            filetype (str): the extension of the file to be created
-
-        Returns:
-            str: The filename of the recreated file 
-        """
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-        """Get all the files associated with the apparat and the professor
-
-        Args:
-            app_id (Union[str,int]): The id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-        """
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self)->list[str]:
-        """Return all the unique semesters in the database
-
-        Returns:
-            list: a list of strings containing the semesters
-        """
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        """Get all the subjects in the database
-
-        Returns:
-            list[tuple]: a list of tuples containing the subjects
-        """
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-        """add a Message to the database
-
-        Args:
-            message (dict): the message to be added
-            user (str): the user who added the message
-            app_id (Union[str,int]): the id of the apparat
-        """
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-    def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-        """Get all the messages for a specific date
-
-        Args:
-            date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-        
-        Returns:
-            list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-        """
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        """Delete a message from the database
-
-        Args:
-            message_id (str): the id of the message
-        """
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-        """Get a professor name based on the id
-
-        Args:
-            prof_id (Union[str,int]): The id of the professor
-            add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-        Returns:
-            str: The name of the professor
-        """
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:Union[str,int])->str:
-        """get the title of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-        """
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str)->tuple:
-        """get all the data of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            tuple: the data of the professor
-        """
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str)->Optional[int]:
-        """Get the id of a professor based on the name
-
-        Args:
-            prof_name (str): the name of the professor
-
-        Returns:
-            Optional[int]: the id of the professor, if the professor is not found, None is returned
-        """
-        
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-        """A customisable function to get specific data of a professor based on the id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-            fields (List[str]): a list of fields to be returned
-
-        Returns:
-            tuple: a tuple containing the requested data
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        """Get mail, telephone number and title of a professor based on the name
-
-        Args:
-            profname (str): name of the professor
-
-        Returns:
-            tuple: the mail, telephone number and title of the professor
-        """
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        """Create a professor in the database
-
-        Args:
-            prof_details (dict): a dictionary containing the details of the professor
-        """
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self)->list[tuple]:
-        """Return all the professors in the database
-
-        Returns:
-            list[tuple]: a list containing all the professors in individual tuples
-        """
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0)->list[tuple]:
-        """Get all the apparats in the database
-
-        Args:
-            deleted (int, optional): Switch the result to use . Defaults to 0.
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-        """Get the Apparat data based on the apparat number and the name
-
-        Args:
-            appnr (str): the apparat number
-            appname (str): the name of the apparat
-
-        Raises:
-            NoResultError: an error is raised if no result is found
-
-        Returns:
-            ApparatData: the appended data of the apparat wrapped in an ApparatData object
-        """
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """Get a list of all the apparat numbers in the database that are currently in use
-
-        Returns:
-            List[int]: the list of used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-        """Set the new semester date for an apparat
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            newDate (str): the new date
-            dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-        """
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-    def getApparatId(self, apparat_name)->Optional[int]:
-        """get the id of an apparat based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-        Returns:
-            Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-        """
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->int:
-        """create the apparat in the database
-
-        Args:
-            apparat (ApparatData): the wrapped metadata of the apparat
-
-        Raises:
-            AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-        Returns:
-            Optional[int]: the id of the apparat
-        """
-                
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            raise AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-        """Get all apparats based on the professor id
-
-        Args:
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            list[tuple]: a list of tuples containing the apparats
-        """
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict[list]:
-        """get all apparats based on the semester
-
-        Args:
-            semester (str): the selected semester
-
-        Returns:
-            dict[list]: a list off all created and deleted apparats for the selected semester
-        """
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        """get a list of all apparats created and deleted by semester
-
-        Returns:
-            tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, app_id:Union[str,int], semester:str):
-        """Delete an apparat from the database
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-            semester (str): the semester the apparat should be deleted from
-        """
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-    def isEternal(self, id):
-        """check if the apparat is eternal (dauerapparat)
-
-        Args:
-            id (int): the id of the apparat to be checked
-
-        Returns:
-            int: the state of the apparat
-        """
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-        """get the name of the apparat based on the id
-
-        Args:
-            app_id (Union[str,int]): the id of the apparat
-            prof_id (Union[str,int]): the id of the professor
-
-        Returns:
-            str: the name of the apparat
-        """
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        """Update an apparat in the database
-
-        Args:
-            apparat_data (ApparatData): the new metadata of the apparat
-        """
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name:str):
-        """check if the apparat is already present in the database based on the name
-
-        Args:
-            apparat_name (str): the name of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-        """a check to see if the apparat is already present in the database, based on the id
-
-        Args:
-            app_id (Union[str, int]): the id of the apparat
-
-        Returns:
-            bool: True if the apparat is present, False if not
-        """
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        """Take n amount of kwargs and return the result of the query
-        """
-        def __query(query):
-            """execute the query and return the result
-
-            Args:
-                query (str): the constructed query
-
-            Returns:
-                list: the result of the query
-            """
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        """Get a single user from the database"""
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self)->list[tuple]:
-        """Return a list of tuples of all the users in the database"""
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        """try to login the user.
-        The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-        Args:
-            user (str): username that tries to login
-            hashed_password (str): the password the user tries to login with
-
-        Returns:
-            bool: True if the login was successful, False if not
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        """change the password of a user.
-        The password will be added with the salt and then committed to the database
-
-        Args:
-            user (str): username
-            new_password (str): the hashed password
-        """
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        """get the role of the user
-
-        Args:
-            user (str): username
-
-        Returns:
-            str: the name of the role
-        """
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self)->list[tuple]:
-        """get all the roles in the database
-
-        Returns:
-            list[str]: a list of all the roles
-        """
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user)->bool:
-        """a check to see if the username is already present in the database
-
-        Args:
-            user (str): the username
-
-        Returns:
-            bool: True if the username is present, False if not
-        """
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """create an user from the AdminCommands class.
-
-        Args:
-            user (str): the username of the user
-            password (str): a hashed password
-            role (str): the role of the user
-            salt (str): a salt for the password
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        """delete an unser
-
-        Args:
-            user (str): username of the user
-        """
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        """changge the data of a user
-
-        Args:
-            username (str): the username of the user
-            data (dict[str, str]): the data to be changed
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str)->tuple:
-        """get a faculty member based on the name
-
-        Args:
-            name (str): the name to be searched for
-
-        Returns:
-            tuple: a tuple containing the data of the faculty member
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-        """update the data of a faculty member
-
-        Args:
-            data (dict): a dictionary containing the data to be updated
-            oldlname (str): the old last name of the faculty member
-            oldfname (str): the old first name of the faculty member
-        """
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        """get a list of all faculty members
-
-        Returns:
-            list[tuple]: a list of tuples containing the faculty members
-        """
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-

Methods

-
-
-def addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.

-

Args

-
-
bookdata : BookData
-
The metadata of the book to be added
-
app_id : str
-
The apparat id where the book should be added to
-
prof_id : str
-
The id of the professor where the book should be added to.
-
-
- -Expand source code - -
def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
-    """
-    Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-    Args:
-        bookdata (BookData): The metadata of the book to be added
-        app_id (str): The apparat id where the book should be added to
-        prof_id (str): The id of the professor where the book should be added to.
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    t_query = (
-        f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-    )
-    # print(t_query)
-    result = cursor.execute(t_query).fetchall()
-    result = [load_pickle(i[0]) for i in result]
-    if bookdata in result:
-        print("Bookdata already in database")
-        # check if the book was deleted in the apparat
-        query = (
-            "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-        )
-        params = (app_id, prof_id, dump_pickle(bookdata))
-        result = cursor.execute(query, params).fetchone()
-        if result[0] == 1:
-            print("Book was deleted, updating bookdata")
-            query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            cursor.execute(query, params)
-            conn.commit()
-        return
-
-    query = (
-        "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-    )
-    converted = dump_pickle(bookdata)
-    params = (converted, app_id, prof_id, 0)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def addMessage(self, message: dict, user: str, app_id: Union[str, int]) -
-
-

add a Message to the database

-

Args

-
-
message : dict
-
the message to be added
-
user : str
-
the user who added the message
-
app_id : Union[str,int]
-
the id of the apparat
-
-
- -Expand source code - -
def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
-    """add a Message to the database
-
-    Args:
-        message (dict): the message to be added
-        user (str): the user who added the message
-        app_id (Union[str,int]): the id of the apparat
-    """
-    def __getUserId(user):
-        return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-    user_id = __getUserId(user)
-    self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
-
-
-
-def changePassword(self, user, new_password) -
-
-

change the password of a user. -The password will be added with the salt and then committed to the database

-

Args

-
-
user : str
-
username
-
new_password : str
-
the hashed password
-
-
- -Expand source code - -
def changePassword(self, user, new_password):
-    """change the password of a user.
-    The password will be added with the salt and then committed to the database
-
-    Args:
-        user (str): username
-        new_password (str): the hashed password
-    """
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    new_password = salt + new_password
-    self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-
-
-
-def checkApparatExists(self, apparat_name: str) -
-
-

check if the apparat is already present in the database based on the name

-

Args

-
-
apparat_name : str
-
the name of the apparat
-
-

Returns

-
-
bool
-
True if the apparat is present, False if not
-
-
- -Expand source code - -
def checkApparatExists(self, apparat_name:str):
-    """check if the apparat is already present in the database based on the name
-
-    Args:
-        apparat_name (str): the name of the apparat
-
-    Returns:
-        bool: True if the apparat is present, False if not
-    """
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-
-
-
-def checkApparatExistsById(self, app_id: Union[str, int]) ‑> bool -
-
-

a check to see if the apparat is already present in the database, based on the id

-

Args

-
-
app_id : Union[str, int]
-
the id of the apparat
-
-

Returns

-
-
bool
-
True if the apparat is present, False if not
-
-
- -Expand source code - -
def checkApparatExistsById(self, app_id:Union[str,int])->bool:
-    """a check to see if the apparat is already present in the database, based on the id
-
-    Args:
-        app_id (Union[str, int]): the id of the apparat
-
-    Returns:
-        bool: True if the apparat is present, False if not
-    """
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
-
-
-
-def checkUsername(self, user) ‑> bool -
-
-

a check to see if the username is already present in the database

-

Args

-
-
user : str
-
the username
-
-

Returns

-
-
bool
-
True if the username is present, False if not
-
-
- -Expand source code - -
def checkUsername(self, user)->bool:
-    """a check to see if the username is already present in the database
-
-    Args:
-        user (str): the username
-
-    Returns:
-        bool: True if the username is present, False if not
-    """
-    data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-    return True if data is not None else False
-
-
-
-def close_connection(self, conn: sqlite3.Connection) -
-
-

closes the connection to the database

-

Args:

-
- conn (sql.Connection): the connection to be closed
-
-
- -Expand source code - -
def close_connection(self, conn: sql.Connection):
-    """
-    closes the connection to the database
-    
-    Args:
-    ----
-        - conn (sql.Connection): the connection to be closed
-    """
-    conn.close()
-
-
-
-def connect(self) ‑> sqlite3.Connection -
-
-

Connect to the database

-

Returns

-
-
sql.Connection
-
The active connection to the database
-
-
- -Expand source code - -
def connect(self)->sql.Connection:
-    """
-    Connect to the database
-
-    Returns:
-        sql.Connection: The active connection to the database
-    """
-    return sql.connect(self.db_path)
-
-
-
-def createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> int -
-
-

create the apparat in the database

-

Args

-
-
apparat : ApparatData
-
the wrapped metadata of the apparat
-
-

Raises

-
-
AppPresentError
-
an error describing that the apparats chosen id is already present in the database
-
-

Returns

-
-
Optional[int]
-
the id of the apparat
-
-
- -Expand source code - -
def createApparat(self, apparat:ApparatData)->int:
-    """create the apparat in the database
-
-    Args:
-        apparat (ApparatData): the wrapped metadata of the apparat
-
-    Raises:
-        AppPresentError: an error describing that the apparats chosen id is already present in the database
-
-    Returns:
-        Optional[int]: the id of the apparat
-    """
-            
-    prof_id = self.getProfId(apparat.profname)
-    app_id = self.getApparatId(apparat.appname)
-    if app_id:
-        raise AppPresentError(app_id)
-
-    self.createProf(apparat.get_prof_details())
-    prof_id = self.getProfId(apparat.profname)
-    ic(prof_id)
-    query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-    logger.log_info(query)
-    self.query_db(query)
-    return self.getApparatId(apparat.appname)
-
-
-
-def createProf(self, prof_details: dict) -
-
-

Create a professor in the database

-

Args

-
-
prof_details : dict
-
a dictionary containing the details of the professor
-
-
- -Expand source code - -
def createProf(self, prof_details:dict):
-    """Create a professor in the database
-
-    Args:
-        prof_details (dict): a dictionary containing the details of the professor
-    """
-    prof_title = prof_details["prof_title"]
-    prof_fname = prof_details["profname"].split(",")[1]
-    prof_fname = prof_fname.strip()
-    prof_lname = prof_details["profname"].split(",")[0]
-    prof_lname = prof_lname.strip()
-    prof_fullname = prof_details["profname"].replace(",", "")
-    prof_mail = prof_details["prof_mail"]
-    prof_tel = prof_details["prof_tel"]
-    params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-    query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-    self.insertInto(query=query, params=params)
-
-
-
-def createUser(self, user, password, role, salt) -
-
-

create an user from the AdminCommands class.

-

Args

-
-
user : str
-
the username of the user
-
password : str
-
a hashed password
-
role : str
-
the role of the user
-
salt : str
-
a salt for the password
-
-
- -Expand source code - -
def createUser(self, user, password, role, salt):
-    """create an user from the AdminCommands class.
-
-    Args:
-        user (str): the username of the user
-        password (str): a hashed password
-        role (str): the role of the user
-        salt (str): a salt for the password
-    """
-    self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-
-
-
-def create_tables(self) -
-
-

Create the tables in the database

-
- -Expand source code - -
def create_tables(self):
-    """
-    Create the tables in the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    cursor.execute(CREATE_TABLE_APPARAT)
-    cursor.execute(CREATE_TABLE_MESSAGES)
-    cursor.execute(CREATE_TABLE_MEDIA)
-    cursor.execute(CREATE_TABLE_APPKONTOS)
-    cursor.execute(CREATE_TABLE_FILES)
-    cursor.execute(CREATE_TABLE_PROF)
-    cursor.execute(CREATE_TABLE_USER)
-    cursor.execute(CREATE_TABLE_SUBJECTS)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def deleteApparat(self, app_id: Union[str, int], semester: str) -
-
-

Delete an apparat from the database

-

Args

-
-
app_id : Union[str, int]
-
the id of the apparat
-
semester : str
-
the semester the apparat should be deleted from
-
-
- -Expand source code - -
def deleteApparat(self, app_id:Union[str,int], semester:str):
-    """Delete an apparat from the database
-
-    Args:
-        app_id (Union[str, int]): the id of the apparat
-        semester (str): the semester the apparat should be deleted from
-    """
-    self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) 
-
-
-
-def deleteBook(self, book_id) -
-
-

Delete a book from the database

-

Args

-
-
book_id : str
-
ID of the book
-
-
- -Expand source code - -
def deleteBook(self, book_id):
-    """
-    Delete a book from the database
-
-    Args:
-        book_id (str): ID of the book
-    """
-    self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-
-
-def deleteMessage(self, message_id) -
-
-

Delete a message from the database

-

Args

-
-
message_id : str
-
the id of the message
-
-
- -Expand source code - -
def deleteMessage(self, message_id):
-    """Delete a message from the database
-
-    Args:
-        message_id (str): the id of the message
-    """
-    self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-
-
-def deleteUser(self, user) -
-
-

delete an unser

-

Args

-
-
user : str
-
username of the user
-
-
- -Expand source code - -
def deleteUser(self, user):
-    """delete an unser
-
-    Args:
-        user (str): username of the user
-    """
-    self.query_db("DELETE FROM user WHERE username=?", (user,))
-
-
-
-def getAllAparats(self, deleted=0) ‑> list[tuple] -
-
-

Get all the apparats in the database

-

Args

-
-
deleted : int, optional
-
Switch the result to use . Defaults to 0.
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the apparats
-
-
- -Expand source code - -
def getAllAparats(self,deleted=0)->list[tuple]:
-    """Get all the apparats in the database
-
-    Args:
-        deleted (int, optional): Switch the result to use . Defaults to 0.
-
-    Returns:
-        list[tuple]: a list of tuples containing the apparats
-    """
-    return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-
-
-
-def getApparatCountBySemester(self) ‑> tuple[list[str], list[int]] -
-
-

get a list of all apparats created and deleted by semester

-

Returns

-
-
tuple[list[str],list[int]]
-
a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-
-
- -Expand source code - -
def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-    """get a list of all apparats created and deleted by semester
-
-    Returns:
-        tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    semesters = self.getSemersters()
-    created = []
-    deleted = []
-    for semester in semesters:
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-        result = cursor.execute(query).fetchone()
-        created.append(result[0])
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-        result = cursor.execute(query).fetchone()
-        deleted.append(result[0])
-    # store data in a tuple
-    ret = []
-    e_tuple = ()
-    for sem in semesters:
-        e_tuple = (
-            sem,
-            created[semesters.index(sem)],
-            deleted[semesters.index(sem)],
-        )
-        ret.append(e_tuple)
-    self.close_connection(conn)
-    return ret 
-
-
-
-def getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData -
-
-

Get the Apparat data based on the apparat number and the name

-

Args

-
-
appnr : str
-
the apparat number
-
appname : str
-
the name of the apparat
-
-

Raises

-
-
NoResultError
-
an error is raised if no result is found
-
-

Returns

-
-
ApparatData
-
the appended data of the apparat wrapped in an ApparatData object
-
-
- -Expand source code - -
def getApparatData(self, appnr, appname)->ApparatData:
-    """Get the Apparat data based on the apparat number and the name
-
-    Args:
-        appnr (str): the apparat number
-        appname (str): the name of the apparat
-
-    Raises:
-        NoResultError: an error is raised if no result is found
-
-    Returns:
-        ApparatData: the appended data of the apparat wrapped in an ApparatData object
-    """
-    result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-    if result is None:
-        raise NoResultError("No result found")
-    apparat = ApparatData()
-    apparat.appname = result[1]
-    apparat.appnr = result[4]
-    apparat.dauerapp = True if result[7] == 1 else False
-    prof_data = self.getProfData(self.getProfNameById(result[2]))
-    apparat.profname = self.getProfNameById(result[2])
-    apparat.prof_mail = prof_data[0]
-    apparat.prof_tel = prof_data[1]
-    apparat.prof_title = prof_data[2]
-    apparat.app_fach = result[3]
-    apparat.erstellsemester = result[5]
-    apparat.semester = result[8]
-    apparat.deleted = result[9]
-    apparat.apparat_adis_id = result[11]
-    apparat.prof_adis_id = result[12]
-    return apparat
-
-
-
-def getApparatId(self, apparat_name) ‑> Optional[int] -
-
-

get the id of an apparat based on the name

-

Args

-
-
apparat_name : str
-
the name of the apparat e.g. "Semesterapparat 1"
-
-

Returns

-
-
Optional[int]
-
the id of the apparat, if the apparat is not found, None is returned
-
-
- -Expand source code - -
def getApparatId(self, apparat_name)->Optional[int]:
-    """get the id of an apparat based on the name
-
-    Args:
-        apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
-    Returns:
-        Optional[int]: the id of the apparat, if the apparat is not found, None is returned
-    """
-    data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getApparatName(self, app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

get the name of the apparat based on the id

-

Args

-
-
app_id : Union[str,int]
-
the id of the apparat
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
str
-
the name of the apparat
-
-
- -Expand source code - -
def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
-    """get the name of the apparat based on the id
-
-    Args:
-        app_id (Union[str,int]): the id of the apparat
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        str: the name of the apparat
-    """
-    return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-
-
-
-def getApparatsByProf(self, prof_id: Union[str, int]) ‑> list[tuple] -
-
-

Get all apparats based on the professor id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the apparats
-
-
- -Expand source code - -
def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
-    """Get all apparats based on the professor id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        list[tuple]: a list of tuples containing the apparats
-    """
-    return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-
-
-
-def getApparatsBySemester(self, semester: str) ‑> dict[list] -
-
-

get all apparats based on the semester

-

Args

-
-
semester : str
-
the selected semester
-
-

Returns

-
-
dict[list]
-
a list off all created and deleted apparats for the selected semester
-
-
- -Expand source code - -
def getApparatsBySemester(self, semester:str)->dict[list]:
-    """get all apparats based on the semester
-
-    Args:
-        semester (str): the selected semester
-
-    Returns:
-        dict[list]: a list off all created and deleted apparats for the selected semester
-    """
-    data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-    conn = self.connect()
-    cursor = conn.cursor()
-    c_tmp = []
-    for i in data:
-        c_tmp.append((i[0], self.getProfNameById(i[1])))
-    query = (
-        f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-    )
-    result = cursor.execute(query).fetchall()
-    d_tmp = []
-    for i in result:
-        d_tmp.append((i[0], self.getProfNameById(i[1])))
-    # group the apparats by prof
-    c_ret = {}
-    for i in c_tmp:
-        if i[1] not in c_ret.keys():
-            c_ret[i[1]] = [i[0]]
-        else:
-            c_ret[i[1]].append(i[0])
-    d_ret = {}
-    for i in d_tmp:
-        if i[1] not in d_ret.keys():
-            d_ret[i[1]] = [i[0]]
-        else:
-            d_ret[i[1]].append(i[0])
-    self.close_connection(conn)
-    return {"created": c_ret, "deleted": d_ret}
-
-
-
-def getBlob(self, filename, app_id: Union[str, int]) -
-
-

Get a blob from the database

-

Args

-
-
filename : str
-
The name of the file
-
app_id : str
-
ID of the apparat
-
-

Returns

-
-
bytes
-
The file stored in
-
-
- -Expand source code - -
def getBlob(self, filename, app_id:Union[str,int]):
-    """
-    Get a blob from the database
-
-    Args:
-        filename (str): The name of the file
-        app_id (str): ID of the apparat
-
-    Returns:
-        bytes: The file stored in 
-    """
-    return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-
-
-
-def getBook(self, book_id: int) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the id in the database

-

Args

-
-
book_id : int
-
The id of the book
-
-

Returns

-
-
BookData
-
The metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBook(self,book_id:int)->BookData:
-    """
-    Get the book based on the id in the database
-
-    Args:
-        book_id (int): The id of the book
-
-    Returns:
-        BookData: The metadata of the book wrapped in a BookData object
-    """
-    return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-
-
-
-def getBookBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
BookData
-
The total metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
-    """
-    Get the book based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        BookData: The total metadata of the book wrapped in a BookData object
-    """
-    result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [load_pickle(i[0]) for i in result]
-    book = [i for i in books if i.signature == signature][0]
-    return book
-
-
-
-def getBookId(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) ‑> int -
-
-

Get the id of a book based on the metadata of the book

-

Args

-
-
bookdata : BookData
-
The wrapped metadata of the book
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
-

Returns

-
-
int
-
ID of the book
-
-
- -Expand source code - -
def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
-    """
-    Get the id of a book based on the metadata of the book
-
-    Args:
-        bookdata (BookData): The wrapped metadata of the book
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-
-    Returns:
-        int: ID of the book
-    """
-    result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-    return result[0]
-
-
-
-def getBookIdBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> int -
-
-

Get a book id based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
int
-
The id of the book
-
-
- -Expand source code - -
def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
-    """
-    Get a book id based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        int: The id of the book
-    """
-    result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [(load_pickle(i[0]),i[1]) for i in result]
-    book = [i for i in books if i[0].signature == signature][0][1]
-    return book
-
-
-
-def getBooks(self, app_id: Union[str, int], prof_id: Union[str, int], deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]] -
-
-

Get the Books based on the apparat id and the professor id

-

Args

-
-
app_id : str
-
The ID of the apparat
-
prof_id : str
-
The ID of the professor
-
deleted : int, optional
-
The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-

Returns

-
-
list[dict[int, BookData, int]]
-
A list of dictionaries containing the id, the metadata of the book and the availability of the book
-
-
- -Expand source code - -
def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
-    """
-    Get the Books based on the apparat id and the professor id
-
-    Args:
-        app_id (str): The ID of the apparat
-        prof_id (str): The ID of the professor
-        deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-    Returns:
-        list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-    """
-    qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-    ret_result = []
-    for result_a in qdata:
-        data = {"id": int, "bookdata": BookData, "available": int}
-        data["id"] = result_a[0]
-        data["bookdata"] = load_pickle(result_a[1])
-        data["available"] = result_a[2]
-        ret_result.append(data)
-    return ret_result
-
-
-
-def getFacultyMember(self, name: str) ‑> tuple -
-
-

get a faculty member based on the name

-

Args

-
-
name : str
-
the name to be searched for
-
-

Returns

-
-
tuple
-
a tuple containing the data of the faculty member
-
-
- -Expand source code - -
def getFacultyMember(self, name:str)->tuple:
-    """get a faculty member based on the name
-
-    Args:
-        name (str): the name to be searched for
-
-    Returns:
-        tuple: a tuple containing the data of the faculty member
-    """
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-
-
-
-def getFacultyMembers(self) -
-
-

get a list of all faculty members

-

Returns

-
-
list[tuple]
-
a list of tuples containing the faculty members
-
-
- -Expand source code - -
def getFacultyMembers(self):
-    """get a list of all faculty members
-
-    Returns:
-        list[tuple]: a list of tuples containing the faculty members
-    """
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-def getFiles(self, app_id: Union[str, int], prof_id: int) ‑> list[tuple] -
-
-

Get all the files associated with the apparat and the professor

-

Args

-
-
app_id : Union[str,int]
-
The id of the apparat
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
list[tuple]
-
a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-
-
- -Expand source code - -
def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
-    """Get all the files associated with the apparat and the professor
-
-    Args:
-        app_id (Union[str,int]): The id of the apparat
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
-    """
-    return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-
-
-def getLastBookId(self) ‑> int -
-
-

Get the last book id in the database

-

Returns

-
-
int
-
ID of the last book in the database
-
-
- -Expand source code - -
def getLastBookId(self)->int:
-    """
-    Get the last book id in the database
-
-    Returns:
-        int: ID of the last book in the database
-    """
-    return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-
-
-
-def getMessages(self, date: str) ‑> list[dict[str, str, str, str]] -
-
-

Get all the messages for a specific date

-

Args

-
-
date : str
-
a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-
-

Returns

-
-
list[dict[str, str, str, str]]
-
a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-
-
- -Expand source code - -
def getMessages(self, date:str)->list[dict[str, str, str, str]]:
-    """Get all the messages for a specific date
-
-    Args:
-        date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-    
-    Returns:
-        list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
-    """
-    def __get_user_name(user_id):
-        return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-    messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-    ret = [
-        {
-            "message": i[2],
-            "user": __get_user_name(i[4]),
-            "appnr": i[5],
-            "id": i[0]
-        }
-        for i in messages
-    ]
-    return ret
-
-
-
-def getProfByName(self, prof_name: str) ‑> tuple -
-
-

get all the data of a professor based on the name

-

Args

-
-
prof_name : str
-
the name of the professor
-
-

Returns

-
-
tuple
-
the data of the professor
-
-
- -Expand source code - -
def getProfByName(self, prof_name:str)->tuple:
-    """get all the data of a professor based on the name
-
-    Args:
-        prof_name (str): the name of the professor
-
-    Returns:
-        tuple: the data of the professor
-    """
-    return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-
-
-
-def getProfData(self, profname: str) -
-
-

Get mail, telephone number and title of a professor based on the name

-

Args

-
-
profname : str
-
name of the professor
-
-

Returns

-
-
tuple
-
the mail, telephone number and title of the professor
-
-
- -Expand source code - -
def getProfData(self, profname:str):
-    """Get mail, telephone number and title of a professor based on the name
-
-    Args:
-        profname (str): name of the professor
-
-    Returns:
-        tuple: the mail, telephone number and title of the professor
-    """
-    data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-    return data
-
-
-
-def getProfId(self, prof_name: str) ‑> Optional[int] -
-
-

Get the id of a professor based on the name

-

Args

-
-
prof_name : str
-
the name of the professor
-
-

Returns

-
-
Optional[int]
-
the id of the professor, if the professor is not found, None is returned
-
-
- -Expand source code - -
def getProfId(self, prof_name:str)->Optional[int]:
-    """Get the id of a professor based on the name
-
-    Args:
-        prof_name (str): the name of the professor
-
-    Returns:
-        Optional[int]: the id of the professor, if the professor is not found, None is returned
-    """
-    
-    data = self.getProfByName(prof_name.replace(",", ""))
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getProfNameById(self, prof_id: Union[str, int], add_title: bool = False) ‑> str -
-
-

Get a professor name based on the id

-

Args

-
-
prof_id : Union[str,int]
-
The id of the professor
-
add_title : bool, optional
-
wether to add the title or no. Defaults to False.
-
-

Returns

-
-
str
-
The name of the professor
-
-
- -Expand source code - -
def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
-    """Get a professor name based on the id
-
-    Args:
-        prof_id (Union[str,int]): The id of the professor
-        add_title (bool, optional): wether to add the title or no. Defaults to False.
-
-    Returns:
-        str: The name of the professor
-    """
-    prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-    if add_title:
-        return f"{self.getTitleById(prof_id)}{prof[0]}"
-    else:
-        return prof[0]
-
-
-
-def getProfs(self) ‑> list[tuple] -
-
-

Return all the professors in the database

-

Returns

-
-
list[tuple]
-
a list containing all the professors in individual tuples
-
-
- -Expand source code - -
def getProfs(self)->list[tuple]:
-    """Return all the professors in the database
-
-    Returns:
-        list[tuple]: a list containing all the professors in individual tuples
-    """
-    return self.query_db("SELECT * FROM prof")
-
-
-
-def getRole(self, user) -
-
-

get the role of the user

-

Args

-
-
user : str
-
username
-
-

Returns

-
-
str
-
the name of the role
-
-
- -Expand source code - -
def getRole(self, user):
-    """get the role of the user
-
-    Args:
-        user (str): username
-
-    Returns:
-        str: the name of the role
-    """
-    return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-
-
-
-def getRoles(self) ‑> list[tuple] -
-
-

get all the roles in the database

-

Returns

-
-
list[str]
-
a list of all the roles
-
-
- -Expand source code - -
def getRoles(self)->list[tuple]:
-    """get all the roles in the database
-
-    Returns:
-        list[str]: a list of all the roles
-    """
-    return self.query_db("SELECT role FROM user")
-
-
-
-def getSemersters(self) ‑> list[str] -
-
-

Return all the unique semesters in the database

-

Returns

-
-
list
-
a list of strings containing the semesters
-
-
- -Expand source code - -
def getSemersters(self)->list[str]:
-    """Return all the unique semesters in the database
-
-    Returns:
-        list: a list of strings containing the semesters
-    """
-    data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-    return [i[0] for i in data]
-
-
-
-def getSpecificProfData(self, prof_id: Union[str, int], fields: List[str]) ‑> tuple -
-
-

A customisable function to get specific data of a professor based on the id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
fields : List[str]
-
a list of fields to be returned
-
-

Returns

-
-
tuple
-
a tuple containing the requested data
-
-
- -Expand source code - -
def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
-    """A customisable function to get specific data of a professor based on the id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-        fields (List[str]): a list of fields to be returned
-
-    Returns:
-        tuple: a tuple containing the requested data
-    """
-    query = "SELECT "
-    for field in fields:
-        query += f"{field},"
-    query = query[:-1]
-    query += " FROM prof WHERE id=?"
-    return self.query_db(query, (prof_id,), one=True)[0]
-
-
-
-def getSubjects(self) -
-
-

Get all the subjects in the database

-

Returns

-
-
list[tuple]
-
a list of tuples containing the subjects
-
-
- -Expand source code - -
def getSubjects(self):
-    """Get all the subjects in the database
-
-    Returns:
-        list[tuple]: a list of tuples containing the subjects
-    """
-    return self.query_db("SELECT * FROM subjects")
-
-
-
-def getTitleById(self, prof_id: Union[str, int]) ‑> str -
-
-

get the title of a professor based on the id

-

Args

-
-
prof_id : Union[str,int]
-
the id of the professor
-
-

Returns

-
-
str
-
the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-
-
- -Expand source code - -
def getTitleById(self, prof_id:Union[str,int])->str:
-    """get the title of a professor based on the id
-
-    Args:
-        prof_id (Union[str,int]): the id of the professor
-
-    Returns:
-        str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
-    """
-    title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-    return f"{title} " if title is not None else ""
-
-
-
-def getUnavailableApparatNumbers(self) ‑> List[int] -
-
-

Get a list of all the apparat numbers in the database that are currently in use

-

Returns

-
-
List[int]
-
the list of used apparat numbers
-
-
- -Expand source code - -
def getUnavailableApparatNumbers(self)->List[int]:
-    """Get a list of all the apparat numbers in the database that are currently in use
-
-    Returns:
-        List[int]: the list of used apparat numbers
-    """
-    numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-    numbers = [i[0] for i in numbers]
-    logger.log_info(f"Currently used apparat numbers: {numbers}")
-    return numbers
-
-
-
-def getUser(self) -
-
-

Get a single user from the database

-
- -Expand source code - -
def getUser(self):
-    """Get a single user from the database"""
-    return self.query_db("SELECT * FROM user", one=True)
-
-
-
-def getUsers(self) ‑> list[tuple] -
-
-

Return a list of tuples of all the users in the database

-
- -Expand source code - -
def getUsers(self)->list[tuple]:
-    """Return a list of tuples of all the users in the database"""
-    return self.query_db("SELECT * FROM user")
-
-
-
-def get_db_contents(self) ‑> Optional[List[Tuple]] -
-
-

Get the contents of the

-

Returns

-
-
Union[List[Tuple], None]
-
description
-
-
- -Expand source code - -
def get_db_contents(self)->Union[List[Tuple], None]:
-    """
-    Get the contents of the 
-
-    Returns:
-        Union[List[Tuple], None]: _description_
-    """
-    try:
-        with sql.connect(self.db_path) as conn:
-            cursor = conn.cursor()
-            cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-            return cursor.fetchall()
-    except sql.OperationalError:
-        return None
-
-
-
-def insertFile(self, file: list[dict], app_id: Union[str, int], prof_id: Union[str, int]) -
-
-

Instert a list of files into the database

-

Args

-
-
file : list[dict]
-
a list containing all the files to be inserted
-
Structured
-
[{"name": "filename", "path": "path", "type": "filetype"}]
-
app_id : int
-
the id of the apparat
-
prof_id : str
-
the id of the professor
-
-
- -Expand source code - -
def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
-    """Instert a list of files into the database
-
-    Args:
-        file (list[dict]): a list containing all the files to be inserted
-        Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
-        app_id (int): the id of the apparat
-        prof_id (str): the id of the professor
-    """
-    for f in file:
-        filename = f["name"]
-        path = f["path"]
-        filetyp = f["type"]
-        if path == "Database":
-            continue
-        blob = create_blob(path)
-        query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-        self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-
-
-
-def insertInto(self, query: str, params: Tuple) ‑> None -
-
-

Insert sent data into the database

-

Args

-
-
query : str
-
The query to be executed
-
params : Tuple
-
the parameters to be inserted into the database
-
-
- -Expand source code - -
def insertInto(self, query:str, params:Tuple) -> None:
-    """
-    Insert sent data into the database
-
-    Args:
-        query (str): The query to be executed
-        params (Tuple): the parameters to be inserted into the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Inserting {params} into database with query {query}")
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def isEternal(self, id) -
-
-

check if the apparat is eternal (dauerapparat)

-

Args

-
-
id : int
-
the id of the apparat to be checked
-
-

Returns

-
-
int
-
the state of the apparat
-
-
- -Expand source code - -
def isEternal(self, id):
-    """check if the apparat is eternal (dauerapparat)
-
-    Args:
-        id (int): the id of the apparat to be checked
-
-    Returns:
-        int: the state of the apparat
-    """
-    return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-
-
-
-def login(self, user, hashed_password) -
-
-

try to login the user. -The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database

-

Args

-
-
user : str
-
username that tries to login
-
hashed_password : str
-
the password the user tries to login with
-
-

Returns

-
-
bool
-
True if the login was successful, False if not
-
-
- -Expand source code - -
def login(self, user, hashed_password):
-    """try to login the user.
-    The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database 
-
-    Args:
-        user (str): username that tries to login
-        hashed_password (str): the password the user tries to login with
-
-    Returns:
-        bool: True if the login was successful, False if not
-    """
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    if salt is None:
-        return False
-    hashed_password = salt + hashed_password
-    password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-    if password == hashed_password:
-        return True
-    else:
-        return False
-
-
-
-def query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]] -
-
-

Query the Database for the sent query.

-

Args

-
-
query : str
-
The query to be executed
-
args : Tuple, optional
-
The arguments for the query. Defaults to ().
-
one : bool, optional
-
Return the first result only. Defaults to False.
-
-

Returns

-

Union[Typle|List[Tuple]]: Returns the result of the query

-
- -Expand source code - -
def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-    """
-    Query the Database for the sent query.
-
-    Args:
-        query (str): The query to be executed
-        args (Tuple, optional): The arguments for the query. Defaults to ().
-        one (bool, optional): Return the first result only. Defaults to False.
-
-    Returns:
-        Union[Typle|List[Tuple]]: Returns the result of the query
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Querying database with query {query}, args: {args}")
-    cursor.execute(query, args)
-    rv = cursor.fetchall()
-    conn.commit()
-    self.close_connection(conn)
-    return (rv[0] if rv else None) if one else rv
-
-
-
-def recreateFile(self, filename: str, app_id: Union[str, int], filetype: str) ‑> str -
-
-

Recreate a file from the database

-

Args

-
-
filename : str
-
the name of the file
-
app_id : Union[str,int]
-
the id of the apparat
-
filetype : str
-
the extension of the file to be created
-
-

Returns

-
-
str
-
The filename of the recreated file
-
-
- -Expand source code - -
def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
-    """Recreate a file from the database
-
-    Args:
-        filename (str): the name of the file
-        app_id (Union[str,int]): the id of the apparat
-        filetype (str): the extension of the file to be created
-
-    Returns:
-        str: The filename of the recreated file 
-    """
-    blob = self.getBlob(filename, app_id)
-    tempdir = config.database.tempdir
-    tempdir = tempdir.replace("~", str(Path.home()))
-    tempdir_path = Path(tempdir)        
-    if not os.path.exists(tempdir_path):
-        os.mkdir(tempdir_path)
-    file = tempfile.NamedTemporaryFile(
-        delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-    )
-    file.write(blob)
-    print("file created")
-    return file.name
-
-
-
-def searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]] -
-
-

Search a book in the database based on the sent data.

-

Args

-
-
data : dict[str, str]
-
A dictionary containing the data to be searched for. The dictionary can contain the following:
-
-
    -
  • signature: The signature of the book
  • -
  • title: The title of the book
  • -
-

Returns

-
-
list[tuple[BookData, int]]
-
A list of tuples containing the wrapped Metadata and the id of the book
-
-
- -Expand source code - -
def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-    """
-    Search a book in the database based on the sent data.
-
-    Args:
-        data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-        - signature: The signature of the book
-        - title: The title of the book
-
-    Returns:
-        list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-    """
-    rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-    ic(rdata, len(rdata))
-    mode = 0
-    if len(data)== 1:
-        if "signature" in data.keys():
-            mode = 1
-        elif "title" in data.keys():
-            mode = 2
-    elif len(data) == 2:
-        mode = 3
-    else:
-        return None
-    ret = []
-    for book in rdata:
-        bookdata = load_pickle(book[1])
-        app_id = book[2]
-        prof_id = book[3]
-        if mode == 1:
-            if data["signature"] in bookdata.signature:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 2:
-            if data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 3:
-            if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-    ic(ret)
-    return ret
-
-
-
-def setAvailability(self, book_id: str, available: str) -
-
-

Set the availability of a book in the database

-

Args

-
-
book_id : str
-
The id of the book
-
available : str
-
The availability of the book
-
-
- -Expand source code - -
def setAvailability(self, book_id:str, available:str):
-    """
-    Set the availability of a book in the database
-
-    Args:
-        book_id (str): The id of the book
-        available (str): The availability of the book
-    """
-    self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-
-
-
-def setNewSemesterDate(self, app_id: Union[str, int], newDate, dauerapp=False) -
-
-

Set the new semester date for an apparat

-

Args

-
-
app_id : Union[str,int]
-
the id of the apparat
-
newDate : str
-
the new date
-
dauerapp : bool, optional
-
if the apparat was changed to dauerapparat. Defaults to False.
-
-
- -Expand source code - -
def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
-    """Set the new semester date for an apparat
-
-    Args:
-        app_id (Union[str,int]): the id of the apparat
-        newDate (str): the new date
-        dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
-    """
-    date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-    if dauerapp:
-        self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
-    else:
-        self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
-
-
-
-def statistic_request(self, **kwargs: Any) -
-
-

Take n amount of kwargs and return the result of the query

-
- -Expand source code - -
def statistic_request(self, **kwargs: Any):
-    """Take n amount of kwargs and return the result of the query
-    """
-    def __query(query):
-        """execute the query and return the result
-
-        Args:
-            query (str): the constructed query
-
-        Returns:
-            list: the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        result = cursor.execute(query).fetchall()
-        for result_a in result:
-            orig_value = result_a
-            prof_name = self.getProfNameById(result_a[2])
-            # replace the prof_id with the prof_name
-            result_a = list(result_a)
-            result_a[2] = prof_name
-            result_a = tuple(result_a)
-            result[result.index(orig_value)] = result_a
-        self.close_connection(conn)
-        return result
-    if "deletable" in kwargs.keys():
-        query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-        return __query(query)
-    if "dauer" in kwargs.keys():
-        kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-    query = "SELECT * FROM semesterapparat WHERE "
-    for key, value in kwargs.items() if kwargs.items() is not None else {}:
-        print(key, value)
-        query += f"{key}='{value}' AND "
-        print(query)
-    # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-    if "deletesemester" in kwargs.keys():
-        query = query.replace(
-            f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-        )
-    if "endsemester" in kwargs.keys():
-        if "erstellsemester" in kwargs.keys():
-            query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-            query = query.replace(
-                f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-            )
-        else:
-            query = query.replace(
-                f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-            )
-            print("replaced")
-        query = query.replace(
-            "xyz",
-            f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-        )
-    # remove all x="" parts from the query where x is a key in kwargs
-    query = query[:-5]
-    print(query)
-    return __query(query)
-
-
-
-def updateApparat(self, apparat_data: src.logic.dataclass.ApparatData) -
-
-

Update an apparat in the database

-

Args

-
-
apparat_data : ApparatData
-
the new metadata of the apparat
-
-
- -Expand source code - -
def updateApparat(self, apparat_data:ApparatData):
-    """Update an apparat in the database
-
-    Args:
-        apparat_data (ApparatData): the new metadata of the apparat
-    """
-    query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-    params = (
-        apparat_data.appname,
-        apparat_data.app_fach,
-        apparat_data.dauerapp,
-        self.getProfId(apparat_data.profname),
-        apparat_data.appnr,        
-    )
-    self.query_db(query, params)
-
-
-
-def updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData) -
-
-

Update the bookdata in the database

-

Args

-
-
book_id : str
-
The id of the book
-
bookdata : BookData
-
The new metadata of the book
-
-
- -Expand source code - -
def updateBookdata(self, book_id, bookdata:BookData):
-    """
-    Update the bookdata in the database
-
-    Args:
-        book_id (str): The id of the book
-        bookdata (BookData): The new metadata of the book
-    """
-    self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-
-
-
-def updateFacultyMember(self, data: dict, oldlname: str, oldfname: str) -
-
-

update the data of a faculty member

-

Args

-
-
data : dict
-
a dictionary containing the data to be updated
-
oldlname : str
-
the old last name of the faculty member
-
oldfname : str
-
the old first name of the faculty member
-
-
- -Expand source code - -
def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
-    """update the data of a faculty member
-
-    Args:
-        data (dict): a dictionary containing the data to be updated
-        oldlname (str): the old last name of the faculty member
-        oldfname (str): the old first name of the faculty member
-    """
-    placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-    query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-    data["oldlname"] = oldlname
-    data["oldfname"] = oldfname
-    self.query_db(query, data)
-
-
-
-def updateUser(self, username, data: dict[str, str]) -
-
-

changge the data of a user

-

Args

-
-
username : str
-
the username of the user
-
data : dict[str, str]
-
the data to be changed
-
-
- -Expand source code - -
def updateUser(self, username, data:dict[str, str]):
-    """changge the data of a user
-
-    Args:
-        username (str): the username of the user
-        data (dict[str, str]): the data to be changed
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    query = "UPDATE user SET "
-    for key,value in data.items():
-        if key == "username":
-            continue
-        query += f"{key}='{value}',"
-    query = query[:-1]
-    query += " WHERE username=?"
-    params = (username,)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/db.html b/docs/db.html deleted file mode 100644 index f2b125f..0000000 --- a/docs/db.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - -db API documentation - - - - - - - - - - - -
-
-
-

Module db

-
-
-

Module db provides the database schema for the semesterapparat application.

-
-
-
- -Expand source code - -
CREATE_TABLE_APPARAT = """CREATE TABLE semesterapparat (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    name TEXT,
-    prof_id INTEGER,
-    fach TEXT,
-    appnr INTEGER,
-    erstellsemester TEXT,
-    verlängert_am TEXT,
-    dauer BOOLEAN,
-    verlängerung_bis TEXT,
-    deletion_status INTEGER,
-    deleted_date TEXT,
-    apparat_id_adis INTEGER,
-    prof_id_adis INTEGER,
-    konto INTEGER REFERENCES app_kontos (id),
-    FOREIGN KEY (prof_id) REFERENCES prof (id)
-  )"""
-CREATE_TABLE_MEDIA = """CREATE TABLE media (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    bookdata BLOB,
-    app_id INTEGER,
-    prof_id INTEGER,
-    deleted INTEGER DEFAULT (0),
-    available BOOLEAN,
-    reservation BOOLEAN,
-    FOREIGN KEY (prof_id) REFERENCES prof (id),
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-  )"""
-CREATE_TABLE_APPKONTOS = """CREATE TABLE app_kontos (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    app_id INTEGER,
-    konto INTEGER,
-    passwort TEXT,
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-    )"""
-CREATE_TABLE_FILES = """CREATE TABLE files (
-    id INTEGER PRIMARY KEY,
-    filename TEXT,
-    fileblob BLOB,
-    app_id INTEGER,
-    filetyp TEXT,
-    prof_id INTEGER REFERENCES prof (id),
-    FOREIGN KEY (app_id) REFERENCES semesterapparat (id)
-    )"""
-CREATE_TABLE_MESSAGES = """CREATE TABLE messages (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    created_at date NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    message TEXT NOT NULL,
-    remind_at date NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    user_id INTEGER NOT NULL,
-    appnr INTEGER,
-    FOREIGN KEY (user_id) REFERENCES user (id)
-  )"""
-CREATE_TABLE_PROF = """CREATE TABLE prof (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    titel TEXT,
-    fname TEXT,
-    lname TEXT,
-    fullname TEXT NOT NULL UNIQUE,
-    mail TEXT,
-    telnr TEXT
-  )"""
-CREATE_TABLE_USER = """CREATE TABLE user (
-    id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
-    created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    username TEXT NOT NULL UNIQUE,
-    password TEXT NOT NULL,
-    salt TEXT NOT NULL,
-    role TEXT NOT NULL,
-    email TEXT UNIQUE,
-    name TEXT
-  )"""
-CREATE_TABLE_SUBJECTS = """CREATE TABLE subjects (
-    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-    name TEXT NOT NULL UNIQUE
-)"""
-
-
-
-
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/documentation/database.html b/documentation/database.html deleted file mode 100644 index 65ce4cf..0000000 --- a/documentation/database.html +++ /dev/null @@ -1,3071 +0,0 @@ - - - - - - -database API documentation - - - - - - - - - - - -
-
-
-

Module database

-
-
-
- -Expand source code - -
import datetime
-import os
-import re
-import sqlite3 as sql
-import tempfile
-from src.logic.log import MyLogger
-#from icecream import ic
-from typing import List, Tuple, Dict, Any, Optional, Union
-from pathlib import Path
-from omegaconf import OmegaConf
-from src.backend.db import CREATE_TABLE_APPARAT, CREATE_TABLE_MESSAGES, CREATE_TABLE_MEDIA, CREATE_TABLE_APPKONTOS, CREATE_TABLE_FILES, CREATE_TABLE_PROF, CREATE_TABLE_USER, CREATE_TABLE_SUBJECTS
-from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
-from src.logic.dataclass import ApparatData, BookData
-from src.errors import NoResultError, AppPresentError
-from src.utils import load_pickle, dump_pickle,create_blob
-config = OmegaConf.load("config.yaml")
-logger = MyLogger(__name__)
-
-
-class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        #ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        #ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id, prof_id)->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id: int, prof_id):
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename, app_id,filetype):
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:int, prof_id:int)->list[tuple]:
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self):
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user, appnr):
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr))
-    def getMessages(self, date:str):
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:int,add_title:bool=False):
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:int):
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str):
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str):
-        """
-        getProfId _summary_
-
-        :param prof_name: _description_
-        :type prof_name: str
-        :return: _description_
-        :rtype: _type_
-        """
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:int, fields:List[str]):
-        """
-        getSpecificProfData _summary_
-        
-        
-        
-        Args:
-        ----
-            - prof_id (int): _description_
-            - fields (List[str]): _description_
-        
-        Returns:
-        -------
-            - _type_: _description_
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self):
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0):
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """
-        getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers
-        
-        
-        
-        Returns:
-        -------
-            - number(List[int]): a list of all currently used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, appnr, newDate, dauerapp=False):
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr))
-    def getApparatId(self, apparat_name):
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int:
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            return AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        #ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:int)->list[tuple]:
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict:
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, appnr, semester):
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr)) 
-    def isEternal(self, id):
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id, prof_id):
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name):
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, apparat_id):
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        def __query(query):
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self):
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self):
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user):
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """Create a user based on passed data.
-
-        Args:
-        ----
-            - username (str): Username to be used
-            - password (str): the salted password
-            - role (str): Role of the user
-            - salt (str): a random salt for the user
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str):
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data, oldlname, oldfname):
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Database -(db_path: str = None) -
-
-

Initialize the database and create the tables if they do not exist.

-

Default constructor for the database class

-

Args

-
-
db_path : str, optional
-
Optional Path for testing / specific purposes. Defaults to None.
-
-
- -Expand source code - -
class Database:
-    """
-    Initialize the database and create the tables if they do not exist.
-    """
-    def __init__(self, db_path: str = None):
-        """
-        Default constructor for the database class
-
-        Args:
-            db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
-        """
-        if db_path is None:
-            self.db_path = config.database.path + config.database.name
-            self.db_path = self.db_path.replace("~", str(Path.home()))
-        else:
-            self.db_path = db_path
-        if self.get_db_contents() is None:
-            logger.log_critical("Database does not exist, creating tables")
-            self.create_tables()
-
-    def get_db_contents(self)->Union[List[Tuple], None]:
-        """
-        Get the contents of the 
-
-        Returns:
-            Union[List[Tuple], None]: _description_
-        """
-        try:
-            with sql.connect(self.db_path) as conn:
-                cursor = conn.cursor()
-                cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-                return cursor.fetchall()
-        except sql.OperationalError:
-            return None
-
-    def connect(self)->sql.Connection:
-        """
-        Connect to the database
-
-        Returns:
-            sql.Connection: The active connection to the database
-        """
-        return sql.connect(self.db_path)
-
-    def close_connection(self, conn: sql.Connection):
-        """
-        closes the connection to the database
-        
-        Args:
-        ----
-            - conn (sql.Connection): the connection to be closed
-        """
-        conn.close()
-
-    def create_tables(self):
-        """
-        Create the tables in the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        cursor.execute(CREATE_TABLE_APPARAT)
-        cursor.execute(CREATE_TABLE_MESSAGES)
-        cursor.execute(CREATE_TABLE_MEDIA)
-        cursor.execute(CREATE_TABLE_APPKONTOS)
-        cursor.execute(CREATE_TABLE_FILES)
-        cursor.execute(CREATE_TABLE_PROF)
-        cursor.execute(CREATE_TABLE_USER)
-        cursor.execute(CREATE_TABLE_SUBJECTS)
-        conn.commit()
-        self.close_connection(conn)
-
-    def insertInto(self, query:str, params:Tuple) -> None:
-        """
-        Insert sent data into the database
-
-        Args:
-            query (str): The query to be executed
-            params (Tuple): the parameters to be inserted into the database
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Inserting {params} into database with query {query}")
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-
-    def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-        """
-        Query the Database for the sent query.
-
-        Args:
-            query (str): The query to be executed
-            args (Tuple, optional): The arguments for the query. Defaults to ().
-            one (bool, optional): Return the first result only. Defaults to False.
-
-        Returns:
-            Union[Typle|List[Tuple]]: Returns the result of the query
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        logger.log_info(f"Querying database with query {query}, args: {args}")
-        cursor.execute(query, args)
-        rv = cursor.fetchall()
-        conn.commit()
-        self.close_connection(conn)
-        return (rv[0] if rv else None) if one else rv
-
-    # Books
-    def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str):
-        """
-        Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-        Args:
-            bookdata (BookData): The metadata of the book to be added
-            app_id (str): The apparat id where the book should be added to
-            prof_id (str): The id of the professor where the book should be added to.
-        """
-        conn = self.connect()
-        cursor = conn.cursor()
-        t_query = (
-            f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-        )
-        # print(t_query)
-        result = cursor.execute(t_query).fetchall()
-        result = [load_pickle(i[0]) for i in result]
-        if bookdata in result:
-            print("Bookdata already in database")
-            # check if the book was deleted in the apparat
-            query = (
-                "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-            )
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            result = cursor.execute(query, params).fetchone()
-            if result[0] == 1:
-                print("Book was deleted, updating bookdata")
-                query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-                params = (app_id, prof_id, dump_pickle(bookdata))
-                cursor.execute(query, params)
-                conn.commit()
-            return
-
-        query = (
-            "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-        )
-        converted = dump_pickle(bookdata)
-        params = (converted, app_id, prof_id, 0)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int:
-        """
-        Get a book id based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            int: The id of the book
-        """
-        result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [(load_pickle(i[0]),i[1]) for i in result]
-        book = [i for i in books if i[0].signature == signature][0][1]
-        return book
-    def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData:
-        """
-        Get the book based on the signature of the book.
-
-        Args:
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-            signature (str): The signature of the book
-
-        Returns:
-            BookData: The total metadata of the book wrapped in a BookData object
-        """
-        result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-        books = [load_pickle(i[0]) for i in result]
-        book = [i for i in books if i.signature == signature][0]
-        return book
-    def getLastBookId(self)->int:
-        """
-        Get the last book id in the database
-
-        Returns:
-            int: ID of the last book in the database
-        """
-        return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-    def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-        """
-        Search a book in the database based on the sent data.
-
-        Args:
-            data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-            - signature: The signature of the book
-            - title: The title of the book
-
-        Returns:
-            list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-        """
-        rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-        #ic(rdata, len(rdata))
-        mode = 0
-        if len(data)== 1:
-            if "signature" in data.keys():
-                mode = 1
-            elif "title" in data.keys():
-                mode = 2
-        elif len(data) == 2:
-            mode = 3
-        else:
-            return None
-        ret = []
-        for book in rdata:
-            bookdata = load_pickle(book[1])
-            app_id = book[2]
-            prof_id = book[3]
-            if mode == 1:
-                if data["signature"] in bookdata.signature:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 2:
-                if data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-            elif mode == 3:
-                if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                    ret.append((bookdata,app_id,prof_id))
-        #ic(ret)
-        return ret
-    def setAvailability(self, book_id:str, available:str):
-        """
-        Set the availability of a book in the database
-
-        Args:
-            book_id (str): The id of the book
-            available (str): The availability of the book
-        """
-        self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-    def getBookId(self, bookdata:BookData, app_id, prof_id)->int:
-        """
-        Get the id of a book based on the metadata of the book
-
-        Args:
-            bookdata (BookData): The wrapped metadata of the book
-            app_id (str): The apparat id the book should be associated with
-            prof_id (str): The professor id the book should be associated with
-
-        Returns:
-            int: ID of the book
-        """
-        result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-        return result[0]
-    def getBook(self,book_id:int)->BookData:
-        """
-        Get the book based on the id in the database
-
-        Args:
-            book_id (int): The id of the book
-
-        Returns:
-            BookData: The metadata of the book wrapped in a BookData object
-        """
-        return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-    def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]:
-        """
-        Get the Books based on the apparat id and the professor id
-
-        Args:
-            app_id (str): The ID of the apparat
-            prof_id (str): The ID of the professor
-            deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-        Returns:
-            list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-        """
-        qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-        ret_result = []
-        for result_a in qdata:
-            data = {"id": int, "bookdata": BookData, "available": int}
-            data["id"] = result_a[0]
-            data["bookdata"] = load_pickle(result_a[1])
-            data["available"] = result_a[2]
-            ret_result.append(data)
-        return ret_result
-
-    def updateBookdata(self, book_id, bookdata:BookData):
-        """
-        Update the bookdata in the database
-
-        Args:
-            book_id (str): The id of the book
-            bookdata (BookData): The new metadata of the book
-        """
-        self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-    def deleteBook(self, book_id):
-        """
-        Delete a book from the database
-
-        Args:
-            book_id (str): ID of the book
-        """
-        self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-    # File Interactions
-    def getBlob(self, filename, app_id):
-        """
-        Get a blob from the database
-
-        Args:
-            filename (str): The name of the file
-            app_id (str): ID of the apparat
-
-        Returns:
-            bytes: The file stored in 
-        """
-        return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-    def insertFile(self, file: list[dict], app_id: int, prof_id):
-        for f in file:
-            filename = f["name"]
-            path = f["path"]
-            filetyp = f["type"]
-            if path == "Database":
-                continue
-            blob = create_blob(path)
-            query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-            self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-    def recreateFile(self, filename, app_id,filetype):
-        blob = self.getBlob(filename, app_id)
-        tempdir = config.database.tempdir
-        tempdir = tempdir.replace("~", str(Path.home()))
-        tempdir_path = Path(tempdir)        
-        if not os.path.exists(tempdir_path):
-            os.mkdir(tempdir_path)
-        file = tempfile.NamedTemporaryFile(
-            delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-        )
-        file.write(blob)
-        print("file created")
-        return file.name
-    def getFiles(self, app_id:int, prof_id:int)->list[tuple]:
-        return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-    def getSemersters(self):
-        data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-        return [i[0] for i in data]
-
-    def getSubjects(self):
-        return self.query_db("SELECT * FROM subjects")
-
-    # Messages
-    def addMessage(self, message:dict,user, appnr):
-        def __getUserId(user):
-            return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-        user_id = __getUserId(user)
-        self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr))
-    def getMessages(self, date:str):
-        def __get_user_name(user_id):
-            return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-        messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-        ret = [
-            {
-                "message": i[2],
-                "user": __get_user_name(i[4]),
-                "appnr": i[5],
-                "id": i[0]
-            }
-            for i in messages
-        ]
-        return ret
-    def deleteMessage(self, message_id):
-        self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-    # Prof data
-    def getProfNameById(self, prof_id:int,add_title:bool=False):
-        prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-        if add_title:
-            return f"{self.getTitleById(prof_id)}{prof[0]}"
-        else:
-            return prof[0]
-    def getTitleById(self, prof_id:int):
-        title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-        return f"{title} " if title is not None else ""
-    def getProfByName(self, prof_name:str):
-        return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-    def getProfId(self, prof_name:str):
-        """
-        getProfId _summary_
-
-        :param prof_name: _description_
-        :type prof_name: str
-        :return: _description_
-        :rtype: _type_
-        """
-        data = self.getProfByName(prof_name.replace(",", ""))
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def getSpecificProfData(self, prof_id:int, fields:List[str]):
-        """
-        getSpecificProfData _summary_
-        
-        
-        
-        Args:
-        ----
-            - prof_id (int): _description_
-            - fields (List[str]): _description_
-        
-        Returns:
-        -------
-            - _type_: _description_
-        """
-        query = "SELECT "
-        for field in fields:
-            query += f"{field},"
-        query = query[:-1]
-        query += " FROM prof WHERE id=?"
-        return self.query_db(query, (prof_id,), one=True)[0]
-    def getProfData(self, profname:str):
-        
-        data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-        return data
-    def createProf(self, prof_details:dict):
-        prof_title = prof_details["prof_title"]
-        prof_fname = prof_details["profname"].split(",")[1]
-        prof_fname = prof_fname.strip()
-        prof_lname = prof_details["profname"].split(",")[0]
-        prof_lname = prof_lname.strip()
-        prof_fullname = prof_details["profname"].replace(",", "")
-        prof_mail = prof_details["prof_mail"]
-        prof_tel = prof_details["prof_tel"]
-        params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-        query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-        self.insertInto(query=query, params=params)
-    def getProfs(self):
-        return self.query_db("SELECT * FROM prof")
-
-    # Apparat
-    def getAllAparats(self,deleted=0):
-        return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-    def getApparatData(self, appnr, appname)->ApparatData:
-
-        result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-        if result is None:
-            raise NoResultError("No result found")
-        apparat = ApparatData()
-        apparat.appname = result[1]
-        apparat.appnr = result[4]
-        apparat.dauerapp = True if result[7] == 1 else False
-        prof_data = self.getProfData(self.getProfNameById(result[2]))
-        apparat.profname = self.getProfNameById(result[2])
-        apparat.prof_mail = prof_data[0]
-        apparat.prof_tel = prof_data[1]
-        apparat.prof_title = prof_data[2]
-        apparat.app_fach = result[3]
-        apparat.erstellsemester = result[5]
-        apparat.semester = result[8]
-        apparat.deleted = result[9]
-        apparat.apparat_adis_id = result[11]
-        apparat.prof_adis_id = result[12]
-        return apparat
-    def getUnavailableApparatNumbers(self)->List[int]:
-        """
-        getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers
-        
-        
-        
-        Returns:
-        -------
-            - number(List[int]): a list of all currently used apparat numbers
-        """
-        numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-        numbers = [i[0] for i in numbers]
-        logger.log_info(f"Currently used apparat numbers: {numbers}")
-        return numbers
-    def setNewSemesterDate(self, appnr, newDate, dauerapp=False):
-        date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-        if dauerapp:
-            self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr))
-        else:
-            self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr))
-    def getApparatId(self, apparat_name):
-        data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-        if data is None:
-            return None
-        else:
-            return data[0]
-    def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int:
-        prof_id = self.getProfId(apparat.profname)
-        app_id = self.getApparatId(apparat.appname)
-        if app_id:
-            return AppPresentError(app_id)
-
-        self.createProf(apparat.get_prof_details())
-        prof_id = self.getProfId(apparat.profname)
-        #ic(prof_id)
-        query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-        logger.log_info(query)
-        self.query_db(query)
-        return self.getApparatId(apparat.appname)
-    def getApparatsByProf(self, prof_id:int)->list[tuple]:
-        return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-    def getApparatsBySemester(self, semester:str)->dict:
-        data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-        conn = self.connect()
-        cursor = conn.cursor()
-        c_tmp = []
-        for i in data:
-            c_tmp.append((i[0], self.getProfNameById(i[1])))
-        query = (
-            f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-        )
-        result = cursor.execute(query).fetchall()
-        d_tmp = []
-        for i in result:
-            d_tmp.append((i[0], self.getProfNameById(i[1])))
-        # group the apparats by prof
-        c_ret = {}
-        for i in c_tmp:
-            if i[1] not in c_ret.keys():
-                c_ret[i[1]] = [i[0]]
-            else:
-                c_ret[i[1]].append(i[0])
-        d_ret = {}
-        for i in d_tmp:
-            if i[1] not in d_ret.keys():
-                d_ret[i[1]] = [i[0]]
-            else:
-                d_ret[i[1]].append(i[0])
-        self.close_connection(conn)
-        return {"created": c_ret, "deleted": d_ret}
-    def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-        conn = self.connect()
-        cursor = conn.cursor()
-        semesters = self.getSemersters()
-        created = []
-        deleted = []
-        for semester in semesters:
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-            result = cursor.execute(query).fetchone()
-            created.append(result[0])
-            query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-            result = cursor.execute(query).fetchone()
-            deleted.append(result[0])
-        # store data in a tuple
-        ret = []
-        e_tuple = ()
-        for sem in semesters:
-            e_tuple = (
-                sem,
-                created[semesters.index(sem)],
-                deleted[semesters.index(sem)],
-            )
-            ret.append(e_tuple)
-        self.close_connection(conn)
-        return ret 
-    def deleteApparat(self, appnr, semester):
-        self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr)) 
-    def isEternal(self, id):
-        return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-    def getApparatName(self, app_id, prof_id):
-        return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-    def updateApparat(self, apparat_data:ApparatData):
-        query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-        params = (
-            apparat_data.appname,
-            apparat_data.app_fach,
-            apparat_data.dauerapp,
-            self.getProfId(apparat_data.profname),
-            apparat_data.appnr,        
-        )
-        self.query_db(query, params)
-    def checkApparatExists(self, apparat_name):
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-    def checkApparatExistsById(self, apparat_id):
-        return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False
-    # Statistics
-    def statistic_request(self, **kwargs: Any):
-        def __query(query):
-            conn = self.connect()
-            cursor = conn.cursor()
-            result = cursor.execute(query).fetchall()
-            for result_a in result:
-                orig_value = result_a
-                prof_name = self.getProfNameById(result_a[2])
-                # replace the prof_id with the prof_name
-                result_a = list(result_a)
-                result_a[2] = prof_name
-                result_a = tuple(result_a)
-                result[result.index(orig_value)] = result_a
-            self.close_connection(conn)
-            return result
-        if "deletable" in kwargs.keys():
-            query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-            return __query(query)
-        if "dauer" in kwargs.keys():
-            kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-        query = "SELECT * FROM semesterapparat WHERE "
-        for key, value in kwargs.items() if kwargs.items() is not None else {}:
-            print(key, value)
-            query += f"{key}='{value}' AND "
-            print(query)
-        # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-        if "deletesemester" in kwargs.keys():
-            query = query.replace(
-                f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-            )
-        if "endsemester" in kwargs.keys():
-            if "erstellsemester" in kwargs.keys():
-                query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-                query = query.replace(
-                    f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-                )
-            else:
-                query = query.replace(
-                    f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-                )
-                print("replaced")
-            query = query.replace(
-                "xyz",
-                f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-            )
-        # remove all x="" parts from the query where x is a key in kwargs
-        query = query[:-5]
-        print(query)
-        return __query(query)
-
-    # Admin data
-    def getUser(self):
-        return self.query_db("SELECT * FROM user", one=True)
-    def getUsers(self):
-        return self.query_db("SELECT * FROM user")
-
-    def login(self, user, hashed_password):
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        if salt is None:
-            return False
-        hashed_password = salt + hashed_password
-        password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-        if password == hashed_password:
-            return True
-        else:
-            return False
-    def changePassword(self, user, new_password):
-        salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-        new_password = salt + new_password
-        self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-    def getRole(self, user):
-        return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-    def getRoles(self):
-        return self.query_db("SELECT role FROM user")
-    def checkUsername(self, user):
-        data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-        return True if data is not None else False
-    def createUser(self, user, password, role, salt):
-        """Create a user based on passed data.
-
-        Args:
-        ----
-            - username (str): Username to be used
-            - password (str): the salted password
-            - role (str): Role of the user
-            - salt (str): a random salt for the user
-        """
-        self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-    def deleteUser(self, user):
-        self.query_db("DELETE FROM user WHERE username=?", (user,))
-    def updateUser(self, username, data:dict[str, str]):
-        conn = self.connect()
-        cursor = conn.cursor()
-        query = "UPDATE user SET "
-        for key,value in data.items():
-            if key == "username":
-                continue
-            query += f"{key}='{value}',"
-        query = query[:-1]
-        query += " WHERE username=?"
-        params = (username,)
-        cursor.execute(query, params)
-        conn.commit()
-        self.close_connection(conn)
-    def getFacultyMember(self, name:str):
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-    def updateFacultyMember(self, data, oldlname, oldfname):
-        placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-        query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-        data["oldlname"] = oldlname
-        data["oldfname"] = oldfname
-        self.query_db(query, data)
-    def getFacultyMembers(self):
-        return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-

Methods

-
-
-def addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: str, prof_id: str) -
-
-

Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.

-

Args

-
-
bookdata : BookData
-
The metadata of the book to be added
-
app_id : str
-
The apparat id where the book should be added to
-
prof_id : str
-
The id of the professor where the book should be added to.
-
-
- -Expand source code - -
def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str):
-    """
-    Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
-    Args:
-        bookdata (BookData): The metadata of the book to be added
-        app_id (str): The apparat id where the book should be added to
-        prof_id (str): The id of the professor where the book should be added to.
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    t_query = (
-        f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
-    )
-    # print(t_query)
-    result = cursor.execute(t_query).fetchall()
-    result = [load_pickle(i[0]) for i in result]
-    if bookdata in result:
-        print("Bookdata already in database")
-        # check if the book was deleted in the apparat
-        query = (
-            "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
-        )
-        params = (app_id, prof_id, dump_pickle(bookdata))
-        result = cursor.execute(query, params).fetchone()
-        if result[0] == 1:
-            print("Book was deleted, updating bookdata")
-            query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
-            params = (app_id, prof_id, dump_pickle(bookdata))
-            cursor.execute(query, params)
-            conn.commit()
-        return
-
-    query = (
-        "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
-    )
-    converted = dump_pickle(bookdata)
-    params = (converted, app_id, prof_id, 0)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def addMessage(self, message: dict, user, appnr) -
-
-
-
- -Expand source code - -
def addMessage(self, message:dict,user, appnr):
-    def __getUserId(user):
-        return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
-    user_id = __getUserId(user)
-    self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr))
-
-
-
-def changePassword(self, user, new_password) -
-
-
-
- -Expand source code - -
def changePassword(self, user, new_password):
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    new_password = salt + new_password
-    self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
-
-
-
-def checkApparatExists(self, apparat_name) -
-
-
-
- -Expand source code - -
def checkApparatExists(self, apparat_name):
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
-
-
-
-def checkApparatExistsById(self, apparat_id) -
-
-
-
- -Expand source code - -
def checkApparatExistsById(self, apparat_id):
-    return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False
-
-
-
-def checkUsername(self, user) -
-
-
-
- -Expand source code - -
def checkUsername(self, user):
-    data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
-    return True if data is not None else False
-
-
-
-def close_connection(self, conn: sqlite3.Connection) -
-
-

closes the connection to the database

-

Args:

-
- conn (sql.Connection): the connection to be closed
-
-
- -Expand source code - -
def close_connection(self, conn: sql.Connection):
-    """
-    closes the connection to the database
-    
-    Args:
-    ----
-        - conn (sql.Connection): the connection to be closed
-    """
-    conn.close()
-
-
-
-def connect(self) ‑> sqlite3.Connection -
-
-

Connect to the database

-

Returns

-
-
sql.Connection
-
The active connection to the database
-
-
- -Expand source code - -
def connect(self)->sql.Connection:
-    """
-    Connect to the database
-
-    Returns:
-        sql.Connection: The active connection to the database
-    """
-    return sql.connect(self.db_path)
-
-
-
-def createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> Union[src.errors.DatabaseErrors.AppPresentError, ForwardRef(None), int] -
-
-
-
- -Expand source code - -
def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int:
-    prof_id = self.getProfId(apparat.profname)
-    app_id = self.getApparatId(apparat.appname)
-    if app_id:
-        return AppPresentError(app_id)
-
-    self.createProf(apparat.get_prof_details())
-    prof_id = self.getProfId(apparat.profname)
-    #ic(prof_id)
-    query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
-    logger.log_info(query)
-    self.query_db(query)
-    return self.getApparatId(apparat.appname)
-
-
-
-def createProf(self, prof_details: dict) -
-
-
-
- -Expand source code - -
def createProf(self, prof_details:dict):
-    prof_title = prof_details["prof_title"]
-    prof_fname = prof_details["profname"].split(",")[1]
-    prof_fname = prof_fname.strip()
-    prof_lname = prof_details["profname"].split(",")[0]
-    prof_lname = prof_lname.strip()
-    prof_fullname = prof_details["profname"].replace(",", "")
-    prof_mail = prof_details["prof_mail"]
-    prof_tel = prof_details["prof_tel"]
-    params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
-    query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
-    self.insertInto(query=query, params=params)
-
-
-
-def createUser(self, user, password, role, salt) -
-
-

Create a user based on passed data.

-

Args:

-
- username (str): Username to be used
-- password (str): the salted password
-- role (str): Role of the user
-- salt (str): a random salt for the user
-
-
- -Expand source code - -
def createUser(self, user, password, role, salt):
-    """Create a user based on passed data.
-
-    Args:
-    ----
-        - username (str): Username to be used
-        - password (str): the salted password
-        - role (str): Role of the user
-        - salt (str): a random salt for the user
-    """
-    self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
-
-
-
-def create_tables(self) -
-
-

Create the tables in the database

-
- -Expand source code - -
def create_tables(self):
-    """
-    Create the tables in the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    cursor.execute(CREATE_TABLE_APPARAT)
-    cursor.execute(CREATE_TABLE_MESSAGES)
-    cursor.execute(CREATE_TABLE_MEDIA)
-    cursor.execute(CREATE_TABLE_APPKONTOS)
-    cursor.execute(CREATE_TABLE_FILES)
-    cursor.execute(CREATE_TABLE_PROF)
-    cursor.execute(CREATE_TABLE_USER)
-    cursor.execute(CREATE_TABLE_SUBJECTS)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def deleteApparat(self, appnr, semester) -
-
-
-
- -Expand source code - -
def deleteApparat(self, appnr, semester):
-    self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr)) 
-
-
-
-def deleteBook(self, book_id) -
-
-

Delete a book from the database

-

Args

-
-
book_id : str
-
ID of the book
-
-
- -Expand source code - -
def deleteBook(self, book_id):
-    """
-    Delete a book from the database
-
-    Args:
-        book_id (str): ID of the book
-    """
-    self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
-
-
-def deleteMessage(self, message_id) -
-
-
-
- -Expand source code - -
def deleteMessage(self, message_id):
-    self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
-
-
-def deleteUser(self, user) -
-
-
-
- -Expand source code - -
def deleteUser(self, user):
-    self.query_db("DELETE FROM user WHERE username=?", (user,))
-
-
-
-def getAllAparats(self, deleted=0) -
-
-
-
- -Expand source code - -
def getAllAparats(self,deleted=0):
-    return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
-
-
-
-def getApparatCountBySemester(self) ‑> tuple[list[str], list[int]] -
-
-
-
- -Expand source code - -
def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
-    conn = self.connect()
-    cursor = conn.cursor()
-    semesters = self.getSemersters()
-    created = []
-    deleted = []
-    for semester in semesters:
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
-        result = cursor.execute(query).fetchone()
-        created.append(result[0])
-        query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
-        result = cursor.execute(query).fetchone()
-        deleted.append(result[0])
-    # store data in a tuple
-    ret = []
-    e_tuple = ()
-    for sem in semesters:
-        e_tuple = (
-            sem,
-            created[semesters.index(sem)],
-            deleted[semesters.index(sem)],
-        )
-        ret.append(e_tuple)
-    self.close_connection(conn)
-    return ret 
-
-
-
-def getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData -
-
-
-
- -Expand source code - -
def getApparatData(self, appnr, appname)->ApparatData:
-
-    result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
-    if result is None:
-        raise NoResultError("No result found")
-    apparat = ApparatData()
-    apparat.appname = result[1]
-    apparat.appnr = result[4]
-    apparat.dauerapp = True if result[7] == 1 else False
-    prof_data = self.getProfData(self.getProfNameById(result[2]))
-    apparat.profname = self.getProfNameById(result[2])
-    apparat.prof_mail = prof_data[0]
-    apparat.prof_tel = prof_data[1]
-    apparat.prof_title = prof_data[2]
-    apparat.app_fach = result[3]
-    apparat.erstellsemester = result[5]
-    apparat.semester = result[8]
-    apparat.deleted = result[9]
-    apparat.apparat_adis_id = result[11]
-    apparat.prof_adis_id = result[12]
-    return apparat
-
-
-
-def getApparatId(self, apparat_name) -
-
-
-
- -Expand source code - -
def getApparatId(self, apparat_name):
-    data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getApparatName(self, app_id, prof_id) -
-
-
-
- -Expand source code - -
def getApparatName(self, app_id, prof_id):
-    return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
-
-
-
-def getApparatsByProf(self, prof_id: int) ‑> list[tuple] -
-
-
-
- -Expand source code - -
def getApparatsByProf(self, prof_id:int)->list[tuple]:
-    return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
-
-
-
-def getApparatsBySemester(self, semester: str) ‑> dict -
-
-
-
- -Expand source code - -
def getApparatsBySemester(self, semester:str)->dict:
-    data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
-    conn = self.connect()
-    cursor = conn.cursor()
-    c_tmp = []
-    for i in data:
-        c_tmp.append((i[0], self.getProfNameById(i[1])))
-    query = (
-        f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
-    )
-    result = cursor.execute(query).fetchall()
-    d_tmp = []
-    for i in result:
-        d_tmp.append((i[0], self.getProfNameById(i[1])))
-    # group the apparats by prof
-    c_ret = {}
-    for i in c_tmp:
-        if i[1] not in c_ret.keys():
-            c_ret[i[1]] = [i[0]]
-        else:
-            c_ret[i[1]].append(i[0])
-    d_ret = {}
-    for i in d_tmp:
-        if i[1] not in d_ret.keys():
-            d_ret[i[1]] = [i[0]]
-        else:
-            d_ret[i[1]].append(i[0])
-    self.close_connection(conn)
-    return {"created": c_ret, "deleted": d_ret}
-
-
-
-def getBlob(self, filename, app_id) -
-
-

Get a blob from the database

-

Args

-
-
filename : str
-
The name of the file
-
app_id : str
-
ID of the apparat
-
-

Returns

-
-
bytes
-
The file stored in
-
-
- -Expand source code - -
def getBlob(self, filename, app_id):
-    """
-    Get a blob from the database
-
-    Args:
-        filename (str): The name of the file
-        app_id (str): ID of the apparat
-
-    Returns:
-        bytes: The file stored in 
-    """
-    return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
-
-
-
-def getBook(self, book_id: int) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the id in the database

-

Args

-
-
book_id : int
-
The id of the book
-
-

Returns

-
-
BookData
-
The metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBook(self,book_id:int)->BookData:
-    """
-    Get the book based on the id in the database
-
-    Args:
-        book_id (int): The id of the book
-
-    Returns:
-        BookData: The metadata of the book wrapped in a BookData object
-    """
-    return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
-
-
-
-def getBookBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> src.logic.dataclass.BookData -
-
-

Get the book based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
BookData
-
The total metadata of the book wrapped in a BookData object
-
-
- -Expand source code - -
def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData:
-    """
-    Get the book based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        BookData: The total metadata of the book wrapped in a BookData object
-    """
-    result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [load_pickle(i[0]) for i in result]
-    book = [i for i in books if i.signature == signature][0]
-    return book
-
-
-
-def getBookId(self, bookdata: src.logic.dataclass.BookData, app_id, prof_id) ‑> int -
-
-

Get the id of a book based on the metadata of the book

-

Args

-
-
bookdata : BookData
-
The wrapped metadata of the book
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
-

Returns

-
-
int
-
ID of the book
-
-
- -Expand source code - -
def getBookId(self, bookdata:BookData, app_id, prof_id)->int:
-    """
-    Get the id of a book based on the metadata of the book
-
-    Args:
-        bookdata (BookData): The wrapped metadata of the book
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-
-    Returns:
-        int: ID of the book
-    """
-    result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
-    return result[0]
-
-
-
-def getBookIdBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> int -
-
-

Get a book id based on the signature of the book.

-

Args

-
-
app_id : str
-
The apparat id the book should be associated with
-
prof_id : str
-
The professor id the book should be associated with
-
signature : str
-
The signature of the book
-
-

Returns

-
-
int
-
The id of the book
-
-
- -Expand source code - -
def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int:
-    """
-    Get a book id based on the signature of the book.
-
-    Args:
-        app_id (str): The apparat id the book should be associated with
-        prof_id (str): The professor id the book should be associated with
-        signature (str): The signature of the book
-
-    Returns:
-        int: The id of the book
-    """
-    result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-    books = [(load_pickle(i[0]),i[1]) for i in result]
-    book = [i for i in books if i[0].signature == signature][0][1]
-    return book
-
-
-
-def getBooks(self, app_id, prof_id, deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]] -
-
-

Get the Books based on the apparat id and the professor id

-

Args

-
-
app_id : str
-
The ID of the apparat
-
prof_id : str
-
The ID of the professor
-
deleted : int, optional
-
The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-

Returns

-
-
list[dict[int, BookData, int]]
-
A list of dictionaries containing the id, the metadata of the book and the availability of the book
-
-
- -Expand source code - -
def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]:
-    """
-    Get the Books based on the apparat id and the professor id
-
-    Args:
-        app_id (str): The ID of the apparat
-        prof_id (str): The ID of the professor
-        deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
-    Returns:
-        list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
-    """
-    qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
-    ret_result = []
-    for result_a in qdata:
-        data = {"id": int, "bookdata": BookData, "available": int}
-        data["id"] = result_a[0]
-        data["bookdata"] = load_pickle(result_a[1])
-        data["available"] = result_a[2]
-        ret_result.append(data)
-    return ret_result
-
-
-
-def getFacultyMember(self, name: str) -
-
-
-
- -Expand source code - -
def getFacultyMember(self, name:str):
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
-
-
-
-def getFacultyMembers(self) -
-
-
-
- -Expand source code - -
def getFacultyMembers(self):
-    return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-
-
-
-def getFiles(self, app_id: int, prof_id: int) ‑> list[tuple] -
-
-
-
- -Expand source code - -
def getFiles(self, app_id:int, prof_id:int)->list[tuple]:
-    return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
-
-
-def getLastBookId(self) ‑> int -
-
-

Get the last book id in the database

-

Returns

-
-
int
-
ID of the last book in the database
-
-
- -Expand source code - -
def getLastBookId(self)->int:
-    """
-    Get the last book id in the database
-
-    Returns:
-        int: ID of the last book in the database
-    """
-    return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
-
-
-
-def getMessages(self, date: str) -
-
-
-
- -Expand source code - -
def getMessages(self, date:str):
-    def __get_user_name(user_id):
-        return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
-    messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
-    ret = [
-        {
-            "message": i[2],
-            "user": __get_user_name(i[4]),
-            "appnr": i[5],
-            "id": i[0]
-        }
-        for i in messages
-    ]
-    return ret
-
-
-
-def getProfByName(self, prof_name: str) -
-
-
-
- -Expand source code - -
def getProfByName(self, prof_name:str):
-    return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
-
-
-
-def getProfData(self, profname: str) -
-
-
-
- -Expand source code - -
def getProfData(self, profname:str):
-    
-    data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
-    return data
-
-
-
-def getProfId(self, prof_name: str) -
-
-

getProfId summary

-

:param prof_name: description -:type prof_name: str -:return: description -:rtype: type

-
- -Expand source code - -
def getProfId(self, prof_name:str):
-    """
-    getProfId _summary_
-
-    :param prof_name: _description_
-    :type prof_name: str
-    :return: _description_
-    :rtype: _type_
-    """
-    data = self.getProfByName(prof_name.replace(",", ""))
-    if data is None:
-        return None
-    else:
-        return data[0]
-
-
-
-def getProfNameById(self, prof_id: int, add_title: bool = False) -
-
-
-
- -Expand source code - -
def getProfNameById(self, prof_id:int,add_title:bool=False):
-    prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
-    if add_title:
-        return f"{self.getTitleById(prof_id)}{prof[0]}"
-    else:
-        return prof[0]
-
-
-
-def getProfs(self) -
-
-
-
- -Expand source code - -
def getProfs(self):
-    return self.query_db("SELECT * FROM prof")
-
-
-
-def getRole(self, user) -
-
-
-
- -Expand source code - -
def getRole(self, user):
-    return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
-
-
-
-def getRoles(self) -
-
-
-
- -Expand source code - -
def getRoles(self):
-    return self.query_db("SELECT role FROM user")
-
-
-
-def getSemersters(self) -
-
-
-
- -Expand source code - -
def getSemersters(self):
-    data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
-    return [i[0] for i in data]
-
-
-
-def getSpecificProfData(self, prof_id: int, fields: List[str]) -
-
-

getSpecificProfData summary

-

Args:

-
- prof_id (int): _description_
-- fields (List[str]): _description_
-
-

Returns:

-
- _type_: _description_
-
-
- -Expand source code - -
def getSpecificProfData(self, prof_id:int, fields:List[str]):
-    """
-    getSpecificProfData _summary_
-    
-    
-    
-    Args:
-    ----
-        - prof_id (int): _description_
-        - fields (List[str]): _description_
-    
-    Returns:
-    -------
-        - _type_: _description_
-    """
-    query = "SELECT "
-    for field in fields:
-        query += f"{field},"
-    query = query[:-1]
-    query += " FROM prof WHERE id=?"
-    return self.query_db(query, (prof_id,), one=True)[0]
-
-
-
-def getSubjects(self) -
-
-
-
- -Expand source code - -
def getSubjects(self):
-    return self.query_db("SELECT * FROM subjects")
-
-
-
-def getTitleById(self, prof_id: int) -
-
-
-
- -Expand source code - -
def getTitleById(self, prof_id:int):
-    title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
-    return f"{title} " if title is not None else ""
-
-
-
-def getUnavailableApparatNumbers(self) ‑> List[int] -
-
-

getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers

-

Returns:

-
- number(List[int]): a list of all currently used apparat numbers
-
-
- -Expand source code - -
def getUnavailableApparatNumbers(self)->List[int]:
-    """
-    getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers
-    
-    
-    
-    Returns:
-    -------
-        - number(List[int]): a list of all currently used apparat numbers
-    """
-    numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")    
-    numbers = [i[0] for i in numbers]
-    logger.log_info(f"Currently used apparat numbers: {numbers}")
-    return numbers
-
-
-
-def getUser(self) -
-
-
-
- -Expand source code - -
def getUser(self):
-    return self.query_db("SELECT * FROM user", one=True)
-
-
-
-def getUsers(self) -
-
-
-
- -Expand source code - -
def getUsers(self):
-    return self.query_db("SELECT * FROM user")
-
-
-
-def get_db_contents(self) ‑> Optional[List[Tuple]] -
-
-

Get the contents of the

-

Returns

-
-
Union[List[Tuple], None]
-
description
-
-
- -Expand source code - -
def get_db_contents(self)->Union[List[Tuple], None]:
-    """
-    Get the contents of the 
-
-    Returns:
-        Union[List[Tuple], None]: _description_
-    """
-    try:
-        with sql.connect(self.db_path) as conn:
-            cursor = conn.cursor()
-            cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
-            return cursor.fetchall()
-    except sql.OperationalError:
-        return None
-
-
-
-def insertFile(self, file: list[dict], app_id: int, prof_id) -
-
-
-
- -Expand source code - -
def insertFile(self, file: list[dict], app_id: int, prof_id):
-    for f in file:
-        filename = f["name"]
-        path = f["path"]
-        filetyp = f["type"]
-        if path == "Database":
-            continue
-        blob = create_blob(path)
-        query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
-        self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
-
-
-
-def insertInto(self, query: str, params: Tuple) ‑> None -
-
-

Insert sent data into the database

-

Args

-
-
query : str
-
The query to be executed
-
params : Tuple
-
the parameters to be inserted into the database
-
-
- -Expand source code - -
def insertInto(self, query:str, params:Tuple) -> None:
-    """
-    Insert sent data into the database
-
-    Args:
-        query (str): The query to be executed
-        params (Tuple): the parameters to be inserted into the database
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Inserting {params} into database with query {query}")
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-def isEternal(self, id) -
-
-
-
- -Expand source code - -
def isEternal(self, id):
-    return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
-
-
-
-def login(self, user, hashed_password) -
-
-
-
- -Expand source code - -
def login(self, user, hashed_password):
-    salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
-    if salt is None:
-        return False
-    hashed_password = salt + hashed_password
-    password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
-    if password == hashed_password:
-        return True
-    else:
-        return False
-
-
-
-def query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]] -
-
-

Query the Database for the sent query.

-

Args

-
-
query : str
-
The query to be executed
-
args : Tuple, optional
-
The arguments for the query. Defaults to ().
-
one : bool, optional
-
Return the first result only. Defaults to False.
-
-

Returns

-

Union[Typle|List[Tuple]]: Returns the result of the query

-
- -Expand source code - -
def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
-    """
-    Query the Database for the sent query.
-
-    Args:
-        query (str): The query to be executed
-        args (Tuple, optional): The arguments for the query. Defaults to ().
-        one (bool, optional): Return the first result only. Defaults to False.
-
-    Returns:
-        Union[Typle|List[Tuple]]: Returns the result of the query
-    """
-    conn = self.connect()
-    cursor = conn.cursor()
-    logger.log_info(f"Querying database with query {query}, args: {args}")
-    cursor.execute(query, args)
-    rv = cursor.fetchall()
-    conn.commit()
-    self.close_connection(conn)
-    return (rv[0] if rv else None) if one else rv
-
-
-
-def recreateFile(self, filename, app_id, filetype) -
-
-
-
- -Expand source code - -
def recreateFile(self, filename, app_id,filetype):
-    blob = self.getBlob(filename, app_id)
-    tempdir = config.database.tempdir
-    tempdir = tempdir.replace("~", str(Path.home()))
-    tempdir_path = Path(tempdir)        
-    if not os.path.exists(tempdir_path):
-        os.mkdir(tempdir_path)
-    file = tempfile.NamedTemporaryFile(
-        delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
-    )
-    file.write(blob)
-    print("file created")
-    return file.name
-
-
-
-def searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]] -
-
-

Search a book in the database based on the sent data.

-

Args

-
-
data : dict[str, str]
-
A dictionary containing the data to be searched for. The dictionary can contain the following:
-
-
    -
  • signature: The signature of the book
  • -
  • title: The title of the book
  • -
-

Returns

-
-
list[tuple[BookData, int]]
-
A list of tuples containing the wrapped Metadata and the id of the book
-
-
- -Expand source code - -
def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
-    """
-    Search a book in the database based on the sent data.
-
-    Args:
-        data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: 
-        - signature: The signature of the book
-        - title: The title of the book
-
-    Returns:
-        list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
-    """
-    rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
-    #ic(rdata, len(rdata))
-    mode = 0
-    if len(data)== 1:
-        if "signature" in data.keys():
-            mode = 1
-        elif "title" in data.keys():
-            mode = 2
-    elif len(data) == 2:
-        mode = 3
-    else:
-        return None
-    ret = []
-    for book in rdata:
-        bookdata = load_pickle(book[1])
-        app_id = book[2]
-        prof_id = book[3]
-        if mode == 1:
-            if data["signature"] in bookdata.signature:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 2:
-            if data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-        elif mode == 3:
-            if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
-                ret.append((bookdata,app_id,prof_id))
-    #ic(ret)
-    return ret
-
-
-
-def setAvailability(self, book_id: str, available: str) -
-
-

Set the availability of a book in the database

-

Args

-
-
book_id : str
-
The id of the book
-
available : str
-
The availability of the book
-
-
- -Expand source code - -
def setAvailability(self, book_id:str, available:str):
-    """
-    Set the availability of a book in the database
-
-    Args:
-        book_id (str): The id of the book
-        available (str): The availability of the book
-    """
-    self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
-
-
-
-def setNewSemesterDate(self, appnr, newDate, dauerapp=False) -
-
-
-
- -Expand source code - -
def setNewSemesterDate(self, appnr, newDate, dauerapp=False):
-    date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
-    if dauerapp:
-        self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr))
-    else:
-        self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr))
-
-
-
-def statistic_request(self, **kwargs: Any) -
-
-
-
- -Expand source code - -
def statistic_request(self, **kwargs: Any):
-    def __query(query):
-        conn = self.connect()
-        cursor = conn.cursor()
-        result = cursor.execute(query).fetchall()
-        for result_a in result:
-            orig_value = result_a
-            prof_name = self.getProfNameById(result_a[2])
-            # replace the prof_id with the prof_name
-            result_a = list(result_a)
-            result_a[2] = prof_name
-            result_a = tuple(result_a)
-            result[result.index(orig_value)] = result_a
-        self.close_connection(conn)
-        return result
-    if "deletable" in kwargs.keys():
-        query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
-        return __query(query)
-    if "dauer" in kwargs.keys():
-        kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
-    query = "SELECT * FROM semesterapparat WHERE "
-    for key, value in kwargs.items() if kwargs.items() is not None else {}:
-        print(key, value)
-        query += f"{key}='{value}' AND "
-        print(query)
-    # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
-    if "deletesemester" in kwargs.keys():
-        query = query.replace(
-            f"deletesemester='{kwargs['deletesemester']}' AND ", ""
-        )
-    if "endsemester" in kwargs.keys():
-        if "erstellsemester" in kwargs.keys():
-            query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
-            query = query.replace(
-                f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
-            )
-        else:
-            query = query.replace(
-                f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
-            )
-            print("replaced")
-        query = query.replace(
-            "xyz",
-            f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
-        )
-    # remove all x="" parts from the query where x is a key in kwargs
-    query = query[:-5]
-    print(query)
-    return __query(query)
-
-
-
-def updateApparat(self, apparat_data: src.logic.dataclass.ApparatData) -
-
-
-
- -Expand source code - -
def updateApparat(self, apparat_data:ApparatData):
-    query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
-    params = (
-        apparat_data.appname,
-        apparat_data.app_fach,
-        apparat_data.dauerapp,
-        self.getProfId(apparat_data.profname),
-        apparat_data.appnr,        
-    )
-    self.query_db(query, params)
-
-
-
-def updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData) -
-
-

Update the bookdata in the database

-

Args

-
-
book_id : str
-
The id of the book
-
bookdata : BookData
-
The new metadata of the book
-
-
- -Expand source code - -
def updateBookdata(self, book_id, bookdata:BookData):
-    """
-    Update the bookdata in the database
-
-    Args:
-        book_id (str): The id of the book
-        bookdata (BookData): The new metadata of the book
-    """
-    self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
-
-
-
-def updateFacultyMember(self, data, oldlname, oldfname) -
-
-
-
- -Expand source code - -
def updateFacultyMember(self, data, oldlname, oldfname):
-    placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
-    query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
-    data["oldlname"] = oldlname
-    data["oldfname"] = oldfname
-    self.query_db(query, data)
-
-
-
-def updateUser(self, username, data: dict[str, str]) -
-
-
-
- -Expand source code - -
def updateUser(self, username, data:dict[str, str]):
-    conn = self.connect()
-    cursor = conn.cursor()
-    query = "UPDATE user SET "
-    for key,value in data.items():
-        if key == "username":
-            continue
-        query += f"{key}='{value}',"
-    query = query[:-1]
-    query += " WHERE username=?"
-    params = (username,)
-    cursor.execute(query, params)
-    conn.commit()
-    self.close_connection(conn)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/documentation/database.md b/documentation/database.md deleted file mode 100644 index c518b09..0000000 --- a/documentation/database.md +++ /dev/null @@ -1,327 +0,0 @@ -Module database -=============== - -Classes -------- - -`Database(db_path: str = None)` -: Initialize the database and create the tables if they do not exist. - - Default constructor for the database class - - Args: - db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None. - - ### Methods - - `addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: str, prof_id: str)` - : Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. - - Args: - bookdata (BookData): The metadata of the book to be added - app_id (str): The apparat id where the book should be added to - prof_id (str): The id of the professor where the book should be added to. - - `addMessage(self, message: dict, user, appnr)` - : - - `changePassword(self, user, new_password)` - : - - `checkApparatExists(self, apparat_name)` - : - - `checkApparatExistsById(self, apparat_id)` - : - - `checkUsername(self, user)` - : - - `close_connection(self, conn: sqlite3.Connection)` - : closes the connection to the database - - Args: - ---- - - conn (sql.Connection): the connection to be closed - - `connect(self) ‑> sqlite3.Connection` - : Connect to the database - - Returns: - sql.Connection: The active connection to the database - - `createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> Union[src.errors.DatabaseErrors.AppPresentError, ForwardRef(None), int]` - : - - `createProf(self, prof_details: dict)` - : - - `createUser(self, user, password, role, salt)` - : Create a user based on passed data. - - Args: - ---- - - username (str): Username to be used - - password (str): the salted password - - role (str): Role of the user - - salt (str): a random salt for the user - - `create_tables(self)` - : Create the tables in the database - - `deleteApparat(self, appnr, semester)` - : - - `deleteBook(self, book_id)` - : Delete a book from the database - - Args: - book_id (str): ID of the book - - `deleteMessage(self, message_id)` - : - - `deleteUser(self, user)` - : - - `getAllAparats(self, deleted=0)` - : - - `getApparatCountBySemester(self) ‑> tuple[list[str], list[int]]` - : - - `getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData` - : - - `getApparatId(self, apparat_name)` - : - - `getApparatName(self, app_id, prof_id)` - : - - `getApparatsByProf(self, prof_id: int) ‑> list[tuple]` - : - - `getApparatsBySemester(self, semester: str) ‑> dict` - : - - `getBlob(self, filename, app_id)` - : Get a blob from the database - - Args: - filename (str): The name of the file - app_id (str): ID of the apparat - - Returns: - bytes: The file stored in - - `getBook(self, book_id: int) ‑> src.logic.dataclass.BookData` - : Get the book based on the id in the database - - Args: - book_id (int): The id of the book - - Returns: - BookData: The metadata of the book wrapped in a BookData object - - `getBookBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> src.logic.dataclass.BookData` - : Get the book based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - BookData: The total metadata of the book wrapped in a BookData object - - `getBookId(self, bookdata: src.logic.dataclass.BookData, app_id, prof_id) ‑> int` - : Get the id of a book based on the metadata of the book - - Args: - bookdata (BookData): The wrapped metadata of the book - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - - Returns: - int: ID of the book - - `getBookIdBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> int` - : Get a book id based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - int: The id of the book - - `getBooks(self, app_id, prof_id, deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]]` - : Get the Books based on the apparat id and the professor id - - Args: - app_id (str): The ID of the apparat - prof_id (str): The ID of the professor - deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. - - Returns: - list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book - - `getFacultyMember(self, name: str)` - : - - `getFacultyMembers(self)` - : - - `getFiles(self, app_id: int, prof_id: int) ‑> list[tuple]` - : - - `getLastBookId(self) ‑> int` - : Get the last book id in the database - - Returns: - int: ID of the last book in the database - - `getMessages(self, date: str)` - : - - `getProfByName(self, prof_name: str)` - : - - `getProfData(self, profname: str)` - : - - `getProfId(self, prof_name: str)` - : getProfId _summary_ - - :param prof_name: _description_ - :type prof_name: str - :return: _description_ - :rtype: _type_ - - `getProfNameById(self, prof_id: int, add_title: bool = False)` - : - - `getProfs(self)` - : - - `getRole(self, user)` - : - - `getRoles(self)` - : - - `getSemersters(self)` - : - - `getSpecificProfData(self, prof_id: int, fields: List[str])` - : getSpecificProfData _summary_ - - - - Args: - ---- - - prof_id (int): _description_ - - fields (List[str]): _description_ - - Returns: - ------- - - _type_: _description_ - - `getSubjects(self)` - : - - `getTitleById(self, prof_id: int)` - : - - `getUnavailableApparatNumbers(self) ‑> List[int]` - : getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers - - - - Returns: - ------- - - number(List[int]): a list of all currently used apparat numbers - - `getUser(self)` - : - - `getUsers(self)` - : - - `get_db_contents(self) ‑> Optional[List[Tuple]]` - : Get the contents of the - - Returns: - Union[List[Tuple], None]: _description_ - - `insertFile(self, file: list[dict], app_id: int, prof_id)` - : - - `insertInto(self, query: str, params: Tuple) ‑> None` - : Insert sent data into the database - - Args: - query (str): The query to be executed - params (Tuple): the parameters to be inserted into the database - - `isEternal(self, id)` - : - - `login(self, user, hashed_password)` - : - - `query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]]` - : Query the Database for the sent query. - - Args: - query (str): The query to be executed - args (Tuple, optional): The arguments for the query. Defaults to (). - one (bool, optional): Return the first result only. Defaults to False. - - Returns: - Union[Typle|List[Tuple]]: Returns the result of the query - - `recreateFile(self, filename, app_id, filetype)` - : - - `searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]]` - : Search a book in the database based on the sent data. - - Args: - data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - - signature: The signature of the book - - title: The title of the book - - Returns: - list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book - - `setAvailability(self, book_id: str, available: str)` - : Set the availability of a book in the database - - Args: - book_id (str): The id of the book - available (str): The availability of the book - - `setNewSemesterDate(self, appnr, newDate, dauerapp=False)` - : - - `statistic_request(self, **kwargs: Any)` - : - - `updateApparat(self, apparat_data: src.logic.dataclass.ApparatData)` - : - - `updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData)` - : Update the bookdata in the database - - Args: - book_id (str): The id of the book - bookdata (BookData): The new metadata of the book - - `updateFacultyMember(self, data, oldlname, oldfname)` - : - - `updateUser(self, username, data: dict[str, str])` - : \ No newline at end of file diff --git a/resources.qrc b/resources.qrc deleted file mode 100644 index 7be4647..0000000 --- a/resources.qrc +++ /dev/null @@ -1,16 +0,0 @@ - - - resources/logo_SAP.ico - resources/logo_SAP.png - resources/1f4e7.svg - resources/1f510.svg - resources/2795.svg - resources/VZjRNn1k.ico - - - resources/critical.png - resources/information.png - resources/question.png - resources/warning.png - - diff --git a/ruff.toml b/ruff.toml deleted file mode 100644 index 747a691..0000000 --- a/ruff.toml +++ /dev/null @@ -1,77 +0,0 @@ -# Exclude a variety of commonly ignored directories. -exclude = [ - ".bzr", - ".direnv", - ".eggs", - ".git", - ".git-rewrite", - ".hg", - ".ipynb_checkpoints", - ".mypy_cache", - ".nox", - ".pants.d", - ".pyenv", - ".pytest_cache", - ".pytype", - ".ruff_cache", - ".svn", - ".tox", - ".venv", - ".vscode", - "__pypackages__", - "_build", - "buck-out", - "build", - "dist", - "node_modules", - "site-packages", - "venv", -] - -# Same as Black. -line-length = 88 -indent-width = 4 - -# Assume Python 3.8 -target-version = "py312" - -[lint] -# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. -# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or -# McCabe complexity (`C901`) by default. -select = ["E4", "E7", "E9", "F"] -ignore = [] - -# Allow fix for all enabled rules (when `--fix`) is provided. -fixable = ["ALL"] -unfixable = [] - -# Allow unused variables when underscore-prefixed. -dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" - -[format] -# Like Black, use double quotes for strings. -quote-style = "double" - -# Like Black, indent with spaces, rather than tabs. -indent-style = "space" - -# Like Black, respect magic trailing commas. -skip-magic-trailing-comma = false - -# Like Black, automatically detect the appropriate line ending. -line-ending = "auto" - -# Enable auto-formatting of code examples in docstrings. Markdown, -# reStructuredText code/literal blocks and doctests are all supported. -# -# This is currently disabled by default, but it is planned for this -# to be opt-out in the future. -docstring-code-format = false - -# Set the line length limit used when formatting code snippets in -# docstrings. -# -# This only has an effect when the `docstring-code-format` setting is -# enabled. -docstring-code-line-length = "dynamic" diff --git a/sap.db b/sap.db deleted file mode 100644 index adc66ba..0000000 Binary files a/sap.db and /dev/null differ diff --git a/semap.db b/semap.db deleted file mode 100644 index e69de29..0000000 diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/bookgrabbertest.py b/test/bookgrabbertest.py deleted file mode 100644 index a744df6..0000000 --- a/test/bookgrabbertest.py +++ /dev/null @@ -1,66 +0,0 @@ -from src.backend.database import Database -from src.logic.webrequest import BibTextTransformer, WebRequest -import sqlite3 - -class BookGrabber: - - def __init__( - self, - mode: str = None, - data: list = None, - app_id: int = None, - prof_id: int = None, - ): - self.app_id = app_id - self.prof_id = prof_id - self.mode = mode - self.data = data - self.book_id = None - - def run(self): - self.db = Database() - item = 0 - for entry in self.data: - signature = str(entry) - self.logger.log_info("Processing entry: " + signature) - - webdata = WebRequest().get_ppn(entry).get_data() - if webdata == "error": - continue - bd = BibTextTransformer(self.mode).get_data(webdata).return_data() - transformer = BibTextTransformer("RDS") - rds = transformer.get_data(webdata).return_data("rds_availability") - bd.signature = entry - # confirm lock is acquired - print("lock acquired, adding book to database") - self.db.addBookToDatabase(bd, self.app_id, self.prof_id) - # get latest book id - self.book_id = self.db.getLastBookId() - self.logger.log_info("Added book to database") - state = 0 - for rds_item in rds.items: - sign = rds_item.superlocation - loc = rds_item.location - # print(item.location) - if self.app_id in sign or self.app_id in loc: - state = 1 - book_id = None - # for book in self.books: - # if book["bookdata"].signature == entry: - # book_id = book["id"] - # break - self.logger.log_info(f"State of {signature}: {state}") - print( - "lock acquired, updating availability of " - + str(book_id) - + " to " - + str(state) - ) - try: - self.db.setAvailability(self.book_id, state) - except sqlite3.OperationalError as e: - self.logger.log_error(f"Failed to update availability: {e}") - break - - # time.sleep(5) - item += 1 diff --git a/test/database_test.py b/test/database_test.py deleted file mode 100644 index a4d091d..0000000 --- a/test/database_test.py +++ /dev/null @@ -1,17 +0,0 @@ -import pytest - -from src.backend.database import Database - - -def test_prof(): - assert Database().getProfNameById(1, add_title=True) == "Karoß Sabine" - assert Database().getProfNameById(1, add_title=False) == "Karoß Sabine" - assert Database().getProfId("Karoß Sabine") == 1 - - -def test_apparat(): - assert Database().getApparatName(3, 1) == "Theorie und Praxis Gymnastik" - - -def test_admin(): - assert len(Database().getUser()) >= 1 and "admin" in Database().getUser() diff --git a/test/many_webrequest_test.py b/test/many_webrequest_test.py deleted file mode 100644 index 2cdd479..0000000 --- a/test/many_webrequest_test.py +++ /dev/null @@ -1,10 +0,0 @@ -from test.webrequest_test import test_webdata_bibtexttransform - - -def many_test_webdata(): - test_webdata_bibtexttransform("RIS") - test_webdata_bibtexttransform("BibTeX") - test_webdata_bibtexttransform("COinS") - test_webdata_bibtexttransform("ARRAY") - test_webdata_bibtexttransform("RDS") - assert True is True diff --git a/test/rds_test.py b/test/rds_test.py deleted file mode 100644 index a7e6b6c..0000000 --- a/test/rds_test.py +++ /dev/null @@ -1,103 +0,0 @@ -def contact_prof(self): - dialog = QtWidgets.QDialog() - mail_prev = Mail_Dialog() - mail_prev.setupUi(dialog) - mail_prevs = os.listdir("mail_vorlagen") - if self.app_name.text() == "": - mail_prevs.remove("Information zum Semesterapparat.eml") - mail_prev.comboBox.addItems(mail_prevs) - active_apparat_id = self.tableWidget_apparate.item( - self.tableWidget_apparate.currentRow(), 0 - ).text() - general_data = { - "Appname": self.app_name.text(), - "AppSubject": self.app_fach.currentText(), - "appnr": self.active_apparat, - } - print(active_apparat_id) - mail_prev.appid = active_apparat_id - base_data = self.db.getProfData(id=active_apparat_id) - profname = self.db.getProfNameById(base_data["id"]) - profname = profname.split(" ") - profname = f"{profname[1]} {profname[0]}" - pass_data = { - "prof_name": profname, - "mail_name": base_data["prof_mail"], - "general": general_data, - } - - mail_prev.set_data(pass_data) - mail_prev.set_mail() - dialog.exec() - - -import subprocess -import tempfile - -from PyQt6 import QtCore, QtGui, QtWidgets - -from src.ui.dialogs.mail_preview import Ui_Dialog - - -class Mail_Dialog(QtWidgets.QDialog, Ui_Dialog): - def __init__(self, parent=None): - super().__init__(parent) - self.setupUi(self) - self.appid = "" - self.mail_data = "" - self.data = None - self.buttonBox.accepted.connect(self.save_mail) - - def set_data(self, data: dict): - print(data) - self.prof_name.setText(data["prof_name"]) - self.mail_name.setText(data["mail_name"]) - # assign data["general"] to self.data - self.data = data["general"] - - def set_mail(self): - email_template = self.comboBox.currentText() - with open(f"mail_vorlagen/{email_template}", "r", encoding="utf-8") as f: - mail_template = f.read() - email_header = email_template.split(".eml")[0] - if "{AppNr}" in email_template: - email_header = email_template.split(".eml")[0].format(AppNr=self.appid) - self.mail_header.setText(email_header) - self.mail_data = mail_template.split("")[0] - mail_html = mail_template.split("")[1] - mail_html = "" + mail_html - print(self.data) - Appname = self.data["Appname"] - mail_html = mail_html.format( - Profname=self.prof_name.text().split(" ")[-1], Appname=Appname - ) - - self.mail_body.setHtml(mail_html) - - def save_mail(self): - # create a temporary file - mail_header = self.mail_header.text() - mail_body = self.mail_body.toHtml() - mail = self.mail_data + mail_body - mail = mail.replace("Subject:", f"Subject: {mail_header}") - with tempfile.NamedTemporaryFile( - mode="w", delete=False, suffix=".eml", encoding="utf-8", dir="mails" - ) as f: - f.write(mail) - self.mail_path = f.name - print(self.mail_path) - # open the file using thunderbird - subprocess.Popen(["thunderbird", f"{self.mail_path}"]) - # delete the file - # os.remove(self.mail_path) - - -if __name__ == "__main__": - import sys - - app = QtWidgets.QApplication(sys.argv) - Dialog = QtWidgets.QDialog() - ui = Mail_Dialog() - ui.setupUi(Dialog) - Dialog.show() - sys.exit(app.exec()) diff --git a/test/semestergen_test.py b/test/semestergen_test.py deleted file mode 100644 index 8c398e0..0000000 --- a/test/semestergen_test.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - -from src.backend.semester import generateSemesterByDate - - -def test_generateSemesterByDate(): - assert generateSemesterByDate() == "WiSe 23/24" diff --git a/test/test_database.py b/test/test_database.py deleted file mode 100644 index 6008df2..0000000 --- a/test/test_database.py +++ /dev/null @@ -1,4 +0,0 @@ -from src.backend.database import Database - -db = Database("semap.db") -# print(db.query_db("SELECT * FROM subjects WHERE id=1")) diff --git a/test/webrequest_test.py b/test/webrequest_test.py deleted file mode 100644 index 9de4d7c..0000000 --- a/test/webrequest_test.py +++ /dev/null @@ -1,18 +0,0 @@ -import pytest - -from src.logic.dataclass import BookData -from src.logic.webrequest import BibTextTransformer, WebRequest - - -def test_webdata_bibtexttransform(source_data: str = "RIS"): - request = WebRequest().get_ppn("ST 250 U42 (15) ").get_data() - assert isinstance(request, list) is True - assert len(request) > 0 - model: BookData = BibTextTransformer(source_data).get_data(request).return_data() - assert model is not None - assert model.signature == "ST 250 U42 (15)" - assert model.ppn == "1693321114" - assert model.author == "Ullenboom, Christian" - assert model.link == "https://rds.ibs-bw.de/phfreiburg/link?kid=1693321114" - assert model.pages == "1246" - assert model.publisher == "Rheinwerk Computing"