o
    2&h3                     @   sF   d dl Z d dlmZ d dlmZmZmZmZmZm	Z	 G dd dZ
dS )    N)asynccontextmanager)ListDictAnyTupleOptionalUnionc                   @   s  e Zd ZdefddZedd Zdd Zded	eeef d
e	fddZ
dedeeef d
ee fddZ	d&dedeeef deeeef  d
e	fddZ			d'dedeeeef  dee dee d
ee f
ddZdedeeef deeef d
e	fddZdedeeef d
e	fddZdedeeef d
e	fddZd&dedeeeef  d
efdd Zd(d"ed#ed
ee fd$d%ZdS ))DatabaseManagerdb_namec                 C   s
   || _ d S N)r
   )selfr
    r   (/var/www/html/server/database/handler.py__init__   s   
zDatabaseManager.__init__c              	   C  sz   t | j4 I dH %}t j|_z|V  W | I dH  n| I dH  w W d  I dH  dS 1 I dH s6w   Y  dS )z/Async context manager for database connections.N)	aiosqliteconnectr
   Rowrow_factorycloser   connr   r   r   get_connection	   s   ".zDatabaseManager.get_connectionc              	      s   |   4 I dH 3}|dI dH  |dI dH  |dI dH  |dI dH  | I dH  W d  I dH  dS 1 I dH sBw   Y  dS )z7Create database and initial tables if they don't exist.Nan  
                CREATE TABLE IF NOT EXISTS visitors (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    ip TEXT DEFAULT NULL,
                    phrase TEXT DEFAULT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            a]  
                CREATE TABLE IF NOT EXISTS api_keys (
                    key_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    ip TEXT NOT NULL,
                    api_key VARCHAR(64) UNIQUE,
                    active BOOLEAN DEFAULT TRUE,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            a  
                CREATE TABLE IF NOT EXISTS config (
                    id INTEGER PRIMARY KEY CHECK (id = 1),
                    enabled INTEGER DEFAULT 1,
                    callback TEXT DEFAULT '45.11.59.247:8000',
                    auth_key TEXT DEFAULT 'AD9U1JVCwYsl43EtQyvQLz9u6KuEQjLM3LOHmxfqeTtbk0QrxkFhBgpXkOJQ42sVF8J3xc5VZusvloi12pz6dcY3Mct3Ehwi'
                )
            zJ
                INSERT OR IGNORE INTO config (id) VALUES (1)
            )r   executecommitr   r   r   r   initialize_database   s   		.z#DatabaseManager.initialize_database
table_namecolumnsreturnc              
      s   zH|   4 I dH 2}ddd | D }d| d| d}||I dH  | I dH  	 W d  I dH  W dS 1 I dH sBw   Y  W dS  tjyd } ztd	|  W Y d}~d
S d}~ww )z*Create a new table with specified columns.N, c                 S   s   g | ]\}}| d | qS ) r   ).0coldtyper   r   r   
<listcomp>9   s    z0DatabaseManager.create_table.<locals>.<listcomp>zCREATE TABLE IF NOT EXISTS  ()TzError creating table: F)r   joinitemsr   r   r   Errorprint)r   r   r   r   columns_defqueryer   r   r   create_table5   s   4zDatabaseManager.create_tablesearch_valuec              
      sr  z|   4 I dH }|d| dI dH }dd |2 I dH }| I dH  |s7g W  d  I dH  W S t trKdd |D } gt| }ndd |D } fdd|D }d	|}d
| d| }	||	|I dH }dd |2 I dH }
| I dH  |
W  d  I dH  W S 1 I dH sw   Y  W dS  tjy } zt	d|  g W  Y d}~S d}~ww )a/  
        Search all columns in a table for a given value (string or int).
        
        Args:
            table_name: The table to search
            search_value: The value to look for in any column

        Returns:
            List of rows (as dicts) where the value appears in any column
        NzPRAGMA table_info(r%   c                    s    g | z
3 d H W }|d q6 S )N   r   r    rowr   r   r   r#   P       z0DatabaseManager.search_table.<locals>.<listcomp>c                 S      g | ]}| d qS z = ?r   r    r!   r   r   r   r#   W       c                 S   r3   )z LIKE ?r   r5   r   r   r   r#   Z   r6   c                    s   g | ]}d   d qS )%r   r    _r.   r   r   r#   [   s    z OR SELECT * FROM  WHERE c                        g | z
3 d H W }t |q6 S r   dictr0   r   r   r   r#   a   r2   zError searching table: )
r   r   r   
isinstanceintlenr&   r   r(   r)   )r   r   r.   r   cursorr   
conditionsparamswhere_clauser+   rowsr,   r   r:   r   search_tableB   s4   

4zDatabaseManager.search_tableNdata	conditionc              
      s  z|   4 I dH }|r{ddd | D }t| }d| d| }|||I dH }| I dH }	|	d dk}
|
r{d	d
d | D }t| | }d| d| d| }|||I dH  | I dH  	 W d  I dH  W dS d	| }d	dd |D }t| }d| d| d| d}|||I dH  | I dH  	 W d  I dH  W dS 1 I dH sw   Y  W dS  tj	y } zt
d|  W Y d}~dS d}~ww )a  
        Universal insert/update function. If the record matching the condition exists,
        it will be updated; otherwise, a new record will be inserted.
        
        Args:
            table_name: The table to operate on
            data: The data to insert or update
            condition: Key-value pairs to identify existing records. 
                      If None, will always insert.
        
        Returns:
            bool: Success or failure
        N AND c                 S   r3   r4   r   r    kr   r   r   r#   {   r6   z*DatabaseManager.upsert.<locals>.<listcomp>SELECT COUNT(*) as count FROM r<   countr   r   c                 S   r3   r4   r   r5   r   r   r   r#      r6   UPDATE  SET Tc                 S   s   g | ]}d qS )?r   r8   r   r   r   r#      s    zINSERT INTO r$   z
) VALUES (r%   zError in upsert operation: F)r   r&   keystuplevaluesr   fetchoner   r   r(   r)   )r   r   rI   rJ   r   rF   where_valuesr+   rC   resultrecord_exists
set_clauseupdate_valuesr   placeholdersrU   r,   r   r   r   upserti   s>   4zDatabaseManager.upsertorder_bylimitc              
      s   zr|   4 I dH \}d| }d}|r-ddd | D }t| }|d| 7 }|r6|d| 7 }|r?|d	| 7 }|||I dH }	d
d |	2 I dH }
|	 I dH  |
W  d  I dH  W S 1 I dH slw   Y  W dS  tjy } zt	d|  g W  Y d}~S d}~ww )a  
        Retrieve rows from the specified table based on conditions.
        
        Args:
            table_name: The table to query
            condition: Key-value pairs for WHERE clause
            order_by: Optional ORDER BY clause (e.g., "id DESC")
            limit: Optional limit for number of returned rows
            
        Returns:
            List of dictionaries representing rows
        Nr;   r   rK   c                 S   r3   r4   r   rL   r   r   r   r#      r6   z,DatabaseManager.get_rows.<locals>.<listcomp>r<   z
 ORDER BY z LIMIT c                    r=   r   r>   r0   r   r   r   r#      r2   zError retrieving rows: )
r   r&   rS   rT   rU   r   r   r   r(   r)   )r   r   rJ   r^   r_   r   r+   rE   rF   rC   rG   r,   r   r   r   get_rows   s.   
4zDatabaseManager.get_rowsc           
   
      s   zc|   4 I dH M}ddd | D }ddd | D }t| t|  }d| d| d	| }|||I dH  | I dH  	 W d  I dH  W d
S 1 I dH s]w   Y  W dS  tjy }	 zt	d|	  W Y d}	~	dS d}	~	ww )a6  
        Update rows in the specified table based on condition.
        
        Args:
            table_name: The table to update
            data: Key-value pairs of fields to update
            condition: Key-value pairs for WHERE clause
            
        Returns:
            Success or failure
        Nr   c                 S   r3   r4   r   r5   r   r   r   r#      r6   z/DatabaseManager.update_rows.<locals>.<listcomp>rK   c                 S   r3   r4   r   rL   r   r   r   r#      r6   rP   rQ   r<   TzError updating rows: F
r   r&   rS   rT   rU   r   r   r   r(   r)   )
r   r   rI   rJ   r   rZ   rF   rU   r+   r,   r   r   r   update_rows   s    4zDatabaseManager.update_rowsc              
      s   zN|   4 I dH 8}ddd | D }t| }d| d| }|||I dH  | I dH  	 W d  I dH  W dS 1 I dH sHw   Y  W dS  tjyj } zt	d|  W Y d}~d	S d}~ww )
a  
        Delete rows from the specified table based on condition.
        
        Args:
            table_name: The table to delete from
            condition: Key-value pairs for WHERE clause
            
        Returns:
            Success or failure
        NrK   c                 S   r3   r4   r   rL   r   r   r   r#      r6   z/DatabaseManager.delete_rows.<locals>.<listcomp>zDELETE FROM r<   TzError deleting rows: Fra   )r   r   rJ   r   rF   rE   r+   r,   r   r   r   delete_rows   s   4	zDatabaseManager.delete_rowsc           
   
      s   zY|   4 I dH C}ddd | D }t| }d| d| }|||I dH }| I dH }| I dH  |d dkW  d  I dH  W S 1 I dH sSw   Y  W dS  tj	yu }	 zt
d	|	  W Y d}	~	d
S d}	~	ww )a	  
        Check if a record exists based on condition.
        
        Args:
            table_name: The table to check
            condition: Key-value pairs for WHERE clause
            
        Returns:
            True if record exists, False otherwise
        NrK   c                 S   r3   r4   r   rL   r   r   r   r#     r6   z*DatabaseManager.exists.<locals>.<listcomp>rN   r<   rO   r   zError checking existence: Fr   r&   rS   rT   rU   r   rV   r   r   r(   r)   )
r   r   rJ   r   rF   rE   r+   rC   rX   r,   r   r   r   exists   s    
4zDatabaseManager.existsc           
   
      s   z_|   4 I dH I}d| }d}|r-ddd | D }t| }|d| 7 }|||I dH }| I dH }| I dH  |d W  d  I dH  W S 1 I dH sYw   Y  W dS  tj	y{ }	 zt
d	|	  W Y d}	~	d
S d}	~	ww )z
        Count records based on condition.
        
        Args:
            table_name: The table to count from
            condition: Key-value pairs for WHERE clause
            
        Returns:
            Number of matching records
        NrN   r   rK   c                 S   r3   r4   r   rL   r   r   r   r#   "  r6   z)DatabaseManager.count.<locals>.<listcomp>r<   rO   zError counting records: r   rd   )
r   r   rJ   r   r+   rE   rF   rC   rX   r,   r   r   r   rO     s&   
4zDatabaseManager.countr   r+   rE   c              
      s   z[|   4 I dH E}|||I dH }|  dr;dd |2 I dH }| I dH  |W  d  I dH  W S | I dH  g W  d  I dH  W S 1 I dH sUw   Y  W dS  tjyx } zt	d|  g W  Y d}~S d}~ww )z
        Execute a custom query with parameters.
        
        Args:
            query: SQL query to execute
            params: Parameters for the query
            
        Returns:
            Results of the query
        NSELECTc                    r=   r   r>   r0   r   r   r   r#   @  r2   z1DatabaseManager.execute_query.<locals>.<listcomp>zError executing query: )
r   r   stripupper
startswithr   r   r   r(   r)   )r   r+   rE   r   rC   rG   r,   r   r   r   execute_query0  s"   4zDatabaseManager.execute_queryr   )NNN)r   )__name__
__module____qualname__strr   r   r   r   r   boolr-   r   rA   r   rH   r   r   r]   r`   rb   rc   re   rO   r   rj   r   r   r   r   r	      sD    
	""(
/
)

$ r	   )r   
contextlibr   typingr   r   r   r   r   r   r	   r   r   r   r   <module>   s     