
    soj              
       p   d dl Z d dlmZ d dlmZ d dlT d dlmZ d dlm	Z	 d dl
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mZ d dlmZ d dl m!Z!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,  G d de          Z-e-.                                 	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e56                    dd e7d                                n# e8$ r Y nw xY w	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e56                    dd e9d                               n# e8$ r Y nw xY w	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e5:                    dd                     n# e8$ r Y nw xY w	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e5;                    ddd                     n# e8$ r Y nw xY w	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e5;                    dd d                     n# e8$ r Y nw xY w	 d dl/m0Z0m1Z2 d dlm3Z3  e0 e3j4                              Z5 e2e56                    dd! e<d"e"j=        #                               dS # e8$ r Y dS w xY w)$    N)Any)ZoneInfo)*)Update)ContextTypes)phrases)	BaseModel)Crew)ContextDataKeyContextDataType)get_last_new_worldget_first_new_worldget_by_levelLocationis_paradise_by_level)Screen)LanguageLANGUAGE_DEFAULT)CrewRole)IncomeTaxBracket)get_user_context_dataset_user_context_dataremove_context_data)get_cumulative_percentage_sumc                   ^   e Zd ZU dZ edd          Zeez  ed<    ed          Zeez  ed<    ed          Z	eez  ed<    ed          Z
eez  ed	<    ed
          Zeez  ed<    ed
 ed          g          Zeez  ed<    ed
 ed          g          Zeez  ed<    ed
          Zeez  ed<    ed          Zej        ez  ed<    ed          Zej        ez  ed<    ed
          Zeez  ed<    ed          Zej        ez  ed<    ed          Zej        ez  ed<    ed
          Zeez  ed<    ed
          Zeez  ed<    ed          Zeez  ed<    ed          Zeez  ed<    ed          Z ej        ez  ed<    ed          Z!ej        ez  ed<    ed          Z"ej        ez  ed<    ed          Z#ej        ez  ed <    ed          Z$ej        ez  ed!<    ed"          Z%eez  ed#<    e&e'd$d%          Z(e'e&z  ed&<    ed          Z)ej        ez  ed'<    ed          Z*eez  ed(<    ed          Z+ej        ez  ed)<    ed          Z,ej        ez  ed*<    ed          Z-eez  ed+<    ed          Z.eez  ed,<    e/d          Z0ee/z  ed-<    eej        j1                  Z2ej        ez  ed.<    ed          Z3ej        ez  ed/<    ed          Z4eez  d0z  ed1<    ed          Z5eez  d0z  ed2<    e/d          Z6ee/z  d0z  ed3<    e/d
          Z7ee/z  ed4<    ed"          Z8eez  ed5<    ed          Z9ej        ez  ed6<    edd7          Z:eez  ed8<    ed          Z;eez  ed9<    ed          Z<ej        ez  ed:<    ed          Z=ej        ez  ed;<    ed"          Z>eez  ed<<    ed          Z?eez  ed=<    e/d
          Z@ee/z  ed><    e/d
          ZAee/z  ed?<    ed@eBjC        A          ZDeez  edB<   d0ZEeedC<   d"ZFeedD<   d0ZGed0z  edE<   d"ZHeedF<   dZIeedG<   d0ZJd0ZKd0ZLd0ZM G dH dI          ZNdJefdKZOdL ZPdM ZQdN ZReSdJeTfdO            ZUdP ZVdJefdQZW	 ddReXdSeYeX         fdTZZddUZ[dJeYeX         fdVZ\dJeXfdWZ]dX Z^dY Z_dReXfdZZ`dReXfd[Zad\ Zbd] Zcd^ ZdeSdedJd fd_            Zed` Zfdad dJefdbZgdJefdcZhdd Zide ZjdJefdfZkdg ZldJefdhZmdJefdiZndJefdjZodJefdkZpdJefdlZqdJerfdmZsdJefdnZtdJefdoZueSdJeTfdp            Zvdqd dJeTfdrZw	 ddsexdteyjz        duedJefdvZ{dteyjz        duefdwZ|dteyjz        fdxZ}eS	 	 ddteyjz        dye~dzed{edJef
d|            ZeS	 ddteyjz        dye~d{edJefd}            ZeS	 ddteyjz        dye~d~eTd{edJeTf
d            ZeS	 ddteyjz        dye~d{efd            ZeSdteyjz        fd            ZdJeYfdZdJefdZdJefdZdJefdZd ZddedJd0fdZdJefdZeSdJeYfd            ZdJefdZdJefdZdJej        fdZdej        dJefdZdej        dJefdZd Zd ZdJefdZdJefdZdJefdZdJefdZdJefdZeSd             Zd0S )Userz
    User class
    c   T)
max_lengthunique
tg_user_id)r   tg_first_nametg_last_nametg_usernamer   defaultbountyztotal_gained_bounty >= 0)r%   constraintstotal_gained_bountyz#total_gained_bounty_unmodified >= 0total_gained_bounty_unmodifiedpending_bountynulldoc_q_cooldown_end_dategame_cooldown_end_dategame_challenge_countgame_cooldown_start_time$game_accept_global_cooldown_end_datebounty_poster_limitlocation_levelshould_propose_new_worldcan_change_regionfight_immunity_end_datefight_cooldown_end_dateplunder_immunity_end_dateplunder_cooldown_end_dateimpel_down_release_dateFimpel_down_is_permanentcrew_members)backrefr,   crewcrew_join_date	crew_rolecrew_promotion_dateconscription_end_datecan_create_crewcan_join_crewcrew_davy_back_fight_prioritylast_message_datelast_system_interaction_dateNprivate_screen_listprivate_screen_stepprivate_screen_in_edit_idbounty_gift_taxis_admin(devil_fruit_collection_cooldown_end_date)r   r,   timezone	is_active%prediction_creation_cooldown_end_date$bounty_loan_issue_cool_down_end_date.is_exempt_from_global_leaderboard_requirementscan_collect_daily_rewardfight_scout_countplunder_scout_count   r   r%   languageprivate_screen_previous_stepprivate_screen_stayprivate_screen_stay_stepprivate_screen_force_go_backshould_update_modelc                       e Zd ZdZdS )	User.MetauserN)__name__
__module____qualname__db_table     /app/src/model/User.pyMetar_   ~   s        rf   rh   returnc                 .    ddl m}  || j                  S )zo
        Returns a formatted string of the bounty
        :return: The formatted string e.g. 1,000,000
        r   )get_belly_formatted)src.utils.string_utilsrk   r&   )selfrk   s     rg   get_bounty_formattedzUser.get_bounty_formatted   s)     	?>>>>>""4;///rf   c                 p    | j         duo&| j         t          j                                        k    p| j        S )zd
        Returns True if the user is arrested
        :return: True if the user is arrested
        N)r:   datetimenowr;   rm   s    rg   is_arrestedzUser.is_arrested   sA     (4 G,x/@/D/D/F/FF* )	*rf   c                 :    |                                  o| j         S )z|
        Returns True if the user is temporarily arrested
        :return: True if the user is temporarily arrested
        rs   r;   rr   s    rg   is_arrested_temporaryzUser.is_arrested_temporary   s!     !!F$*F&FFrf   c                 8    |                                  o| j        S )z|
        Returns True if the user is permanently arrested
        :return: True if the user is permanently arrested
        ru   rr   s    rg   is_arrested_permanentzUser.is_arrested_permanent   s     !!Bd&BBrf   c                      t           j        dk    t           j                                        t           j        t          j                                        k     z  z  S )z
        Returns a case statement condition which returns true if the user is not arrested
        :return: The case statement
        F)r   r;   r:   is_nullrp   rq   re   rf   rg   'get_is_not_arrested_statement_conditionz,User.get_is_not_arrested_statement_condition   sK     ,5)1133+h.?.C.C.E.EEG
 	
rf   c                 8    ddl m} |                    |           S )z`
        Returns the current impel down log
        :return: The current impel down log
        r   )ImpelDownLog)src.model.ImpelDownLogr}   get_current_for_user)rm   r}   s     rg   get_current_impel_down_logzUser.get_current_impel_down_log   s*     	87777700666rf   c                 Z    |                                  }|dS |                                S )zO
        Get the bail for the user
        :return: The impel_down_log
        Nr   )r   get_bail)rm   current_impel_down_logs     rg   get_current_bailzUser.get_current_bail   s3    
 "&!@!@!B!B!)1%..000rf   screenprevious_screen_listc                 T   |t          |          dk    rd}|+d| _        t          j                            |          | _        | j        |t          j        u r|| _        n|                                 }t          |          dk    r	|| _        dS t          |          dk    r|d         |u r|	                                 n|d         |ur|
                    |           t          j                            |          | _        t          | j                  dk    r	d| _        dS dS )z
        Updates the private screen list
        :param screen: The screen
        :param previous_screen_list: The previous screen list
        Nr      )lenrI   cSTANDARD_SPLIT_CHARjoinrH   r   	PVT_STARTget_private_screen_listpopappend)rm   r   r   rH   s       rg   update_private_screen_listzUser.update_private_screen_list   sD     +4H0I0IQ0N0N#' +'+D$'('<'A'ABV'W'WD$#+v9I/I/I'-D$$"&">">"@"@&''1,,+1( &''!++0CB0G60Q0Q#''))))$R(66#**6222'('<'A'ABU'V'VD$t'((A--'+D$$$ .-rf   c                 f    ddl m} | j        dS | j        dS ||                                 }||v S )a  
        Returns True if the user is in edit mode, i.e. is expected to send a text input
        as part of a multi-step flow (e.g. crew creation, prediction creation) or is editing
        an existing item.
        :param current_screen: The screen currently resolved for this request. Required to
        correctly detect edit mode based on private_screen_step, since that field is only
        meaningful while the user is actually on one of the screens that use it
        (see Screen.SCREENS_WITH_STEP). Without it, a stale/default private_screen_step value
        left on the user row would incorrectly be treated as "in edit mode" forever.
        :return: True if the user is in edit mode
        r   )SCREENS_WITH_STEPNTF)src.model.enums.Screenr   rJ   rI   get_current_private_screen)rm   current_screenr   s      rg   in_edit_modezUser.in_edit_mode   sU     	=<<<<<)54#+5!!<<>>N!222rf   c                 p    | j         sg S d | j                             t          j                  D             S )zZ
        Returns the private screen list
        :return: The private screen list
        c                 n    g | ]2}|                                 t          t          |                    3S re   )stripr   str).0r   s     rg   
<listcomp>z0User.get_private_screen_list.<locals>.<listcomp>  sD     
 
 
||~~
3v;;
 
 
rf   )rH   splitr   r   rr   s    rg   r   zUser.get_private_screen_list  sI     ' 	I
 
2889NOO
 
 
 	
rf   c                 <    |                                  pdgd         S )z^
        Returns the current saved private screen
        :return: The private screen
        Nr   )r   rr   s    rg   r   zUser.get_current_private_screen  s"     ,,..84&"==rf   c                 >    d| _         d| _        d| _        d| _        dS )z+
        Resets the private screen
        NF)rI   rJ   rZ   r[   rr   s    rg   reset_private_screenzUser.reset_private_screen  s*    
 $( )-&#( (,%%%rf   c                     |                                  }t          |          dk    r:|                                 t          j                            |          | _        dS dS )z1
        Removes the last private screen
        r   N)r   r   r   r   r   r   rH   )rm   rH   s     rg   remove_last_private_screenzUser.remove_last_private_screen(  sd    
 #::<<"##a''##%%%'('<'A'ABU'V'VD$$$ ('rf   c                     |                                  }|                    |           t          j                            |          | _        dS )zI
        Adds a private screen
        :param screen: The screen
        N)r   r   r   r   r   rH   )rm   r   rH   s      rg   add_private_screenzUser.add_private_screen2  sJ     #::<<""6***#$#8#=#=>Q#R#R   rf   c                 X    |                                   |                     |           dS )zT
        Replaces the last private screen
        :param screen: The screen
        N)r   r   )rm   r   s     rg   replace_last_private_screenz User.replace_last_private_screen<  s0     	'')))'''''rf   c                 |    |                                  r'| j         t          | j                  t          j        u S dS )z~
        Returns True if the user is the captain of a Crew
        :return: True if the user is the captain of a Crew
        NF)is_crew_memberr@   r   CAPTAINrr   s    rg   is_crew_captainzUser.is_crew_captainE  s=        	@T^%?DN++x/???urf   c                 |    |                                  r'| j         t          | j                  t          j        u S dS )z
        Returns True if the user is the first mate of a Crew
        :return: True if the user is the first mate of a Crew
        NF)r   r@   r   
FIRST_MATErr   s    rg   is_crew_first_matezUser.is_crew_first_mateP  s=        	CT^%?DN++x/BBBurf   c                 R    |                                  p|                                 S )z
        Returns True if the user is the captain or first mate of a Crew
        :return: True if the user is the captain or first mate of a Crew
        )r   r   rr   s    rg   is_crew_captain_or_first_matez"User.is_crew_captain_or_first_mate[  s'     ##%%B)@)@)B)BBrf   c                 R    t                               t           j        | k              S )z
        Returns the User by the Telegram user id
        :param tg_user_id: The Telegram user id
        :return: The User
        )r   get_or_noner    r    s    rg   get_by_tg_idzUser.get_by_tg_idc  s     : =>>>rf   c                     | j         duS )zf
        Returns True if the user is in a crew
        :return: True if the user is in a crew
        Nr>   rr   s    rg   r   zUser.is_crew_memberm  s     y$$rf   r`   c                 <    | j         duo|duo| j         |j         k    S )z
        Returns True if the user is in the same crew as the given user
        :param user: The user
        :return: True if the user is in the same crew as the given user
        Nr   )rm   r`   s     rg   in_same_crewzUser.in_same_crewu  s)     y$TT)9Tdi49>TTrf   c                 :    ddl m}  || j        | j                  S zl
        Returns the markdown mention of the user
        :return: The markdown mention of the user
        r   )mention_markdown_v2)src.service.message_servicer   r    r!   rm   r   s     rg   get_markdown_mentionzUser.get_markdown_mention~  s/     	DCCCCC""4?D4FGGGrf   c                 D    ddl m}  || j        t          j                  S r   )r   r   r    r   TEXT_YOUr   s     rg   get_you_markdown_mentionzUser.get_you_markdown_mention  s/     	DCCCCC""4?G4DEEErf   c                 .    ddl m}  || j                  S )zf
        Returns the markdown name of the user
        :return: The markdown name of the user
        r   )escape_valid_markdown_chars)r   r   r!   )rm   r   s     rg   get_markdown_namezUser.get_markdown_name  s+     	LKKKKK**4+=>>>rf   c                     |                                  r,t          | j        | j                                                  S | j        S )z
        Returns the max bounty between the user and the crew average
        :return: The max bounty between the user and the crew average
        )r   maxr&   r>   get_average_bountyrr   s    rg   get_max_bountyzUser.get_max_bounty  sA        	Dt{DI$@$@$B$BCCC{rf   c                 .    ddl m}  || j                  S )zt
        Returns True if the user is in the New World
        :return: True if the user is in the New World
        r   )is_new_world_by_level)src.model.enums.Locationr   r3   )rm   r   s     rg   in_new_worldzUser.in_new_world  s+     	CBBBBB$$T%8999rf   c                 r    |                                  r"| j        | j                                        k    S dS )z
        Returns True if the user has a higher bounty than the crew average
        :return: True if the user has a higher bounty than the crew average
        F)r   r&   r>   r   rr   s    rg   #has_higher_bounty_than_crew_averagez(User.has_higher_bounty_than_crew_average  s9        	@;!=!=!?!???urf   c                 T    |                                  o|                                  S )z|
        Returns True if the user has the New World bonus
        :return: True if the user has the New World bonus
        )r   has_bounty_gain_limitationsrr   s    rg   has_new_world_bonuszUser.has_new_world_bonus  s*       ""M4+K+K+M+M'MMrf   c                 T    |                                  o|                                  S )zr
        Returns True if the user has the Crew bonus
        :return: True if the user has the Crew bonus
        )r   r   rr   s    rg   has_crew_bonuszUser.has_crew_bonus  s*     ""$$OT-M-M-O-O)OOrf   c                 T    |                                  o|                                  S )zz
        Returns True if the user has the Crew MVP bonus
        :return: True if the user has the Crew MVP bonus
        )r   r   rr   s    rg   has_crew_mvp_bonuszUser.has_crew_mvp_bonus  s,     4466at?_?_?a?a;a	
rf   c                 *    t          | j                  S )zj
        Returns True if the user is in Paradise
        :return: True if the user is in Paradise
        )r   r3   rr   s    rg   is_in_paradisezUser.is_in_paradise  s     $D$7888rf   c                 *    t          | j                  S )z\
        Returns the location of the user
        :return: The location of the user
        )r   r3   rr   s    rg   get_locationzUser.get_location  s     D/000rf   c                 4    |                                  j        S )zf
        Returns the location name of the user
        :return: The location name of the user
        )r   namerr   s    rg   get_location_namezUser.get_location_name  s       ""''rf   c                     |                                  o#| j        | j        z   t                      j        k    p#| j        | j        z   t                      j        k    S )a4  
        Returns True if the user has bounty gain limitations
        This occurs when the user is in Paradise but has enough bounty to be in the New World, or
        their bounty is higher than that required to reach the final location
        :return: True if the user has bounty gain limitations
        )r   r&   r*   r   required_bountyr   rr   s    rg   r   z User.has_bounty_gain_limitations  s_     !! ]t227J7L7L7\\[ {T005G5I5I5YY	[rf   c                      t           j        t                      j        k     t           j        t           j        z   t                      j        k    z  t           j        t           j        z   t                      j        k    z  S )z
        Returns the has bounty gain limitations statement condition
        :return: The has bounty gain limitations statement condition
        )r   r3   r   levelr&   r*   r   r   re   rf   rg   3get_has_bounty_gain_limitations_statement_conditionz8User.get_has_bounty_gain_limitations_statement_condition  sc      #6#8#8#>>d116I6K6K6[[]kD//4F4H4H4XXZ 	Zrf   
other_userc                    t                               t                              t           j                                                |j                            d          |j        | j        k    z  |t           j        k    z            dk    S )z
        Returns the in same crew statement condition
        :param other_user: The other user
        :return: The in same crew statement condition
        Fr   )r   selectfnCOUNTidwherer>   rz   )rm   r   s     rg   $get_in_same_crew_statement_conditionz)User.get_in_same_crew_statement_condition  ss     KK))**00((//?di/1(* 
 	
rf   updatecontextchat_idc                 <   K   ddl m}  || |||           d{V S )z
        Returns True if the user is an admin of the chat
        :param update: The update
        :param context: The context
        :param chat_id: The chat id
        :return: True if the user is an admin of the chat
        r   )user_is_chat_admin)r   r   tg_group_idN)src.service.user_servicer   )rm   r   r   r   r   s        rg   is_chat_adminzUser.is_chat_admin  sH       	@?????''VWZabbbbbbbbbbrf   c                 :   K   ddl m}  || ||           d{V S )z
        Returns True if the user is in the chat
        :param context: The context
        :param chat_id: The chat id
        :return: True if the user is in the chat
        r   )user_is_chat_member)r   r   N)r   r   )rm   r   r   r   s       rg   is_chat_memberzUser.is_chat_member%  sE       	A@@@@@((wGTTTTTTTTTTrf   c                    K   t           j                                        }|D ]!}|                     ||           d{V r dS "dS )z
        Returns True if the user is in authorized groups
        :param context: The context
        :return: True if the user is in authorized groups
        NTF)EnvAUTHORIZED_GROUPSget_listr   )rm   r   	group_idsgroup_ids       rg   in_authorized_groupszUser.in_authorized_groups1  sh       )2244	! 	 	H(((;;;;;;;; tt urf   keytolerate_key_exception	inner_keyc                 (    t          | |||          S )a%  
        Get user data from context
        :param context: The context
        :param key: The key
        :param tolerate_key_exception: If the key is not found, raise CommonChatException instead
        of KeyError
        :param inner_key: The inner key
        :return: The value
        r   r   )r   )r   r   r   r   s       rg   get_context_datazUser.get_context_data?  s&    " %S1GS\
 
 
 	
rf   c                 L    	 t          | |d|          S # t          $ r Y dS w xY w)z
        Get user data from context or None
        :param context: The context
        :param key: The key
        :param inner_key: The inner key
        :return: The value
        Fr  N)r   KeyErrorr   r   r   s      rg   get_context_data_or_nonezUser.get_context_data_or_noneT  sK    	(Ui     	 	 	44	s    
##valuec                 (    t          | |||          S )z
        Set user data to context
        :param context: The context
        :param key: The key
        :param value: The value
        :param inner_key: The inner key
        r   )r   )r   r   r  r   s       rg   set_context_datazUser.set_context_dataf  s     %Wc5INNNNrf   c                 d    	 t          | t          j        ||           dS # t          $ r Y dS w xY w)z
        Remove user data from context
        :param context: The context
        :param key: The key
        :param inner_key: The inner key
        r
  N)r   r   USERr  r  s      rg   r   zUser.remove_context_datat  sI    	)=siXXXXXX 	 	 	DD	s   ! 
//c                     t          | t          j        t          j                   t          | t          j        t          j                   dS )zO
        Clear the context filters
        :param context: The context
        N)r   r   r  r   FILTERINBOUND_KEYBOARD)r   s    rg   clear_context_filterszUser.clear_context_filters  s:     	G_%9>;PQQQG_%9>;Z[[[[[rf   c                     ddl m} ddlm} | j                            |j        |j        k                                  |j	        
                                          S )zX
        Get the expired bounty loans
        :return: The expired bounty loans
        r   )BountyLoanStatus)
BountyLoan) src.model.enums.BountyLoanStatusr  src.model.BountyLoanr  bounty_borrowersr   statusEXPIREDorder_bydateasc)rm   r  r  s      rg   get_expired_bounty_loanszUser.get_expired_bounty_loans  so     	FEEEEE333333$**:+<@P@X+XYYbbO!!
 
 	
rf   c                 L    t          |                                           dk    S )z~
        Returns True if the user has expired bounty loans
        :return: True if the user has expired bounty loans
        r   )r   r  rr   s    rg   has_expired_bounty_loanszUser.has_expired_bounty_loans  s#     4002233a77rf   c           	          ddl m}  |t          t          j                                        gt          |                                           z                      S )z
        Returns the cumulative percentage of the expired bounty loans
        :return: The cumulative percentage of the expired bounty loans
        r   format_percentage_value)src.utils.math_utilsr"  r   r   BOUNTY_LOAN_GARNISH_PERCENTAGE	get_floatr   r  rm   r"  s     rg   .get_expired_bounty_loans_cumulative_percentagez3User.get_expired_bounty_loans_cumulative_percentage  sj     	A@@@@@&&)3==??@d3355667 
 
 	
rf   c                      | j         | j        z   S )zp
        Returns the bounty plus the pending bounty
        :return: The bounty plus the pending bounty
        )r&   r*   rr   s    rg   get_bounty_plus_pending_bountyz#User.get_bounty_plus_pending_bounty  s     {T000rf   c                 2    |                                  dk    S )zj
        Returns True if the user has income tax
        :return: True if the user has income tax
        r   )get_income_tax_percentagerr   s    rg   has_income_taxzUser.has_income_tax  s     --//!33rf      levels_downc                 z    t          j        | j        |          }|j        | _        |                                  dS )z
        Reduces the tax bracket by the given amount
        :param levels_down: The number of levels down
        :return: None
        N)r   get_previous_bracketr(   
min_amountsave)rm   r.  previous_tax_brackets      rg   reduce_tax_bracketzUser.reduce_tax_bracket  s=      0D$k 
  

 $8#B 		rf   c                 \    ddl m}  |t          j        | j                  j                  S )z^
        Returns the income tax percentage
        :return: The income tax percentage
        r   r!  )r#  r"  r   get_bracketr(   
percentager&  s     rg   r+  zUser.get_income_tax_percentage  s@     	A@@@@@&&()ABBM
 
 	
rf   c                     t                                                               t           j        t          j                                        t	          j        t          j        	                                          z
  k              S )zs
        Get the active users who interacted with the system
        :return: The active interactive users
        )days)
r   r   r   rG   rp   rq   	timedeltar   INACTIVE_GROUP_USER_DAYSget_intre   rf   rg   get_active_interactive_usersz!User.get_active_interactive_users  sh     {{}}""-##%% c&B&J&J&L&LMMMNN
 
 	
rf   c                 f    t          | j        pt          j                                                  S )z\
        Returns the timezone of the user
        :return: The timezone of the user
        )r   rN   r   TZgetrr   s    rg   get_timezonezUser.get_timezone  s#     5666rf   c                 Z    	 t          | j                  S # t          $ r
 t          cY S w xY w)z
        Returns the language of the user, used for texts sent in private chat
        :return: The language of the user
        )r   rX   
ValueErrorr   rr   s    rg   get_languagezUser.get_language  s>    	$DM*** 	$ 	$ 	$####	$s    **c                 d    t           j                             |                                           S )zd
        Returns the current time of the user
        :return: The current time of the user
        )rp   rq   rA  rr   s    rg   get_current_timezUser.get_current_time  s'      $$T%6%6%8%8999rf   r  c                 &    ddl m}  |||           S )z
        Returns the formatted datetime of the user in their timezone

        :param date: The datetime
        :return: The formatted datetime of the user
        r   )default_datetime_format)src.service.date_servicerH  )rm   r  rH  s      rg   get_datetime_formattedzUser.get_datetime_formatted  s*     	EDDDDD&&tT222rf   c                 &    ddl m}  |||           S )z
        Returns the formatted date of the user in their timezone

        :param date: The date
        :return: The formatted date of the user
        r   )default_date_format)rI  rL  )rm   r  rL  s      rg   get_date_formattedzUser.get_date_formatted  s*     	A@@@@@""4...rf   c                 <    | j         t          | j                   ndS )zF
        Returns the crew role
        :return: The crew role
        N)r@   r   rr   s    rg   get_crew_rolezUser.get_crew_role  s     
 ,0>+Ex'''4Orf   c                 N    |                                                                  S )z^
        Returns the crew role description
        :return: The crew role description
        )rO  get_descriptionrr   s    rg   get_crew_role_descriptionzUser.get_crew_role_description&  s"     !!##33555rf   c                    ddl m}m}  |             t          j                                        }| j                            |j                                        |j        |k    z            	                                dk    S )zx
        Returns True if the user is a Legendary Pirate
        :return: True if the user is a Legendary Pirate
        r   LegendaryPirateensure_legendary_pirate_schema)
src.model.LegendaryPiraterU  rV  rp   rq   legendary_piratesr   end_daterz   countrm   rU  rV  rq   s       rg   is_legendary_piratezUser.is_legendary_pirate.  s    
 	^]]]]]]]&&(((##%%%++%--//O4Ls4RS
 

%''A 	rf   c                     ddl m}m}  |             t          j                                        }| j                            |j        dk    |j        	                                |j        |k    z  z            
                                dk    S )z
        Returns True if the user is a permanent Legendary Pirate
        :return: True if the user is a permanent Legendary Pirate
        r   rT  T)rW  rU  rV  rp   rq   rX  r   is_permanentrY  rz   rZ  r[  s       rg   is_permanent_legendary_piratez"User.is_permanent_legendary_pirate;  s    
 	^]]]]]]]&&(((##%%"(( -5#,4466?;SVY;YZ\  egg		
rf   c                     ddl m} | j                            |j        t
          j                                        k                                              dk    S )zf
        Returns True if the user is a Warlord
        :return: True if the user is a Warlord
        r   )Warlord)src.model.Warlordra  warlordsr   rY  rp   rq   rZ  )rm   ra  s     rg   
is_warlordzUser.is_warlordL  sU    
 	.-----}""7#3h6G6K6K6M6M#MNNTTVVYZZZrf   c                     d| j          S )zb
        Returns the mention url of the user
        :return: The mention url of the user
        ztg://user?id=r   rr   s    rg   get_mention_urlzUser.get_mention_urlU  s     1t000rf   c                 .    ddl m}  || j                  S )zf
        Get the conscription remaining time
        :return: The conscription remaining time
        r   )get_remaining_duration)rI  rh  rB   )rm   rh  s     rg   get_conscription_remaining_timez$User.get_conscription_remaining_time]  s+    
 	DCCCCC%%d&@AAArf   c                  `    t                               d                                           dS )z>
        Reset the daily reward
        :return: None
        T)rS   N)r   r   executere   rf   rg   reset_daily_rewardzUser.reset_daily_rewardf  s*     	T22::<<<<<rf   )N)NNN)TN)r-  )ra   rb   rc   __doc__	CharFieldr    r   __annotations__r!   r"   r#   BigIntegerFieldr&   intCheckr(   r)   r*   DateTimeFieldr-   rp   r.   SmallIntegerFieldr/   r0   r1   r2   r3   BooleanFieldr4   boolr5   r6   r7   r8   r9   r:   r;   ForeignKeyFieldr
   r>   r?   r@   rA   rB   rC   rD   IntegerFieldrE   rq   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   r   r  rX   rY   rZ   r[   r\   r]   r  rX  rc  daily_bonusesrh   rn   rs   rv   rx   staticmethodr   r{   r   r   r   listr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   DEFAULT_TYPEr   r   r   r   anyr  r  r  r   r  r  r  r'  r)  r,  r4  floatr+  r=  r   rA  r   rD  rF  rJ  rM  rO  rR  r\  r_  rd  rf  ri  rl  re   rf   rg   r   r   "   se          #,)r$"G"G"GJiGGG%.Y"%=%=%=M3?===$-I$<$<$<L#	/<<<#,9#;#;#;Ky;;;$3OA$>$>$>FC/!>>>1@&@ A AB2 2 2.    =LO&K L LM= = ="C/$9    -<OA,F,F,FNC/)FFFANTXAYAYAYX.>YYY@MSW@X@X@XH-=XXX4E4Ea4P4P4P# 11PPPBO-UYBZBZBZh/-?ZZZN[mO O O((*;m*K    4E3DQ3O3O3O00OOO.?.?.J.J.JNC++JJJ4@L4N4N4Nd\1NNN-9\$-G-G-Gtl*GGGANTXAYAYAYX.>YYYANTXAYAYAYX.>YYYCP=VZC[C[C[x0=@[[[CP=VZC[C[C[x0=@[[[ANTXAYAYAYX.>YYY3?<3N3N3NTL0NNN#2?4VZ#[#[#[D$
 [[[8E48P8P8PNH%5PPP):):)E)E)EIs&&EEE=J]PT=U=U=U*]:UUU?L}RV?W?W?W8,}<WWW+7<+E+E+EOTL(EEE)5d)C)C)CM4,&CCC8D$8O8O8O!3#5OOO;H=!%< < <x(=8    GTmY]F^F^F^ ("3m"C^^^2;)r2J2J2Jy4/JJJ:K:KQU:V:V:V0047VVV;G<T;R;R;Rs\1D8RRR*6,q*A*A*AOS<'AAA$0L$?$?$?Hd\!???R_R_S S S,h.?-.O    !*	Rd C C CHcIoCCC%1\$%?%?%?Itl"???O\}P P P)8+<}+L    O\mO O O((*;m*K    KW,K K K2D<4G    5AL4N4N4Nd\1NNN,8L,C,C,Cs\)CCC.:l1.E.E.E|+EEE )	Q@P@V W W WHcIoWWW )- #,,, %%%%+/cDj///). $...
 !%$$$ HM       0c 0 0 0 0	* 	* 	*G G GC C C 
S 
 
 
 \
7 7 7	1# 	1 	1 	1 	1 DH", ",",48L", ", ", ",H3 3 3 36
f 
 
 
 
">F > > > >- - -W W WS S S S S(& ( ( ( (	 	 		 	 	C C C ? ? ? ? ? \?% % %U UD U U U UHc H H H HF F F? ? ?	 	 	 	 	: : :	T 	 	 	 	NT N N N NP P P P P
D 
 
 
 
9 9 9 9 91h 1 1 1 1(3 ( ( ( ([T [ [ [ [ 	Z 	Z 	Z 	Z \	Z
v 
# 
 
 
 
" `dc cc.:.GcY\c	c c c c
UL,E 
UPS 
U 
U 
U 
U,2K      (,	
 
*

 !%
 	

 

 
 
 \
( RV *1?LO	   \" ^bO O*O1?OHKOX[O	O O O \O RV *1?LO   \ \|'@ \ \ \ \\
$ 
 
 
 
8$ 8 8 8 8
 
 
 
 
1 1 1 1 14 4 4 c $     

5 

 

 

 

 

$ 

 

 

 \

7h 7 7 7 7	$h 	$ 	$ 	$ 	$:("3 : : : :
38+< 
3 
3 
3 
3 
3
/x'8 
/S 
/ 
/ 
/ 
/P P P6 6 6T    
t 
 
 
 
"[D [ [ [ [1 1 1 1 1B B B B B = = \= = =rf   r   )MySQLMigratormigrate)db_objr`   r/   r$   r0   Tr+   rI   )r@   rB   F)r   )r&   rX   rV   rW   )>rp   typingr   zoneinfor   peeweesrc.tg_compatr   src.tg_compat.extr   	constantsr   resources.EnvironmentEnvironmentr   	resourcesr   src.model.BaseModelr	   src.model.Crewr
   src.model.enums.ContextDataKeyr   r   r   r   r   r   r   r   r   r   src.model.enums.Languager   r   src.model.enums.crew.CrewRoler   +src.model.enums.income_tax.IncomeTaxBracketr   src.utils.context_utilsr   r   r   r#  r   r   create_tableplayhouse.migrater  r  
pw_migrater  get_db	_migrator
add_columnrt  	Exceptionrs  drop_not_null	add_indexrn  r  re   rf   rg   <module>r     s                                * * * * * *     # # # # # #       ) ) ) ) ) )       J J J J J J J J              * ) ) ) ) ) ? ? ? ? ? ? ? ? 2 2 2 2 2 2 H H H H H H         
 ? > > > > >K= K= K= K= K=9 K= K= K=\      		FFFFFFFF******mfmoo..IJV%;=N=NWX=Y=Y=YZZ     	 	 	D			FFFFFFFF******mfmoo..IJV%?TXAYAYAYZZ     	 	 	D			FFFFFFFF******mfmoo..IJ(=>>     	 	 	D			FFFFFFFF******mfmoo..IJF$JSXYY     	 	 	D	
		FFFFFFFF******mfmoo..IJFK>>     	 	 	D		FFFFFFFF******mfmoo..IJJ		Q@P@V W W W	
 	
    
  	 	 	DD	sr    AC1 1C98C9=AE EEAF   F('F(,AG4 4G<;G< AI IIAJ, ,J54J5