Ë
    Šd¨j•  ã                  ó^  — 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	Z	ddl
Z
ddlZddlZ ej                  e«      j                  «       j                   j                   Zedz  dz  Zdddd	œZdd
„Zdd„Zdd„Zd d„Zd eej                  j3                  «       dz  dz  «      ddddddgZdZd!d„Z eej                  j3                  «       dz  dz  «      Zd"d„Zd#d„Ze dk(  r	  e
jB                   e«       «       yy# e"$ r'Z# ede#›�«        e
jB                  d«       Y dZ#[#ydZ#[#ww xY w)$u¿  comments.sqlite ã�®ä¸–ä»£ãƒ�ãƒƒã‚¯ã‚¢ãƒƒãƒ—ã€‚

- `VACUUM INTO` ã�§ä¸€è²«ã�—ã�Ÿã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆã‚’å�–ã‚‹ (ç¨¼åƒ�ä¸­ã�® daemon ã�¨å…±å­˜ã�§ã��ã‚‹ã€‚ å�–å¾—ä¸­ã�¯
  æ›¸ã��è¾¼ã�¿ã�Œæ•°å��ç§’å¾…ã�Ÿã�•ã‚Œã‚‹ã�Œã€� daemon å�´ã�¯ busy_timeout=30s ã�§å�¸å�Žã�™ã‚‹)
- ã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆã‚’ `PRAGMA quick_check` ã�§æ¤œè¨¼ã�—ã�¦ã�‹ã‚‰ zstd åœ§ç¸®
- DB ã�¨ã�¯åˆ¥ã�®ç‰©ç�†ãƒ‡ã‚£ã‚¹ã‚¯ã�«ç½®ã�� (æ—¢å®š: ~/backups/stream-commentsã€� DB ã�¯ sda / æ—¢å®šå…ˆã�¯ sdb)
- ä¸–ä»£: æ—¥æ¬¡ 7 / é€±æ¬¡ (æ—¥æ›œ) 4 / æœˆæ¬¡ (1 æ—¥) 12
- channels.toml ã�¨ scripts/ ã‚‚ä¸€ç·’ã�« tar ã�§ä¿�å­˜ (è¨­å®šã�¨ã‚³ãƒ¼ãƒ‰ã�®å¾©å…ƒç”¨)
- `--offsite user@host:dir` ã‚’ä»˜ã�‘ã‚‹ã�¨ã��ã�®æ—¥ã�®ã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆã‚’ scp ã�§åˆ¥ãƒžã‚·ãƒ³ã�«ã‚‚é€�ã‚‹ (14 æ—¥ä¿�æŒ�)
- `--gdrive remote:path` ã‚’ä»˜ã�‘ã‚‹ã�¨ weekly / monthly ã‚’ rclone ã�§ Google Drive (æš—å�·åŒ– remote) ã�«å�ŒæœŸ

ä½¿ã�„æ–¹ (systemd timer ã�‹ã‚‰):
    python3 scripts/backup_db.py [--dest DIR] [--offsite HOST:DIR]
é    )ÚannotationsNÚdatazcomments.sqliteé   é   é   )ÚdailyÚweeklyÚmonthlyc                ó$   — t        d| › �d¬«       y )Nz	[backup] T)Úflush)Úprint)Úmsgs    úscripts/backup_db.pyÚlogr       s   € Ü	ˆI�c�UÐ
 4Ö(ó    c                ó  — | d|› d�z  }|j                  d¬«       t        j                  «       }t        j                  dt
        › d�dd¬«      }	 |j                  d	«       |j                  d
t        |«      f«       |j                  «        t        d|j                  «       j                  dz  d›dt        j                  «       |z
  d›d�«       t        j                  t        |«      «      }	 |j                  d«      j                  «       d   }|j                  d«      j                  «       d   }|j                  «        |dk7  rt        d|› �«      ‚t        d|d›�«       | d|› d�z  }t        j                  ddddddt        |«      d t        |«      g	d¬!«       t        d"|j                   › d#|j                  «       j                  dz  d›d$�«       |S # |j                  «        w xY w# |j                  «        w xY w)%Nz
.comments-z.sqlite.tmpT)Ú
missing_okzfile:z?mode=rog      ^@)ÚuriÚtimeoutzPRAGMA busy_timeout = 120000zVACUUM INTO ?zVACUUM INTO i   ú.0fz MiB in z.1fÚszPRAGMA quick_checkr   zSELECT count(*) FROM commentsÚokzquick_check failed: zquick_check ok, rows=ú,ú	comments-ú.sqlite.zstÚzstdú-qz-T0z-10z--rmz-fú-o©Úchecku   compressed â†’ ú z MiB)ÚunlinkÚtimeÚ	monotonicÚsqlite3ÚconnectÚDBÚexecuteÚstrÚcloser   ÚstatÚst_sizeÚfetchoneÚRuntimeErrorÚ
subprocessÚrunÚname)	ÚdestÚstampÚtmpÚtÚconnÚchkÚresÚrowsÚouts	            r   Úsnapshotr;   $   sÇ  € Ø
�:˜e˜W KÐ0Ñ
0€CØ‡J�J˜$€JÔÜ�‰Ó€AÜ�?‰?˜U¤2 $ hÐ/°TÀ5ÔI€DðØ�‰Ð3Ô4Ø�‰�_¤s¨3£x kÔ2à�
‰
ŒÜˆ,�s—x‘x“z×)Ñ)¨EÑ1°#Ð6°h¼t¿~¹~Ó?OÐRSÑ?SÐTWÐ>XÐXYÐZÔ[Ü
�/‰/œ#˜c›(Ó
#€CðØ�k‰kÐ.Ó/×8Ñ8Ó:¸1Ñ=ˆØ�{‰{Ð:Ó;×DÑDÓFÀqÑIˆà�	‰	ŒØ
ˆd‚{ÜÐ1°#°Ð7Ó8Ð8ÜÐ
  Q˜xÐ(Ô)Ø
�9˜U˜G ;Ð/Ñ
/€CÜ‡N�N�F˜D %¨°¸¼cÀ#»hÈÌcÐRUËhÐWÐ_cÕdÜˆ/˜#Ÿ(™(˜ 1 S§X¡X£Z×%7Ñ%7¸%Ñ%?ÀÐ$DÀDÐIÔJØ€Jøð 	�
‰
�ûð 	�	‰	�ús   Á-G Ã1AG1 ÇG.Ç1Hc                óÞ   — | d|› d�z  }t        j                  |d«      5 }dD ]1  }t        |z  }|j                  «       sŒ|j	                  ||d„ ¬«       Œ3 	 d d d «       |S # 1 sw Y   |S xY w)Núconfig-ú.tar.gzzw:gz)zchannels.tomlÚscriptszrequirements.txtc                ó\   — d| j                   v s| j                   j                  d«      rd S | S )NÚ__pycache__z.bak)r1   Úendswith)Útis    r   ú<lambda>zconfig_tar.<locals>.<lambda>D   s.   € À-ÐSU×SZÑSZÑBZÐ^`×^eÑ^e×^nÑ^nÐouÔ^v¸$€ Ð|~€ r   )ÚarcnameÚfilter)ÚtarfileÚopenÚROOTÚexistsÚadd)r2   r3   r:   Útfr1   Úps         r   Ú
config_tarrN   >   s|   € Ø
�7˜5˜' Ð)Ñ
)€CÜ	�‰�c˜6Ó	"ð @ bØDò 	@ˆDÜ�t‘ˆAØ�x‰x�zØ—‘�q $Ñ/~�Õñ	@÷@ð
 €J÷@ð
 €Jús    A"Á A"Á"A,c           	     óŠ  ‡— dg}|j                  «       dk(  r|j                  d«       |j                  dk(  r|j                  d«       |D ]E  }| |z  }|j                  d¬«       ||fD ]%  }t	        j
                  |||j                  z  «       Œ' ŒG |j                  «        |j                  «        t        j                  «       D ]z  \  }}| |z  }|j                  «       sŒdD ]Z  Št        ˆfd	„|j                  «       D «       «      }	|	d |  D ]-  }
|
j                  «        t        d
|› d|
j                  › �«       Œ/ Œ\ Œ| y )Nr   é   r	   é   r
   T)Úexist_ok)r   r=   c              3  óZ   •K  — | ]"  }|j                   j                  ‰«      sŒ|–— Œ$ y ­w)N)r1   Ú
startswith)Ú.0rM   Úprefixs     €r   ú	<genexpr>zrotate.<locals>.<genexpr>Z   s"   øè ø€ ÒO °Q·V±V×5FÑ5FÀvÕ5Nœ1ÑOùs   ƒ +¤+zrotate: removed ú/)ÚweekdayÚappendÚdayÚmkdirÚshutilÚcopy2r1   r"   ÚKEEPÚitemsÚis_dirÚsortedÚiterdirr   )r2   ÚtodayÚsnapÚconfÚtiersÚtierÚdÚfÚkeepÚfilesÚoldrV   s              @r   Úrotatern   H   s+  ø€ ØˆI€EØ‡}�}ƒ˜!ÒØ�‰�XÔØ‡y�y�A‚~Ø�‰�YÔØò (ˆØ�4‰KˆØ	�‰˜ˆÔØ˜�ò 	(ˆAÜ�L‰L˜˜A §¡™JÕ'ñ	(ð(ð
 	‡K�K„MØ‡K�K„MÜ—j‘j“lò :‰
ˆˆdØ�4‰KˆØ�x‰xŒzØØ.ò 	:ˆFÜÓO a§i¡i£kÔOÓOˆEØ˜V˜t˜e�}ò :�Ø—
‘
”ÜÐ& t f¨A¨c¯h©h¨ZÐ8Õ9ñ:ñ	:ñ	:r   z-iz.sshÚid_backup_ed25519r   zBatchMode=yeszConnectTimeout=15z StrictHostKeyChecking=accept-newé   c           	     óª  — |j                  d«      \  }}}|xs d}t        | d|› d�z  «      t        | d|› d�z  «      g}t        j                  dgt        ¢|‘d|› �‘d	¬
«       t        j                  ddgt        ¢|¢|› d|› d�‘d	¬
«       t        j                  dgt        ¢|‘d|› dt
        › d�‘d	¬
«       t        d|› d|› dt
        › d�«       y)uÍ   ã��ã�®æ—¥ã�®ã‚¹ãƒŠãƒƒãƒ—ã‚·ãƒ§ãƒƒãƒˆã�¨è¨­å®š tar ã‚’ scp ã�§åˆ¥ãƒžã‚·ãƒ³ã�¸é€�ã‚Šã€� å�¤ã�„ã‚‚ã�®ã‚’æ¶ˆã�™ã€‚

    é€�ã‚Šå…ˆã�« rsync ã�Œç„¡ã��ã�¦ã‚‚å‹•ã��ã‚ˆã�† scp + ssh ã� ã�‘ã�§å®Œçµ�ã�•ã�›ã‚‹ã€‚
    ú:zbackups/stream-commentsr   r   r=   r>   Ússhz	mkdir -p Tr   Úscpr   rX   zfind zJ -maxdepth 1 -type f \( -name 'comments-*' -o -name 'config-*' \) -mtime +z -deleteu   offsite copied â†’ z (keep z days)N)Ú	partitionr)   r/   r0   ÚSSHÚOFFSITE_KEEP_DAYSr   )r   r3   ÚtargetÚhostÚ_Úrdirrl   s          r   Úoffsiter|   e   s  € ð
 ×$Ñ$ SÓ)�M€Dˆ!ˆTØÒ,Ð,€DÜ�˜9 U G¨;Ð7Ñ7Ó8¼#¸eÈÐPUÈwÐV]ÐF^Ñ>^Ó:_Ð`€EÜ‡N�N�EÐ:œCÐ: Ð:¨°4°&Ð'9Ð:À$ÕGÜ‡N�N�E˜4ÐA¤#ÐA¨ÐA°$°°q¸¸¸aÐ/@ÐAÈÕNÜ‡N�NØ	ð 	@”ð 	@�dð 	@Ø��ÐbÔctÐbuÐu}Ð	~ð	@àõô
 Ð
˜d˜V 1 T F¨'Ô2CÐ1DÀFÐKÕLr   ÚbinÚrclonec                óÚ   — dD ]X  }| |z  }|j                  «       sŒt        j                  t        dt	        |«      |j                  d«      › d|› �ddddgd¬	«       ŒZ t        d
|› �«       y)u{  é€±æ¬¡ãƒ»æœˆæ¬¡ã�®ä¸–ä»£ã� ã�‘ã‚’ rclone ã�§ Google Drive (æš—å�·åŒ– remote) ã�«å�ŒæœŸã�™ã‚‹ã€‚

    æ—¥æ¬¡ã�¾ã�§é€�ã‚‹ã�¨ Drive å®¹é‡�ã‚’é£Ÿã�†ã�®ã�§ã€� é•·æœŸä¿�æŒ�ã�® weekly / monthly ã�«çµžã‚‹ã€‚
    remote ã�¯ rclone ã�® crypt remote (ä¾‹: gdrive-crypt:stream-comments) ã‚’æƒ³å®šã�—ã€�
    æœ¬æ–‡ã�¯ Drive ä¸Šã�§ã�¯æš—å�·åŒ–ã�•ã‚Œã�Ÿãƒ•ã‚¡ã‚¤ãƒ«å��ãƒ»ä¸­èº«ã�«ã�ªã‚‹ã€‚
    )r	   r
   ÚsyncrX   z--transfersÚ2z--stats-one-liner   Tr   u!   gdrive synced weekly/monthly â†’ N)ra   r/   r0   ÚRCLONEr)   Úrstripr   )r2   Úremoterh   Úsrcs       r   Úgdriver†   z   sy   € ð &ò 
ˆØ�T‰kˆØ�z‰zŒ|ØÜ�‰Ü�VœS ›X¨&¯-©-¸Ó*<Ð)=¸Q¸t¸fÐ'EÀ}ÐVYÐ[mÐosÐtØö	
ð	
ô Ð
+¨F¨8Ð4Õ5r   c                 ó  — t        j                  «       } | j                  dt        t        j
                  j                  «       dz  dz  «      ¬«       | j                  dd¬«       | j                  dd	¬«       | j                  «       }t	        j
                  |j                  «      }|j                  d
d
¬«       t        j                  j                  «       }|j                  d«      }t        ||«      }t        ||«      }t!        ||||«       |j"                  rt#        |dz  ||j"                  «       |j$                  rt%        ||j$                  «       t'        j(                  |«      j*                  dz  }t-        d|d›d�«       y)Nz--destÚbackupszstream-comments)Údefaultz--gdriveuR   rclone remote (ä¾‹: gdrive-crypt:stream-comments)ã€‚ weekly / monthly ã� ã�‘é€�ã‚‹)Úhelpz	--offsiteu@   é€�ã‚Šå…ˆ (ä¾‹: kuroneko@192.168.10.200:backups/stream-comments)T)ÚparentsrR   z%Y%m%dr   i   @zdone. free on backup disk: r   z GiBr   )ÚargparseÚArgumentParserÚadd_argumentr)   ÚpathlibÚPathÚhomeÚ
parse_argsr2   r\   ÚdtÚdaterd   Ústrftimer;   rN   rn   r|   r†   r]   Ú
disk_usageÚfreer   )ÚapÚnsr2   rd   r3   re   rf   r—   s           r   Úmainrš   Œ   s1  € Ü	×	 Ñ	 Ó	"€BØ‡O�O�H¤c¬'¯,©,×*;Ñ*;Ó*=À	Ñ*IÐL]Ñ*]Ó&^€OÔ_Ø‡O�O�JÐ%y€OÔzØ‡O�O�KÐ&h€OÔiØ	�‰‹€BÜ�<‰<˜Ÿ™Ó €DØ‡J�J�t d€JÔ+Ü�G‰G�M‰M‹O€EØ�N‰N˜8Ó$€EÜ�D˜%Ó €DÜ�d˜EÓ"€DÜ
ˆ4�˜˜dÔ#Ø	‡z‚zÜ��w‘  r§z¡zÔ2Ø	‡y‚yÜˆt�R—Y‘YÔÜ×Ñ˜TÓ"×'Ñ'¨%Ñ/€DÜÐ
% d¨3 Z¨tÐ4Ô5Ør   Ú__main__zFAILED: rQ   )r   r)   ÚreturnÚNone)r2   úpathlib.Pathr3   r)   rœ   rž   )
r2   rž   rd   zdt.datere   rž   rf   rž   rœ   r�   )r   rž   r3   r)   rx   r)   rœ   r�   )r2   rž   r„   r)   rœ   r�   )rœ   Úint)$Ú__doc__Ú
__future__r   rŒ   Údatetimer“   r�   r]   r%   r/   ÚsysrG   r#   r�   Ú__file__ÚresolveÚparentrI   r'   r_   r   r;   rN   rn   r)   r‘   rv   rw   r|   r‚   r†   rš   Ú__name__ÚexitÚ	ExceptionÚe© r   r   ú<module>r¬      sF  ðñõ #ã Û Û Û Û Û Û 
Û Û à€w‡|�|�HÓ×%Ñ%Ó'×.Ñ.×5Ñ5€Ø	ˆF�]Ð&Ñ&€Ø˜a¨BÑ/€ó)óó4ó:ð0 ‰S�—‘×"Ñ"Ó$ vÑ-Ð0CÑCÓDÀdÈOØÐ  $Ð(JðL€àÐ óMñ$ 
ˆW�\‰\×ÑÓ  5Ñ(¨8Ñ3Ó	4€ó6ó$ð, ˆzÒðØˆ�‰‘“Õð øð ò Ùˆh�q�eÐÔØˆ�‰��‰ûðús   Ã'D  Ä D,ÄD'Ä'D,