§
    �åiQ&  ã                   ól  — d dl mZmZmZmZmZmZmZmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZmZm Z m!Z! ddl"m#Z#m$Z$m%Z%m&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-m-Z-m.Z.  eddg¬¦  «        Z/ ee¬¦  «        Z0e/ 1                    de¬¦  «         ee#¦  «        fdefd„¦   «         Z2e/ 3                    de¬¦  «         ee¦  «         e e$d¦  «        ¦  «        fdededefd„¦   «         Z4e/ 5                    d¦  «         ed¦  «         ee¦  «         ee#¦  «        fdededefd „¦   «         Z6e/ 1                    d!¦  «        d d" ee¦  «         ee&¦  «        fd#ed$e7d%e7dedee         f
d&„¦   «         Z8e/ 5                    d!e dz  ¬¦  «         ee¦  «         ee&¦  «        fd'ededee         fd(„¦   «         Z9e/ 3                    d)e dz  ¬¦  «         ee¦  «         ee&¦  «        fd*e:d'ededee         fd+„¦   «         Z;e/ <                    d)ej=        ¬,¦  «         ee¦  «         ee&¦  «        fd*e:dedee         fd-„¦   «         Z>e/ 1                    d.e dz  ¬¦  «         ee¦  «         ee&¦  «        fd*e:dedee         fd/„¦   «         Z?dS )0é    )	Ú	APIRouterÚDependsÚHTTPExceptionÚstatusÚ
UploadFileÚFileÚFormÚRequestÚResponse)ÚSession)ÚOptional)ÚLimiter)Úget_remote_addressé   )Úget_db)ÚUser)ÚWatchHistory)ÚStream)ÚUserResponseÚUserProfileUpdate)ÚWatchHistoryCreateÚWatchHistoryUpdateÚWatchHistoryResponseÚWatchHistoryWithStream)Úget_current_active_userÚrequire_permissionÚrequire_any_permissionÚget_current_user_optional)ÚsettingsN)ÚdatetimeÚtimezonez
/api/usersÚusers)ÚprefixÚtags)Úkey_funcz/me)Úresponse_modelÚcurrent_userc              ƒ   ó.   K  — t          j        | ¦  «        S ©N)r   Úfrom_orm)r'   s    ú/app/app/api/users.pyÚget_my_profiler,      s   è è € åÔ  Ñ.Ô.Ð.ó    zuser:update:ownÚprofile_dataÚdbc              ƒ   óì   K  — | j         �| j         |_         t          j        t          j        ¦  «        |_        |                     ¦   «          |                     |¦  «         t          j	        |¦  «        S r)   )
Úprofile_image_urlr    Únowr!   ÚutcÚ
updated_atÚcommitÚrefreshr   r*   )r.   r/   r'   s      r+   Úupdate_my_profiler7      s`   è è € ð Ô%Ð1Ø)5Ô)GˆÔ&Ý&œl­8¬<Ñ8Ô8€LÔØ‡I‚I�K„K€KØ‡J‚Jˆ|ÑÔÐÝÔ  Ñ.Ô.Ð.r-   z/me/profile-image.Úfilec              ƒ   óŽ  K  — | j         r| j                              d¦  «        st          t          j        d¬¦  «        ‚g d¢}| j         |vrt          t          j        d¬¦  «        ‚t
          j                             t          j	        d¦  «        }t          j
        |d¬¦  «         | j         d	k    rd
nd}|j        › d|› �}t
          j                             ||¦  «        }t          |d¦  «        5 }|                      ¦   «         ƒ d {V —†}	t          |	¦  «        dk    rt          t          j        d¬¦  «        ‚|                     |	¦  «         d d d ¦  «         n# 1 swxY w Y   d|› �|_        t#          j        t&          j        ¦  «        |_        |                     ¦   «          |                     |¦  «         d|j        dœS )Nzimage/zOnly image files are allowed©Ústatus_codeÚdetail)ú	image/pngz
image/jpegz	image/jpgz$Only PNG and JPEG images are allowedÚprofile_imagesT)Úexist_okr=   ÚpngÚjpgú.Úwbi  P zFile size exceeds 5MB limitz/storage/profile_images/z#Profile image uploaded successfully)Úmessager1   )Úcontent_typeÚ
startswithr   r   ÚHTTP_400_BAD_REQUESTÚosÚpathÚjoinr   ÚSTORAGE_PATHÚmakedirsÚidÚopenÚreadÚlenÚwriter1   r    r2   r!   r3   r4   r5   r6   )
r8   r/   r'   Úallowed_typesÚprofile_images_dirÚfile_extensionÚfilenameÚ	file_pathÚbufferÚcontents
             r+   Úupload_profile_imagerY   +   s  è è € ð Ôð 
 DÔ$5×$@Ò$@ÀÑ$JÔ$Jð 
ÝÝÔ3Ø1ð
ñ 
ô 
ð 	
ð =Ð<Ð<€MØÔ Ð-Ð-ÝÝÔ3Ø9ð
ñ 
ô 
ð 	
õ œŸš¥hÔ&;Ð=MÑNÔNÐÝ„KÐ"¨TÐ2Ñ2Ô2Ð2ð #Ô/°;Ò>Ð>�U�UÀE€NØ”/Ð4Ð4 NÐ4Ð4€HÝ”—’Ð/°Ñ:Ô:€Iõ 
ˆi˜Ñ	Ô	ð  &ØŸ	š	™œÐ#Ð#Ð#Ð#Ð#Ð#ˆåˆw‰<Œ<˜/Ò)Ð)ÝÝ"Ô7Ø4ðñ ô ð ð 	�Š�WÑÔÐðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð &KÀÐ%JÐ%J€LÔ"Ý&œl­8¬<Ñ8Ô8€LÔØ‡I‚I�K„K€KØ‡J‚Jˆ|ÑÔÐà<ÐS_ÔSqÐrÐrÐrs   Ã2AEÅE Å#E z/me/watch-historyé2   ÚrequestÚskipÚlimitc              ƒ   ó®  K  — |sg S |                      t          ¦  «                             t          j        |j        k    ¦  «                             t          j                             ¦   «         ¦  «                             |¦  «         	                    |¦  «         
                    ¦   «         }g }|D ]É}|                      t          ¦  «                             t          j        |j        k    ¦  «                             ¦   «         }t          j        |¦  «                             ¦   «         }	|r|j        |	d<   |j        |	d<   |j        |	d<   nd |	d<   d |	d<   d |	d<   |                     t+          di |	¤Ž¦  «         ŒÊt-          j        t1          j        d„ |D ¦   «         d¬¦  «                             ¦   «         ¦  «                             ¦   «         }
| j                             d¦  «        }||
k    rt=          d¬	¦  «        S g }|D ]¡}|                     ¦   «         }t?          |d
         ¦  «        |d
<   t?          |d         ¦  «        |d<   t?          |d         ¦  «        |d<   dD ]+}||v r%||         �||                               ¦   «         ||<   Œ,|                     |¦  «         Œ¢t=          t1          j        |¦  «        d¬¦  «        }|
|j        d<   |S )NÚstream_titleÚstream_thumbnail_urlÚstream_duration_secondsc                 ó|   — g | ]9}t          |j        ¦  «        |j        r|j                             ¦   «         nd dœ‘Œ:S )N)rM   Úlast_watched_at)ÚstrrM   rc   Ú	isoformat)Ú.0Úrs     r+   ú
<listcomp>z(get_my_watch_history.<locals>.<listcomp>}   s\   € ð #ð #ð #ð õ �!”$‰iŒiØ<=Ô<MÐW˜1Ô,×6Ò6Ñ8Ô8Ð8ÐSWð$ð $ð #ð #ð #r-   T)Ú	sort_keyszif-none-matchi0  ©r;   rM   Úuser_idÚ	stream_id)rc   Ú
created_atr4   zapplication/json)rX   Ú
media_typeÚETag© )!Úqueryr   Úfilterrk   rM   Úorder_byrc   ÚdescÚoffsetr]   Úallr   rl   Úfirstr   r*   Ú
model_dumpÚtitleÚthumbnail_urlÚduration_secondsÚappendr   ÚhashlibÚmd5ÚjsonÚdumpsÚencodeÚ	hexdigestÚheadersÚgetr   rd   re   )r[   r\   r]   r/   r'   Úwatch_historyÚresultÚwhÚstreamÚwh_dictÚetagÚif_none_matchÚresponse_datarg   Úr_dictÚkeyÚresponses                    r+   Úget_my_watch_historyr�   ]   s×  è è € ð ð Øˆ	à—H’H�\Ñ*Ô*×1Ò1ÝÔ ¤Ò/ñô ç‚h�|Ô+×0Ò0Ñ2Ô2Ñ3Ô3·F²F¸4±L´LÇÂÀuÁÄÏcÊcÉeÌeð ð
 €FØð 9ð 9ˆØ—’�&Ñ!Ô!×(Ò(­¬°b´lÒ)BÑCÔC×IÒIÑKÔKˆÝ&Ô/°Ñ3Ô3×>Ò>Ñ@Ô@ˆØð 	6Ø&,¤lˆG�NÑ#Ø.4Ô.BˆGÐ*Ñ+Ø17Ô1HˆGÐ-Ñ.Ð.à&*ˆG�NÑ#Ø.2ˆGÐ*Ñ+Ø15ˆGÐ-Ñ.Ø�ŠÕ,Ð7Ð7¨wÐ7Ð7Ñ8Ô8Ð8Ð8õ Œ;•t”zð #ð #ð ð#ñ #ô #ð #'ð(ñ (ô (÷ )/ª©¬ñ2ô 2÷ 3<²)±+´+ð 	ð ”O×'Ò'¨Ñ8Ô8€MØ˜ÒÐÝ CÐ(Ñ(Ô(Ð(ð €MØð 	%ð 	%ˆØ—’‘”ˆÝ˜6 $œ<Ñ(Ô(ˆˆt‰Ý  yÔ 1Ñ2Ô2ˆˆyÑÝ! &¨Ô"5Ñ6Ô6ˆˆ{ÑàBð 	6ð 	6ˆCØ�fˆ}ˆ} ¨¤Ð!8Ø$ Sœk×3Ò3Ñ5Ô5��s‘øØ×Ò˜VÑ$Ô$Ð$Ð$å¥¤
¨=Ñ 9Ô 9ÐFXÐYÑYÔY€HØ#€HÔ�VÑØ€Or-   Ú
watch_datac           	   ƒ   óØ  K  — |sd S |                      t          ¦  «                             t          j        | j        k    ¦  «                             ¦   «         }|st          t          j        d¬¦  «        ‚|                      t          ¦  «                             t          j
        |j        k    t          j        | j        k    ¦  «                             ¦   «         }|rx| j        |_        | j        |_        t          j        t          j        ¦  «        |_        |                     ¦   «          |                     |¦  «         t)          j        |¦  «        S t          |j        | j        | j        | j        t          j        t          j        ¦  «        ¬¦  «        }|                     |¦  «         |                     ¦   «          |                     |¦  «         t)          j        |¦  «        S )NzStream not foundr:   )rk   rl   Úlast_position_secondsÚ	completedrc   )rq   r   rr   rM   rl   rw   r   r   ÚHTTP_404_NOT_FOUNDr   rk   r“   r”   r    r2   r!   r3   rc   r5   r6   r   r*   Úadd)r‘   r/   r'   rˆ   ÚexistingÚnew_watch_historys         r+   Úcreate_or_update_watch_historyr™   ™   s©  è è € ð ð Øˆtð �XŠX•fÑÔ×$Ò$¥V¤Y°*Ô2FÒ%FÑGÔG×MÒMÑOÔO€FØð 
ÝÝÔ1Ø%ð
ñ 
ô 
ð 	
ð �xŠx�Ñ%Ô%×,Ò,ÝÔ ¤Ò/ÝÔ *Ô"6Ò6ñô ÷ ‚e�g„gð ð
 ð @à)3Ô)IˆÔ&Ø'Ô1ˆÔÝ#+¤<µ´Ñ#=Ô#=ˆÔ Ø
�	Š	‰ŒˆØ
�
Š
�8ÑÔÐÝ#Ô,¨XÑ6Ô6Ð6õ )Ø ”OØ Ô*Ø",Ô"BØ Ô*Ý$œL­¬Ñ6Ô6ð
ñ 
ô 
Ðð 	�ŠÐ Ñ!Ô!Ð!Ø
�	Š	‰ŒˆØ
�
Š
Ð$Ñ%Ô%Ð%Ý#Ô,Ð->Ñ?Ô?Ð?r-   z/me/watch-history/{stream_id}rl   c              ƒ   ó  K  — |sd S |                      t          ¦  «                             t          j        |j        k    t          j        | k    ¦  «                             ¦   «         }|st          t          j	        d¬¦  «        ‚|j
        |_
        |j        �|j        |_        t          j        t          j        ¦  «        |_        |                     ¦   «          |                     |¦  «         t'          j        |¦  «        S ©NzWatch history not foundr:   )rq   r   rr   rk   rM   rl   rw   r   r   r•   r“   r”   r    r2   r!   r3   rc   r5   r6   r   r*   )rl   r‘   r/   r'   r…   s        r+   Úupdate_watch_historyrœ   È   së   è è € ð ð Øˆtà—H’H�\Ñ*Ô*×1Ò1ÝÔ ¤Ò/ÝÔ )Ò+ñô ÷ ‚e�g„gð ð
 ð 
ÝÝÔ1Ø,ð
ñ 
ô 
ð 	
ð
 +5Ô*J€MÔ'ØÔÐ'Ø",Ô"6ˆÔÝ$,¤Lµ´Ñ$>Ô$>€MÔ!Ø‡I‚I�K„K€KØ‡J‚Jˆ}ÑÔÐåÔ(¨Ñ7Ô7Ð7r-   rj   c              ƒ   ó`  K  — |sd S |                      t          ¦  «                             t          j        |j        k    t          j        | k    ¦  «                             ¦   «         }|st          t          j	        d¬¦  «        ‚| 
                    |¦  «         |                     ¦   «          d S r›   )rq   r   rr   rk   rM   rl   rw   r   r   r•   Údeleter5   ©rl   r/   r'   r…   s       r+   Údelete_watch_historyr    è   s¬   è è € ð ð Øˆà—H’H�\Ñ*Ô*×1Ò1ÝÔ ¤Ò/ÝÔ )Ò+ñô ÷ ‚e�g„gð ð
 ð 
ÝÝÔ1Ø,ð
ñ 
ô 
ð 	
ð
 ‡I‚IˆmÑÔÐØ‡I‚I�K„K€Kàˆ4r-   z$/me/watch-history/stream/{stream_id}c              ƒ   ó   K  — |sd S |                      t          ¦  «                             t          j        |j        k    t          j        | k    ¦  «                             ¦   «         }|sd S t          j        |¦  «        S r)   )	rq   r   rr   rk   rM   rl   rw   r   r*   rŸ   s       r+   Úget_stream_watch_historyr¢     s|   è è € ð ð Øˆtà—H’H�\Ñ*Ô*×1Ò1ÝÔ ¤Ò/ÝÔ )Ò+ñô ÷ ‚e�g„gð ð ð ØˆtåÔ(¨Ñ7Ô7Ð7r-   )@Úfastapir   r   r   r   r   r   r	   r
   r   Úsqlalchemy.ormr   Útypingr   Úslowapir   Úslowapi.utilr   Údatabaser   Úmodels.userr   Úmodels.watch_historyr   Úmodels.streamr   Úschemas.userr   r   Úschemas.watch_historyr   r   r   r   Úauthr   r   r   r   Úconfigr   rH   Úuuidr}   r   r    r!   ÚrouterÚlimiterr„   r,   Úputr7   ÚpostrY   Úintr�   r™   rd   rœ   rž   ÚHTTP_204_NO_CONTENTr    r¢   rp   r-   r+   ú<module>r·      si  ðØ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hÐ hØ "Ð "Ð "Ð "Ð "Ð "Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø +Ð +Ð +Ð +Ð +Ð +Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø /Ð /Ð /Ð /Ð /Ð /Ø "Ð "Ð "Ð "Ð "Ð "Ø :Ð :Ð :Ð :Ð :Ð :Ð :Ð :Ø xÐ xÐ xÐ xÐ xÐ xÐ xÐ xÐ xÐ xÐ xÐ xØ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qØ Ð Ð Ð Ð Ð Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'à	ˆ˜,¨g¨YÐ	7Ñ	7Ô	7€Ø
ˆ'Ð-Ð
.Ñ
.Ô
.€ð ‡‚ˆE ,€Ñ/Ô/Ø.5¨gÐ6MÑ.NÔ.Nð /ð / tð /ð /ð /ñ 0Ô/ð/ð ‡‚ˆE ,€Ñ/Ô/ð �'˜&‘/”/Ø ˜Ð!3Ð!3Ð4EÑ!FÔ!FÑGÔGð
/ð 
/Ø#ð
/àð
/ð ð
/ð 
/ð 
/ñ 0Ô/ð
/ð ‡‚Ð Ñ!Ô!à�t˜C‘y”yØ�'˜&‘/”/Ø ˜Ð!8Ñ9Ô9ð.sð .sØ
ð.sàð.sð ð.sð .sð .sñ "Ô!ð.sðb ‡‚ÐÑ Ô ð ØØ�'˜&‘/”/Ø#* 7Ð+DÑ#EÔ#Eð8ð 8Øð8à
ð8ð ð8ð 	ð	8ð
 ˜4”.ð8ð 8ð 8ñ !Ô ð8ðv ‡‚Ð Ð1EÈÑ1L€ÑMÔMð �'˜&‘/”/Ø#* 7Ð+DÑ#EÔ#Eð+@ð +@Ø"ð+@àð+@ð ˜4”.ð+@ð +@ð +@ñ NÔMð+@ð\ ‡‚Ð+Ð<PÐSWÑ<W€ÑXÔXð �'˜&‘/”/Ø#* 7Ð+DÑ#EÔ#Eð	8ð 8Øð8à"ð8ð 	ð8ð ˜4”.ð	8ð 8ð 8ñ YÔXð8ð> ‡‚Ð.¸FÔ<V€ÑWÔWð �'˜&‘/”/Ø#* 7Ð+DÑ#EÔ#Eðð Øðàðð ˜4”.ðð ð ñ XÔWðð4 ‡‚Ð2ÐCWÐZ^ÑC^€Ñ_Ô_ð �'˜&‘/”/Ø#* 7Ð+DÑ#EÔ#Eð8ð 8Øð8àð8ð ˜4”.ð8ð 8ð 8ñ `Ô_ð8ð 8ð 8r-   