U
    !j,                     @  s  d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ eddZe Zdd	d
dZdd	ddZddddddddddZdddddddZdddddZdd	ddZddd d!d"Zdddd#d$d%Zddddd&d'd(Ze	G d)d* d*Zddddd*d+d,d-Zdd.d/d0d1Zddd2ddddd3d4d5Zddddd6d7d8Zdddd9d:d;ZdS )<u  Локальное хранилище на SQLite: токены порталов, курсоры поллинга,
очередь согласования и состояние редактирования.

ВНИМАНИЕ: файл store.sqlite содержит OAuth-токены доступа к твоим порталам.
Ограничь к нему доступ средствами ОС (права 600, отдельный пользователь и т.п.).
    )annotationsN)	dataclass)AnyZDB_PATHzstore.sqlitezsqlite3.Connection)returnc                  C  s   t t} t j| _| S )N)sqlite3connect_DB_PATHZRowZrow_factoryc r   ,/var/www/spa-bitrix.ru/bitrix_asist/store.py_conn   s    
r   Nonec               
   C  s0   t " t } | d W 5 Q R X W 5 Q R X d S )Nu  
            CREATE TABLE IF NOT EXISTS portals (
                domain         TEXT PRIMARY KEY,
                access_token   TEXT,
                refresh_token  TEXT,
                expires_at     INTEGER,
                member_id      TEXT,
                operator_id    TEXT,   -- user_id оператора (тебя) на портале
                bot_id         TEXT,   -- id зарегистрированного чат-бота
                app_token      TEXT    -- application_token для проверки событий
            );
            CREATE TABLE IF NOT EXISTS cursors (
                domain      TEXT,
                dialog_id   TEXT,
                last_msg_id INTEGER,
                PRIMARY KEY (domain, dialog_id)
            );
            CREATE TABLE IF NOT EXISTS pending (
                id          TEXT PRIMARY KEY,
                domain      TEXT,
                dialog_id   TEXT,        -- исходный чат, куда уйдёт ответ
                incoming    TEXT,        -- текст входящего (для показа)
                draft       TEXT,        -- текущий черновик
                status      TEXT,        -- new | sent | skipped
                created_at  INTEGER
            );
            CREATE TABLE IF NOT EXISTS edit_state (
                domain      TEXT,
                operator_id TEXT,
                pending_id  TEXT,
                PRIMARY KEY (domain, operator_id)
            );
            )_lockr   Zexecutescriptr	   r   r   r   init_db   s    r   strintz
str | None)domainaccessrefresh
expires_in	member_id	app_tokenr   c                 C  sV   t t t | d }t0 t }|d| |||||f W 5 Q R X W 5 Q R X d S )N<   a  INSERT INTO portals (domain, access_token, refresh_token, expires_at, member_id, app_token)
               VALUES (?,?,?,?,?,?)
               ON CONFLICT(domain) DO UPDATE SET
                 access_token=excluded.access_token,
                 refresh_token=excluded.refresh_token,
                 expires_at=excluded.expires_at,
                 member_id=COALESCE(excluded.member_id, portals.member_id),
                 app_token=COALESCE(excluded.app_token, portals.app_token))r   timer   r   execute)r   r   r   r   r   r   
expires_atr
   r   r   r   upsert_portal_tokensD   s    r   r   )r   fieldvaluer   c              
   C  sJ   |dkst t0 t }|d| d|| f W 5 Q R X W 5 Q R X d S )N>   bot_idoperator_idr   zUPDATE portals SET z=? WHERE domain=?)AssertionErrorr   r   r   )r   r   r   r
   r   r   r   set_portal_fieldV   s    r#   zdict | None)r   r   c                 C  s\   t N t <}|d| f }|r,t|nd W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nz$SELECT * FROM portals WHERE domain=?)r   r   r   fetchonedict)r   r
   rowr   r   r   
get_portal\   s    r'   z	list[str]c                  C  sR   t D t 2} dd | d D W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nc                 S  s   g | ]}|d  qS )r   r   ).0rr   r   r   
<listcomp>d   s     z&all_portal_domains.<locals>.<listcomp>zSELECT domain FROM portals)r   r   r   Zfetchallr	   r   r   r   all_portal_domainsb   s    r+   )r   r   c                 C  s\   t N t <}|d| f }|r,|d nd W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nz,SELECT domain FROM portals WHERE member_id=?r   r   r   r   r$   )r   r
   r&   r   r   r   find_domain_by_memberg   s    r-   )r   	dialog_idr   c                 C  sb   t T t B}|d| |f }|r2t|d ndW  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nz>SELECT last_msg_id FROM cursors WHERE domain=? AND dialog_id=?last_msg_idr   )r   r   r   r$   r   )r   r.   r
   r&   r   r   r   
get_cursoro   s    r0   )r   r.   r/   r   c              
   C  s<   t . t }|d| |t|f W 5 Q R X W 5 Q R X d S )NzINSERT INTO cursors (domain, dialog_id, last_msg_id) VALUES (?,?,?)
               ON CONFLICT(domain, dialog_id) DO UPDATE SET last_msg_id=excluded.last_msg_id)r   r   r   r   )r   r.   r/   r
   r   r   r   
set_cursorx   s
    r1   c                   @  sF   e Zd ZU ded< ded< ded< ded< ded< ded< ded	< d
S )Pendingr   idr   r.   incomingdraftstatusr   
created_atN)__name__
__module____qualname____annotations__r   r   r   r   r2      s   
r2   )r   r.   r4   r5   r   c                 C  sz   t t jd d | |||dtt d}t@ t .}|d|j	|j
|j|j|j|j|jf W 5 Q R X W 5 Q R X |S )N   new)r3   r   r.   r4   r5   r6   r7   zgINSERT INTO pending (id, domain, dialog_id, incoming, draft, status, created_at) VALUES (?,?,?,?,?,?,?))r2   uuiduuid4hexr   r   r   r   r   r3   r   r.   r4   r5   r6   r7   )r   r.   r4   r5   pr
   r   r   r   create_pending   s    
	rB   zPending | None)
pending_idr   c                 C  sb   t T t B}|d| f }|r2tf t|nd W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nz SELECT * FROM pending WHERE id=?)r   r   r   r$   r2   r%   )rC   r
   r&   r   r   r   get_pending   s    rD   )r5   r6   )rC   r5   r6   r   c             
   C  sV   t H t 6}|d k	r&|d|| f |d k	r>|d|| f W 5 Q R X W 5 Q R X d S )Nz%UPDATE pending SET draft=? WHERE id=?z&UPDATE pending SET status=? WHERE id=?r   r   r   )rC   r5   r6   r
   r   r   r   update_pending   s
    rF   )r   r!   rC   r   c              
   C  s8   t * t }|d| ||f W 5 Q R X W 5 Q R X d S )NzINSERT INTO edit_state (domain, operator_id, pending_id) VALUES (?,?,?)
               ON CONFLICT(domain, operator_id) DO UPDATE SET pending_id=excluded.pending_idrE   )r   r!   rC   r
   r   r   r   set_edit_state   s
    rG   )r   r!   r   c                 C  s   t t t b}|d| |f }|s>W 5 Q R  W 5 Q R  d S |d| |f |d W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )NzBSELECT pending_id FROM edit_state WHERE domain=? AND operator_id=?z7DELETE FROM edit_state WHERE domain=? AND operator_id=?rC   r,   )r   r!   r
   r&   r   r   r   pop_edit_state   s    rH   )__doc__
__future__r   osr   	threadingr   r>   dataclassesr   typingr   getenvr   Lockr   r   r   r   r#   r'   r+   r-   r0   r1   r2   rB   rD   rF   rG   rH   r   r   r   r   <module>   s4   )	

	