a
    ‘–•j"  ã                   @   s&  d Z ddl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m	Z	 ddl
mZ ej ej e¡¡Zeejƒdkr€eejd ƒndZdejvZej d¡p¾eejƒd	kr²ejd	 nej ed
¡Zej ed¡ZdZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z G dd„ deƒZ!dd„ Z"e#dk�r"e"ƒ  dS )uà  
AI æ¼«å‰§ Â· æ— é™�ç”»å¸ƒ â€”â€” SQLite æœ¬åœ°æ•°æ�®æœ�åŠ¡å™¨
============================================
ç”¨æ³•:
    python3 aicomic-server.py            # é»˜è®¤ç«¯å�£ 8765ï¼Œæ•°æ�®åº“ aicomic.db
    python3 aicomic-server.py 9000       # æŒ‡å®šç«¯å�£
    AICOMIC_DB=/path/x.db python3 aicomic-server.py   # æŒ‡å®šæ•°æ�®åº“è·¯å¾„

å�¯åŠ¨å�Žæµ�è§ˆå™¨æ‰“å¼€: http://127.0.0.1:8765/
æ•°æ�®å…¨éƒ¨å­˜åœ¨ SQLite æ•°æ�®åº“æ–‡ä»¶ï¼ˆé»˜è®¤: aicomic.dbï¼‰ä¸­ï¼Œå�¯éš�æ—¶æ‹·è´�å¤‡ä»½ã€‚
é    N)ÚBaseHTTPRequestHandlerÚThreadingHTTPServer)Úurlparseé   i="  z--no-browserZ
AICOMIC_DBé   z
aicomic.dbzaicomic-canvas.htmlé   c                  C   s*   t  t¡} t j| _|  d¡ |  d¡ | S )NzÛ
        CREATE TABLE IF NOT EXISTS canvas_state (
            id INTEGER PRIMARY KEY CHECK (id = 1),
            cards TEXT NOT NULL,
            view  TEXT NOT NULL,
            updated_at REAL NOT NULL
        )
    z×
        CREATE TABLE IF NOT EXISTS snapshots (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            cards TEXT NOT NULL,
            view  TEXT NOT NULL,
            created_at REAL NOT NULL
        )
    )Úsqlite3ZconnectÚDB_PATHZRowZrow_factoryÚexecute)Úconn© r   úaicomic-server.pyÚdb   s
    


r   c                  C   sH   t ƒ } |  d¡ ¡ }|  ¡  |s$d S t |d ¡t |d ¡|d dœS )Nz;SELECT cards, view, updated_at FROM canvas_state WHERE id=1ÚcardsÚviewÚ
updated_at©r   r   r   ©r   r
   ZfetchoneÚcloseÚjsonÚloads)r   Úrowr   r   r   Ú
load_state5   s    r   c                 C   s|   t ƒ }t ¡ }| dtj| dd�tj|dd�|f¡ | dtj| dd�tj|dd�|f¡ | dtf¡ | ¡  | ¡  d S )NzÇ
        INSERT INTO canvas_state (id, cards, view, updated_at) VALUES (1, ?, ?, ?)
        ON CONFLICT(id) DO UPDATE SET cards=excluded.cards, view=excluded.view, updated_at=excluded.updated_at
    F©Zensure_asciiz@INSERT INTO snapshots (cards, view, created_at) VALUES (?, ?, ?)zYDELETE FROM snapshots WHERE id NOT IN (SELECT id FROM snapshots ORDER BY id DESC LIMIT ?))r   Útimer
   r   ÚdumpsÚMAX_SNAPSHOTSZcommitr   )r   r   r   Znowr   r   r   Ú
save_state>   s    ýÿÿr   c                  C   s.   t ƒ } |  dtf¡ ¡ }|  ¡  dd„ |D ƒS )Nz=SELECT id, created_at FROM snapshots ORDER BY id DESC LIMIT ?c                 S   s   g | ]}|d  |d dœ‘qS )ÚidÚ
created_at)r   r   r   )Ú.0Úrr   r   r   Ú
<listcomp>R   ó    z"list_snapshots.<locals>.<listcomp>)r   r
   r   Zfetchallr   )r   Zrowsr   r   r   Úlist_snapshotsM   s    ÿr$   c                 C   sF   t ƒ }| d| f¡ ¡ }| ¡  |s(d S t |d ¡t |d ¡dœS )Nz,SELECT cards, view FROM snapshots WHERE id=?r   r   )r   r   r   )Úsidr   r   r   r   r   Úrestore_snapshotU   s    r&   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )ÚHandlerzHTTP/1.1c                 C   s(   |   dd¡ |   dd¡ |   dd¡ d S )NzAccess-Control-Allow-OriginÚ*zAccess-Control-Allow-MethodszGET, POST, OPTIONSzAccess-Control-Allow-HeadersúContent-Type)Úsend_header©Úselfr   r   r   Ú_corsa   s    zHandler._corsc                 C   s^   t j|dd� d¡}|  |¡ |  dd¡ |  dtt|ƒƒ¡ |  ¡  |  ¡  | j	 
|¡ d S )NFr   úutf-8r)   zapplication/json; charset=utf-8úContent-Length)r   r   ÚencodeÚsend_responser*   ÚstrÚlenr-   Úend_headersÚwfileÚwrite)r,   ÚcodeÚobjÚbodyr   r   r   Ú_jsonf   s    
zHandler._jsonc                 C   sV   t | j dd¡pdƒ}|dkr"d S zt | j |¡ d¡¡W S  tyP   Y d S 0 d S )Nr/   r   r.   )	ÚintZheadersÚgetr   r   ZrfileÚreadÚdecodeÚ	Exception)r,   Zlengthr   r   r   Ú
_read_jsono   s    zHandler._read_jsonc                 C   s   |   d¡ |  ¡  |  ¡  d S )NéÌ   )r1   r-   r4   r+   r   r   r   Ú
do_OPTIONSx   s    
zHandler.do_OPTIONSc                 C   s(  t | jƒj}|dv r¸z~ttdƒ�}| ¡ }W d   ƒ n1 s>0    Y  |  d¡ |  dd¡ |  dtt|ƒƒ¡ |  	¡  |  
¡  | j |¡ W d S  ty¶   |  ddd	i¡ Y d S 0 |d
krôtƒ }|d u rä|  dd d d dœ¡ n|  d|¡ d S |dk�r|  dtƒ ¡ d S |  ddd| i¡ d S )N)ú/z/index.htmlz/aicomic-canvas.htmlÚrbéÈ   r)   ztext/html; charset=utf-8r/   é”  Úerrorz<aicomic-canvas.html not found, run server from its directoryú
/api/stater   z/api/snapshotsúnot found: )r   ÚpathÚopenÚ	HTML_PATHr=   r1   r*   r2   r3   r-   r4   r5   r6   ÚFileNotFoundErrorr:   r   r$   )r,   rJ   Úfr9   Ústr   r   r   Údo_GET}   s2    &

zHandler.do_GETc           	      C   s°  t | jƒj}|dkrx|  ¡ }|d u s4t| d¡tƒsH|  dddi¡ d S t|d | di ¡ƒ |  ddt ¡ d	œ¡ d S |d
k�r<|  ¡ }|d u sœ| d¡s°|  dddi¡ d S zHdd l	}|j
|d t| dd¡pÔdƒt| dd¡ƒd�}|  d|¡ W n> t�y6 } z$|  dddt|ƒ i¡ W Y d }~n
d }~0 0 d S |dk�r
|  ¡ �pRi }zrdd l	}|j| dd¡| dd¡| d¡�p„g | dd¡| dd¡| dd¡| dd¡d�}|  dd|d œ¡ W n> t�y } z$|  dd!t|ƒdd"œ¡ W Y d }~n
d }~0 0 d S | d#¡�r˜| d$¡�r˜| d%¡d& }zt|ƒ}W n& t�yb   |  ddd'i¡ Y d S 0 t|ƒ}|d u �rˆ|  d(dd)i¡ n|  d|¡ d S |  d(dd*| i¡ d S )+NrH   r   i�  rG   z,body must be {"cards": [...], "view": {...}}r   rE   T)ÚokZsaved_atz/api/import-novelÚtextzCbody must be {"text": "...", "target_chars": 1500, "use_llm": true}r   Útarget_charsiÜ  Úuse_llm)rS   rT   iô  u   å¯¼å…¥å¤±è´¥: %sz/api/image-promptÚsceneÚ ÚpromptÚcharsÚmoveÚstyleÚ
style_packZcelÚqualityZhigh)rU   ZdetailrX   rY   rZ   r[   r\   )rQ   rW   F)rQ   rG   rW   z/api/snapshots/z/restorerC   é   zbad snapshot idrF   zsnapshot not foundrI   )r   rJ   r@   Ú
isinstancer<   Úlistr:   r   r   Úaicomic_importZ
run_importr;   Úboolr?   r2   Zoptimize_image_promptÚ
startswithÚendswithÚsplitÚ
ValueErrorr&   )	r,   rJ   Údatar`   ÚresÚerW   r%   rO   r   r   r   Údo_POST™   sn    
ý.






ù.
zHandler.do_POSTc                 G   s"   t j dt d¡|| f ¡ d S )Nz[%s] %s
z%H:%M:%S)ÚsysÚstderrr6   r   Ústrftime)r,   ZfmtÚargsr   r   r   Úlog_messageÑ   s    zHandler.log_messageN)Ú__name__Ú
__module__Ú__qualname__Zprotocol_versionr-   r:   r@   rB   rP   ri   rn   r   r   r   r   r'   ^   s   		8r'   c                  C   sº   t dƒ t dƒ t dt ƒ t dt ƒ t dƒ t dƒ tj t¡sPt dt ƒ tdtftƒ} t	rŽzt
 dd	d
„ ¡ ¡  W n tyŒ   Y n0 z|  ¡  W n ty´   t dƒ Y n0 d S )Nz8========================================================u,     AI æ¼«å‰§ Â· æ— é™�ç”»å¸ƒ SQLite æœ�åŠ¡å™¨z  URL : http://127.0.0.1:%d/z
  DB  : %su     å�œæ­¢: Ctrl+CuQ   è­¦å‘Š: æœªæ‰¾åˆ° %s ï¼Œè¯·æŠŠæœ¬è„šæœ¬å’Œ aicomic-canvas.html æ”¾åœ¨å�Œä¸€ç›®å½•z	127.0.0.1g      ð?c                   S   s   t  dt ¡S )Nzhttp://127.0.0.1:%d/)Ú
webbrowserrK   ÚPORTr   r   r   r   Ú<lambda>á   r#   zmain.<locals>.<lambda>u
   
å·²å�œæ­¢)Úprintrs   r	   ÚosrJ   ÚexistsrL   r   r'   Ú	AUTO_OPENZ	threadingZTimerÚstartr?   Zserve_foreverÚKeyboardInterrupt)Zserverr   r   r   ÚmainÕ   s$    r{   Ú__main__)$Ú__doc__r   rv   r   rj   r   rr   Zhttp.serverr   r   Zurllib.parser   rJ   ÚdirnameÚabspathÚ__file__ZBASE_DIRr3   Úargvr;   rs   rx   Úenvironr<   Újoinr	   rL   r   r   r   r   r$   r&   r'   r{   ro   r   r   r   r   Ú<module>   s.    
2		w
