o
    `pj%_                     @   s@
  d dl mZ d dlmZ d dl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mZmZ d d	lmZ d d
lmZmZmZ d dlmZm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z'm(Z(m)Z) d dl*m+Z+m,Z,m-Z- d dl.m/Z/m0Z0 d dl1m2Z2m3Z3m4Z4m5Z5m6Z6 d dl7m8Z8m9Z9m:Z:m;Z;m<Z< d dl=m>Z> d dl?m@ZA d dl?mBZC d dlDmEZF d dlDmGZH eeIJ jKd ZLedddZMG dd deZNG dd deZOG d d! d!eZPG d"d# d#eZQG d$d% d%eZRG d&d' d'eZSG d(d) d)eZTG d*d+ d+eZUG d,d- d-eZVG d.d/ d/eZWG d0d1 d1eZXG d2d3 d3eZYG d4d5 d5eZZG d6d7 d7eZ[G d8d9 d9eZ\G d:d; d;eZ]d<e^d=e]fd>d?Z_d@e`d=e`fdAdBZadCe`d@e`d=e`fdDdEZbdCe`d@e`d=e`fdFdGZcdHe8dIe`d=eNfdJdKZd	Ld dMee`dLB e f d=e`fdNdOZe	Ld dMee`dLB e f d=e`dLB fdPdQZfeMjgdReSdSdTeRfdUdVZheMjidWeSdSdCee`eeef fdXdYZjeMidZe
dLd[d\d]fdCee`eeef d^ekdLB fd_d`ZleMjidaeTdSe
dbdcddfdCee`eeef dee`fdfdgZmdCe`fdhdiZndjdk ZoeMidldCee`eeef fdmdnZpeMgdoedbfdCee`eeef dpeqe fdqdrZreMidsdCee`eeef fdtduZseMgdvdTeWdCee`eeef fdwdxZteMidydCee`eeef fdzd{ZueMgdydTeXdCee`eeef fd|d}ZveMwd~dekdCee`eeef fddZxeMide
ddde
dddd]fdee`dLB eeff dekdekfddZyeMgddTeYdCee`eeef fddZzeMgddekdCee`eeef fddZ{eMiddCee`eeef fddZ|eM}ddTeUdCee`eeef fddZ~eMgddTeVdCee`eeef fddZeMwddCee`eeef fddZeMwddekdCee`eeef fddZeMiddCee`eeef fddZeMjgde]dSdTeZdCee`eeef fddZeMjide]dSdekdCee`eeef fddZeMj}de]dSdekdTeZdCee`eeef fddZeMwddekdCee`eeef fddZeMgddekdCee`eeef fddZeMjide]dSdCe`dekdee`eeef fddZeMiddd ZeMjide\dSdCee`eeef fddZeMj}de\dSdTe[dCee`eeef fddZeMjideQdSdd ZeMjideOdSe
ddde
ede d]dLe
dLd[d\d]dfdekdekdCe`dLB d^ekdLB def
ddÄZded=dLfddƄZdCe`de`d=efddɄZeMidʡdCe`de`fdd̄ZeMid͡dCe`de`fddτZeMidСdd҄ ZeMidӡddՄ ZeMid֡dd؄ ZeMid١ddۄ ZeMidܡddބ ZeMidߡdd ZeMiddd ZeMiddd ZeMiddCee`eeef fddZeMiddekfddZded=dLfddZeMiddekde`fddZeMiddd ZeMiddd ZeMiddCe`dekfddZeMjdeeLddd dLS (      )Path)	Annotated)DependsFastAPIFileHeaderHTTPExceptionQuery
UploadFile)FileResponse)StaticFiles)	BaseModel)config)get_activityget_my_activitieslist_activities)verify_login_key)get_checkin_statusperform_checkinsave_uploaded_images)PAGE_SIZE_DEFAULTPAGE_SIZE_MAX)resolve_avatar_urlresolve_display_namebuild_profile)cancel_alarmcreate_alarmlist_alarms)
like_entrylist_entries
post_entry)get_shopredeem_shop_item)clear_equipped_titlesequip_titleget_title_settingsset_equipped_titlesunequip_title)CheckinImagefetch_checkins_paginatedfetch_user_settlement_daylist_user_idsresolve_image_path)ensure_thumbnail)character_store)user_settings)	character)rulesstaticu   BotEro 打卡图库z1.0.0)titleversionc                   @   sF   e Zd ZU eed< eed< eed< eed< eed< eed< eed< dS )	CheckinItemOutiduser_iddisplay_namecheckin_datethumbnail_url	image_urlhas_fileN)__name__
__module____qualname__int__annotations__strbool rE   rE   0/home/dore/onebot/Bot_Ero/checkin_gallery/app.pyr6   ,   s   
 r6   c                   @   s:   e Zd ZU ee ed< eed< eed< eed< eed< dS )CheckinListOutitemstotalpage	page_sizehas_moreN)r>   r?   r@   listr6   rB   rA   rD   rE   rE   rE   rF   rG   6   s   
 rG   c                   @   s   e Zd ZU eed< eed< dS )UserOptionOutr8   r9   Nr>   r?   r@   rC   rB   rE   rE   rE   rF   rN   >   s   
 rN   c                   @      e Zd ZU ee ed< dS )
UserIdsOutusersN)r>   r?   r@   rM   rN   rB   rE   rE   rE   rF   rQ   C      
 rQ   c                   @      e Zd ZU eed< dS )LoginInkeyNrO   rE   rE   rE   rF   rU   G      
 rU   c                   @   s.   e Zd ZU eed< eed< eed< eed< dS )
SessionOutr8   r9   
avatar_urltokenNrO   rE   rE   rE   rF   rX   K   s
   
 rX   c                   @   s"   e Zd ZU eed< ee ed< dS )DayCheckinsOutdaterH   N)r>   r?   r@   rC   rB   rM   r6   rE   rE   rE   rF   r[   R   s   
 r[   c                   @   rP   )EquippedTitlesIn	title_idsN)r>   r?   r@   rM   rA   rB   rE   rE   rE   rF   r]   W   rS   r]   c                   @   rT   )
EquipOneIntitle_idN)r>   r?   r@   rA   rB   rE   rE   rE   rF   r_   [   rW   r_   c                   @   rT   )ShopRedeemIn
product_idNrO   rE   rE   rE   rF   ra   _   rW   ra   c                   @   s   e Zd ZU eed< eed< dZedB ed< dZedB ed< dZeed< dZ	eed< dZ
eed	< dZeed
< dZeed< dZedB ed< dZedB ed< dZedB ed< dZedB ed< dS )AlarmCreateIncontentschedule_typeNr\   timer   yearsmonthsdayshoursminutesinterval_daysweekdaymonthday)r>   r?   r@   rC   rB   r\   rf   rg   rA   rh   ri   rj   rk   rl   rm   rn   ro   rE   rE   rE   rF   rc   c   s   
 rc   c                   @   rT   )GuestbookPostInrd   NrO   rE   rE   rE   rF   rp   s   rW   rp   c                   @   sz  e Zd ZU eed< eed< eed< dZeed< dZeed< dZeed< d	Z	eed
< eed< eed< eed< eed< eed< eed< g Z
ee ed< g Zee ed< d	Zeed< d	Zeed< d	Zeed< d	Zeed< dZeed< d	Zeed< d	Zeed< dZeed< g Zee ed< dZeed< g Zee ed< dZeed < dZeed!< dZeed"< dZeed#< dZeed$< dZeed%< d&S )'CharacterIn	char_namerace
class_name   level 
background	alignmentr   xp	str_score	dex_score	con_score	int_score	wis_score	cha_scoreproficient_skillssaving_profshpac
current_hptemp_hp   speeddeath_saves_successdeath_saves_failFinspiration	equipmentother_proficienciesattacksfeaturespersonality_traitsidealsbondsflawsnotesN)r>   r?   r@   rC   rB   rv   rA   rx   ry   rz   r   rM   r   r   r   r   r   r   r   r   r   rD   r   r   r   r   r   r   r   r   r   rE   rE   rE   rF   rq   w   sB   
 rq   c                   @   s   e Zd ZU dZedB ed< dS )
SettingsInNprivacy)r>   r?   r@   r   dictrB   rE   rE   rE   rF   r      s   
 r   c                   @   rT   )SettingsOutr   N)r>   r?   r@   r   rB   rE   rE   rE   rF   r      rW   r   c                   @   sn  e Zd ZU eed< eed< eed< eed< eed< eed< eed< eed< eed	< eed
< eed< eed< eed< eed< eed< eed< ee ed< eed< eed< eed< eed< eed< eed< eed< eed< eed< eed< ee ed< eed< eed< eed< eed < eed!< eed"< ee ed#< eed$< ee ed%< eed&< eed'< eed(< eed)< eed*< d+S ),CharOutr7   r8   r9   rr   rs   rt   rv   r   r   
skill_modsscores
prof_bonus	save_modspassive_perception
initiativehit_dicer   r   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   N)	r>   r?   r@   rA   rB   rC   r   rM   rD   rE   rE   rE   rF   r      sV   
 r   datareturnc              	      s   fdddD }t  }td6i d d d d dt d d|d d|dd	d
|d
d	dt|ddd|d d|d d|di d|di d|ddd|di d|ddd|ddd|ddd|dg d|dd	d dd	d dd	dt ddd|d d |d  d!|d! d"|d" d#|d# d$|d$ d% d%g pg d&t d&dd't d'dd(t d(d)d*t d*dd+t d+dd,t d,d-d. d.g pg d/ d/d	d0 d0g p;g d1 d1d	d2 d2d	d3 d3d	d4 d4d	d5 d5d	S d1 d1d	d2 d2d	d3 d3d	d4 d4d	d5 d5d	S )7Nc                    s   i | ]	}|  |d qS )   )get).0kr   rE   rF   
<dictcomp>   s    z _char_to_out.<locals>.<dictcomp>)r{   r|   r}   r~   r   r   r7   r8   r9   rr   rs   rw   rt   rv   ru   r   r   r   r   r      r   r   
   r   r   r   1d8r   r   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   Fr   r   r   r   r   r   r   r   rE   )	trpg_charfinalizer   r   r   rA   rD   )r   base_scores	finalizedrE   r   rF   _char_to_out   s   
	
 !"#$%&'()*%&'()*r   rd   c                 C   s   |  dd dd ddS )N{rw   }-)replace)rd   rE   rE   rF   
_file_slug  s   r   r8   c                 C      d|  dt | S )N/media//r   r8   rd   rE   rE   rF   
_media_url     r   c                 C   r   )Nz/thumb/r   r   r   rE   rE   rF   
_thumb_url
  r   r   itemr9   c              	   C   s6   t | j| j|| jt| j| jt| j| j| jd udS )Nr7   r8   r9   r:   r;   r<   r=   )r6   r7   r8   r:   r   rd   r   
image_path)r   r9   rE   rE   rF   _checkin_to_out  s   r   Nauthorizationc                 C   sF   | r|  dstdddt| dd   }|d u r!tddd|S )NBearer   u	   未登录status_codedetail      密钥无效)
startswithr   r   strip)r   uidrE   rE   rF   get_current_user_id  s   r   c                 C   s&   | r|  ds	d S t| dd   S )Nr   r   )r   r   r   )r   rE   rE   rF   get_optional_user_id%  s   r   z/api/auth/login)response_modelbodyc                 C   sD   t | j }|d u rtddd| j }t|t|t||dS )Nr   r   r   r8   r9   rY   rZ   )r   rV   r   r   rX   r   r   )r   r   rZ   rE   rE   rF   	api_login-  s   
r   z/api/auth/mec                 C   s   t | t| t| ddS )Nrw   r   )rX   r   r   r8   rE   rE   rF   api_me;  s   r   z/api/me/profilei  i4  )geleyearc                 C   s
   t | |S Nr   )r8   r   rE   rE   rF   api_my_profileE  s   
r   z/api/me/day.z^\d{4}-\d{2}-\d{2}$)patternr\   c                    s,   t | |}t|  t| fdd|D dS )Nc                    s   g | ]}t | qS rE   )r   )r   itnamerE   rF   
<listcomp>V  s    zapi_my_day.<locals>.<listcomp>)r\   rH   )r+   r   r[   )r8   r\   rH   rE   r   rF   
api_my_dayM  s   
r   c              
   G   s>   z	| |g|R  W S  t y } z	tdt|d|d }~ww N  r   
ValueErrorr   rC   )fnr8   argsexcrE   rE   rF   _title_settings_or_400Z  s   r   c              
   G   s6   z| | W S  t y } z	tdt|d|d }~ww r   r   )r   r   r   rE   rE   rF   _checkin_or_400a  s   
r   z/api/me/checkin/statusc                 C      t | S r   )r   r   rE   rE   rF   api_checkin_statush     r   z/api/me/checkinfilesc                    sD   g }|D ]}|  I d H }|||jf qtt| |}t| |S r   )readappendcontent_typer   r   r   )r8   r   payloadsfr   namesrE   rE   rF   api_checkin_submitm  s   
r   z/api/me/shopc                 C   r   r   )r"   r   rE   rE   rF   api_shopz  r   r   z/api/me/shop/redeemc                 C      t t|| jS r   )r   r#   rb   r   r8   rE   rE   rF   api_shop_redeem     r   z/api/me/alarmsc                 C   r   r   )r   r   rE   rE   rF   api_alarms_list  r   r   c                 C   s   t t||  S r   )r   r   
model_dumpr   rE   rE   rF   api_alarms_create  s   r   z/api/me/alarms/{alarm_id}alarm_idc                 C      t t|| S r   )r   r   )r   r8   rE   rE   rF   api_alarms_cancel     r   z/api/guestbookru   )r   r   d   	viewer_idrJ   rK   c                 C   s   t | ||S r   )r    )r  rJ   rK   rE   rE   rF   api_guestbook_list  s   r  c                 C   r   r   )r   r!   rd   r   rE   rE   rF   api_guestbook_post  r   r  z/api/guestbook/{entry_id}/likeentry_idc                 C   r   r   )r   r   )r  r8   rE   rE   rF   api_guestbook_like  r   r  z/api/me/titles/settingsc                 C   r   r   )r&   r   rE   rE   rF   api_title_settings  r   r  z/api/me/titles/equippedc                 C   r   r   )r   r'   r^   r   rE   rE   rF   api_set_equipped  r   r  z/api/me/titles/equipc                 C   r   r   )r   r%   r`   r   rE   rE   rF   api_equip_one  r   r  c                 C   r   r   )r$   r   rE   rE   rF   api_clear_equipped  r   r	  z/api/me/titles/equip/{title_id}r`   c                 C   r   r   )r   r(   )r`   r8   rE   rE   rF   api_unequip_one  r   r
  z/api/me/charactersc                 C   s8   t | }t | }|r|d nd }|dd |D dS )Nr7   c                 S   s   g | ]}t |qS rE   )r   )r   crE   rE   rF   r     s    z%api_my_characters.<locals>.<listcomp>)
current_id
characters)
char_store
list_charsget_current)r8   charscurrentr  rE   rE   rF   api_my_characters  s   

r  c              
   C   s   |   }t|dddkr-t|dddkr-tjtt|d d ttjd  |d< t|}|d |d< |d |d< zt	
||}W n ty[ } z	tdt|d|d }~ww tt	||S )	Nrz   r   rv   ru   r   r   r   r   )r   rA   r   
trpg_rulesXP_THRESHOLDSminlenr   r   r  create_charr   r   rC   r   get_char)r   r8   r   r   char_idr   rE   rE   rF   api_create_character  s   (*
r  z/api/me/characters/{char_id}r  c                 C   s$   t || }|stdddt|S )N     角色不存在r   )r  r  r   r   )r  r8   charrE   rE   rF   api_get_my_character  s   r  c              
   C   s   t || stddd| }t|dddkr9t|dddkr9tjtt|d d t	tjd  |d< t
|}|d |d< |d	 |d	< z	t || | W n tyh } z	td
t|d|d }~ww tt || S )Nr  r  r   rz   r   rv   ru   r   r   r   )r  r  r   r   rA   r   r  r  r  r  r   r   update_charr   rC   r   )r  r   r8   r   r   r   rE   rE   rF   api_update_character  s   (*
r!  c                 C   s,   t || stdddt ||  ddiS )Nr  r  r   okT)r  r  r   delete_char)r  r8   rE   rE   rF   api_delete_character  s   r$  z%/api/me/characters/{char_id}/activatec              
   C   sB   zt ||  W ddiS  ty  } z	tdt|d|d }~ww )Nr  r   r"  T)r  set_currentr   r   rC   )r  r8   r   rE   rE   rF   api_activate_character  s   r&  z#/api/characters/{user_id}/{char_id}c              
   C   s   t |  stdddt |t | krt| stdddzt| |}W n ty< } z	tdt |d|d }~ww |sEtdddt|S )Nr   u   非法用户 IDr     u   对方未公开角色卡r  r  )	rC   isdigitr   user_settings_modprivacy_publicr  r  r   r   )r8   r  r  r  r   rE   rE   rF   api_view_character+  s   r+  z/api/trpg/rulesc                   C   s>   t jt jt jt jt jt jt jt jt j	t j
g dg dddS )N)u   守序   中立u   混乱)u   善良r,  u   邪恶)lawmoral)
attributesattribute_enskillsskill_aliasesracesclassespoint_buy_costpoint_buy_budgetstandard_arrayxp_thresholds
alignments)r  
ATTRIBUTESATTRIBUTE_ENSKILLSSKILL_ALIASESRACESCLASSESPOINT_BUY_COSTPOINT_BUY_BUDGETSTANDARD_ARRAYr  rE   rE   rE   rF   api_trpg_rules>  s   rC  z/api/me/settingsc                 C   s   t | }t|di dS )Nr   r   )r)  get_settingsr   r   )r8   settingsrE   rE   rF   api_my_settingsR  s   
rG  c                 C   s*   | j dd}t||}t|di dS )NT)exclude_noner   rD  )r   r)  update_settingsr   r   )r   r8   patchmergedrE   rE   rF   api_update_settingsX  s   rL  z
/api/usersc                  C   s   dd t  D } t| dS )Nc                 S   s   g | ]
}t |t|d qS ))r8   r9   )rN   r   )r   r   rE   rE   rF   r   d  s    zapi_users.<locals>.<listcomp>rR   )r,   rQ   rM  rE   rE   rF   	api_usersb  s   
rN  z/api/checkinsTonly_with_filec                 C   s   t ||| ||d\}}}i }g }	|D ]0}
|
j|vr!t|
j||
j< |	t|
j|
j||
j |
jt|
j|
jt	|
j|
j|
j
d ud qt|	|| ||dS )N)r8   r   rJ   rK   rO  r   )rH   rI   rJ   rK   rL   )r*   r8   r   r   r6   r7   r:   r   rd   r   r   rG   )rJ   rK   r8   r   rO  rH   rI   rL   
name_cacheoutr   rE   rE   rF   api_checkinsk  s<   
rR  pathc              
   C   B   z|   tj   W d S  ty  } ztddd|d }~ww Nr'  u   禁止访问r   )resolverelative_tor   
IMAGE_ROOTr   r   rS  r   rE   rE   rF   _assert_under_root     rZ  filenamec                 C   sV   d| v sd|v sd|v sd|v rt dddt| |}|d u r%t dddt| |S )	N..r   \r      非法路径r   r     图片不存在)r   r-   rZ  r8   r\  rS  rE   rE   rF   _resolve_and_guard  s    
rb  z/thumb/{user_id}/{filename}c              
   C   sJ   t | |}zt|}W n ty } ztddd|d }~ww t|ddS )N  u   缩略图生成失败r   z
image/jpeg)
media_type)rb  r.   OSErrorr   r   )r8   r\  sourcethumbr   rE   rE   rF   serve_thumb  s   
rh  z/media/{user_id}/{filename}c                 C   s   t | |}t|S r   )rb  r   ra  rE   rE   rF   serve_media  s   
ri  r   c                  C   $   t d } |  stdddt| S )Nz
index.htmlrc  u   缺少静态页面r   
STATIC_DIRis_filer   r   )
index_filerE   rE   rF   index     ro  z/profilec                  C   rj  )Nzprofile.htmlrc  u   缺少个人主页r   rk  rJ   rE   rE   rF   profile_page  rp  rr  z/profile/settingsc                  C   rj  )Nzsettings.htmlrc  u   缺少设置页r   rk  rq  rE   rE   rF   profile_settings_page  rp  rs  z/profile/checkinc                  C   rj  )Nzcheckin.htmlrc  u   缺少打卡页r   rk  rq  rE   rE   rF   profile_checkin_page  rp  rt  z/profile/shopc                  C   rj  )Nz	shop.htmlrc  u   缺少商店页r   rk  rq  rE   rE   rF   profile_shop_page  rp  ru  z/profile/alarmsc                  C   rj  )Nzalarms.htmlrc  u   缺少闹钟页r   rk  rq  rE   rE   rF   profile_alarms_page  rp  rv  z
/guestbookc                  C   rj  )Nzguestbook.htmlrc  u   缺少留言簿页r   rk  rq  rE   rE   rF   guestbook_page  rp  rw  z/api/activitiesc                   C   s
   dt  iS NrH   )r   rE   rE   rE   rF   api_activities  s   
ry  z/api/me/activitiesc                 C   s   dt | iS rx  )r   r   rE   rE   rF   api_my_activities  s   rz  z/api/activities/{activity_id}activity_idc                    sH   t  }|stddd|d D ]} fdd|dg D |d< q|S )Nr  u   活动不存在r   membersc                    s   g | ]
}d   d| qS )z	/archive/r   rE   )r   r   r{  rE   rF   r     s    z'api_activity_detail.<locals>.<listcomp>images)r   r   r   )r{  actmrE   r}  rF   api_activity_detail  s   

r  c              
   C   rT  rU  )rV  rW  r   ACTIVITY_ROOTr   r   rY  rE   rE   rF   _assert_under_activity_root  r[  r  z'/archive/{activity_id}/media/{filename}c                 C   s^   d|v sd|v sd|v rt dddtjt|  d | }| s't dd	dt| t|S )
Nr   r^  r]  r   r_  r   imgsr  r`  )r   r   r  rC   rm  r  r   )r{  r\  rS  rE   rE   rF   serve_activity_media	  s   r  z/archivec                  C   rj  )Nzactivities.htmlrc  u   缺少活动归档页r   rk  rq  rE   rE   rF   archive_page  rp  r  z/profile/trpgc                  C   rj  )Nz	trpg.htmlrc  u   缺少跑团车卡页r   rk  rq  rE   rE   rF   profile_trpg_page  rp  r  z/trpg/char/{user_id}/{char_id}c                 C   s$   t d }| stdddt|S )Nzchar_view.htmlrc  u   缺少角色卡查看页r   rk  )r8   r  rJ   rE   rE   rF   trpg_char_view_page$  rp  r  z/static)	directoryr   r   )pathlibr   typingr   fastapir   r   r   r   r   r	   r
   fastapi.responsesr   fastapi.staticfilesr   pydanticr   checkin_galleryr    checkin_gallery.activity_servicer   r   r   checkin_gallery.authr   checkin_gallery.checkin_servicer   r   r   checkin_gallery.configr   r   checkin_gallery.onebot_clientr   r   checkin_gallery.profile_servicer   checkin_gallery.alarm_servicer   r   r   !checkin_gallery.guestbook_servicer   r    r!   checkin_gallery.shop_servicer"   r#   checkin_gallery.title_settingsr$   r%   r&   r'   r(   checkin_gallery.repositoryr)   r*   r+   r,   r-   checkin_gallery.thumbnailsr.   corer/   r  r0   r)  	core.trpgr1   r   r2   r  __file__rV  parentrl  appr6   rG   rN   rQ   rU   rX   r[   r]   r_   ra   rc   rp   rq   r   r   r   r   r   rC   r   r   r   r   r   r   postr   r   r   rA   r   r   r   r   r   rM   r   r   r   r   r   deleter   r  r  r  r  putr  r  r	  r
  r  r  r  r!  r$  r&  r+  rC  rG  rL  rN  rD   rR  rZ  rb  rh  ri  ro  rr  rs  rt  ru  rv  rw  ry  rz  r  r  r  r  r  r  mountrE   rE   rE   rF   <module>   s   $
#-3

	





	

'
	










