
    X3j                         d dl Z d dlZd dlmZ  e             dZd Zd ZddZd Zd Z	d	 Z
d
 Zd Zd Zd Zedk    r e             dS dS )    N)load_dotenvzdatabase.dbc                  ^    t          j        t          d          } t           j        | _        | S )zJReturns a connection to the SQLite database with a thread timeout handler.g      $@)timeout)sqlite3connectDB_NAMERowrow_factory)conns    #/home/pi/cupos-finder/db_manager.pyget_db_connectionr      s%    ?7D111D{DK    c                  >   t                      5 } |                                 }|                    d           |                    d           |                    d           |                                  ddd           n# 1 swxY w Y   t	          d           dS )z7Initializes the database schema with relational tables.zPRAGMA foreign_keys = ON;z
            CREATE TABLE IF NOT EXISTS users (
                chat_id INTEGER PRIMARY KEY,
                username TEXT,
                preferred_center TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            );
        ae  
            CREATE TABLE IF NOT EXISTS monitors (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                chat_id INTEGER,
                ciclo TEXT NOT NULL,
                clave_materia TEXT NOT NULL,
                nrc TEXT NOT NULL,
                was_present INTEGER DEFAULT 0, -- 0 = Not found last loop, 1 = Found last loop
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (chat_id) REFERENCES users(chat_id) ON DELETE CASCADE,
                UNIQUE(chat_id, ciclo, nrc) -- Prevents duplicate monitors for the same user
            );
        Nu&   ✨ Database initialized successfully.)r   cursorexecutecommitprintr   r   s     r   init_dbr      s    			  	2333 	  	 	 	 	  	 	 	 	=              > 

233333s   A(BB
Bc                    t                      5 }|                                }|r|                    d| ||f           n|                    d| |f           |                                 ddd           dS # 1 swxY w Y   dS )z|
    Saves a new user or updates an existing one. 
    Restricts changes to mutable profile options (preferred_center).
    a  
                INSERT INTO users (chat_id, username, preferred_center)
                VALUES (?, ?, ?)
                ON CONFLICT(chat_id) DO UPDATE SET 
                    username = excluded.username,
                    preferred_center = excluded.preferred_center;
            z
                INSERT INTO users (chat_id, username)
                VALUES (?, ?)
                ON CONFLICT(chat_id) DO UPDATE SET username = excluded.username;
            Nr   r   r   r   )chat_idusernamepreferred_centerr   r   s        r   save_or_update_userr   3   s    
 
		  	&NN  8%568 8 8 8 NN  8$	& & &
 	%                 s   AA99A= A=c                     t                      5 }|                                }|                    d| f           |                                cddd           S # 1 swxY w Y   dS )z&Retrieves a user's configuration data.zHSELECT chat_id, username, preferred_center FROM users WHERE chat_id = ?;N)r   r   r   fetchoner   r   r   s      r   get_user_profiler   L   s    			 !adkcmnnn  ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !   ?AA"Ac           	         t          j        dd          }	 t                      5 }|                                }|                    d| ||                                                                |                                f           |                                 	 ddd           dS # 1 swxY w Y   dS # t          j	        $ r Y dS w xY w)z-Adds a target class to monitor for a student.CICLO202620z|
                INSERT INTO monitors (chat_id, ciclo, clave_materia, nrc)
                VALUES (?, ?, ?, ?);
            NTF)
osgetenvr   r   r   upperstripr   r   IntegrityError)r   clave_materianrcciclor   r   s         r   add_monitorr,   U   s   Igx((E
   	D[[]]FNN  5-"5"5"7"7"="="?"?MO O O KKMMM	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 !   uus5   B9 A:B,B9 ,B00B9 3B04B9 9CCc                     t                      5 }|                                }|                    d| f           |                                 ddd           dS # 1 swxY w Y   dS )z!Deletes a tracking record safely.z"DELETE FROM monitors WHERE id = ?;Nr   )
monitor_idr   r   s      r   remove_monitorr/   d   s    			 ;j]KKK                 s   A AA #A c                     t                      5 }|                                }|                    d| f           |                                cddd           S # 1 swxY w Y   dS )z9Returns all active classes a specific user is monitoring.z{
            SELECT id, clave_materia, nrc, was_present 
            FROM monitors 
            WHERE chat_id = ?;
        Nr   r   r   fetchallr   s      r   get_user_monitorsr3   k   s    			 !  Z		 	 	
   ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !r    c                      t                      5 } |                                 }|                    d           |                                cddd           S # 1 swxY w Y   dS )z
    De-duplicates targets globally.
    Returns rows containing unique (preferred_center, ciclo, clave_materia)
    so we hit SIIAU exactly once per overall subject page.
    z
            SELECT DISTINCT u.preferred_center, m.ciclo, m.clave_materia 
            FROM monitors m
            JOIN users u ON m.chat_id = u.chat_id
            WHERE u.preferred_center IS NOT NULL;
        Nr1   r   s     r   get_unique_targets_to_scraper5   x   s     
		 !  	 	 	   ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !s   =AA Ac                     t                      5 }|                                }|                    d| ||f           |                                cddd           S # 1 swxY w Y   dS )zIFinds all users waiting for a specific NRC and their last tracking state.z
            SELECT chat_id, id, was_present 
            FROM monitors 
            WHERE ciclo = ? AND clave_materia = ? AND nrc = ?;
        Nr1   )r+   r)   r*   r   r   s        r   get_subscribers_for_targetr7      s    			 !  ]C(		* 	* 	*
   ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !   AAA!$A!c                     t                      5 }|                                }|                    d|| f           |                                 ddd           dS # 1 swxY w Y   dS )zIUpdates the individual state marker (0 or 1) for a specific tracking row.z1UPDATE monitors SET was_present = ? WHERE id = ?;Nr   )r.   was_presentr   r   s       r   update_monitor_stater;      s    			 J[ZdLefff                 r8   __main__)N)r   r$   dotenvr   r   r   r   r   r   r,   r/   r3   r5   r7   r;   __name__ r   r   <module>r@      s     				       
  !4 !4 !4J   2! ! !    	! 	! 	!! ! ! 	! 	! 	!   zGIIIII r   