
    sojC                    *   d dl Z d dlZd dl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 d dlmZmZmZmZ d dlmZ d dlZd dl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&m'Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z= d dl>m?Z? d dl@mAZA d dlBmCZC d dlDmEZE d dlFmGZG d d lHmIZI d d!lJmKZK d d"lLmMZM d d#lNmOZOmPZP d d$lQmRZRmSZSmTZT d d%lUmVZVmWZW d d&lXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_ d d'l`maZa d d(lbmcZcmdZd d d)lemfZfmgZgmhZh d d*limjZj d d+lkmlZl d,eGd-efd.Zm	 	 	 dd0ed1e9d2ejn        d3eod4ed5efd6Zp	 	 	 	 	 	 	 	 	 dd0ed7eod1e9d8ed9eMd:eqd;eod<erd=eod>eod?eod-erfd@Zsd0edAed-erfdBZt	 dd0edDeod-erfdEZud0ed-erfdFZv	 	 dd2ejn        d4ed0edGeodHeod-dfdIZw	 dd4ed2ejn        d,eGd0ed-edz  f
dJZxddKZyd2ejn        d-dfdLZzd2ejn        d0edMe;fdNZ{d2ejn        dAedOed0efdPZ|d2ejn        d4ed0efdQZ}d0ed-eeef         fdRZ~	 ddAed0edSeod-dfdTZd0ed-erfdUZd9eMfdVZd4ed2ejn        d0edWeqdXedYed-dfdZZd0ed[ed\eod]eod-ee         f
d^Zd4ed2ejn        d0edAed-df
d_Zd0ed-eGfd`Z	 dd0edaerdbeodceod-df
ddZ	 dd2ejn        d0edee9dfedgerdhedierdjerd-dfdkZ	 	 	 	 	 	 	 	 	 dd4ed0edledOedmeodneodoeodpeodqeodreodseod-dfdtZd0edAed-erfduZej        fdAedveqd-erfdwZddxeod-eqfdyZddxeod-erfdzZ	 dd4ed2ejn        d0edAed{ed|eqd}eqd-dfd~Zd2ejn        d0edYedeqderderdeeeG                  fdZd2ejn        d0ed-eofdZd2ejn        d0ed-dfdZ	 dd2ejn        d0edeod-dfdZd2ejn        d0edAed-eofdZd2ejn        d-dfdZ	 dd0edeqdeod-e7e7gfdZd0edAed-e?eAz  eCz  fdZd2ejn        d0edAed-eofdZ	 dd0ederderd-erergfdZ	 dd4ed2ejn        d0edAederd-eofdZd0ed-erfdZd2ejn        d0ed-erfdZd2ejn        d0ed-eeeG                  fdZdS )    N)datetime	timedelta)TupleCallable)DoesNotExist)Update)
RetryAfter
BadRequestTimedOutTelegramError)ContextTypes)phrasesEnvironment)Game)	GroupChat)User)ContextDataKey)Emoji)
GameStatus)GameTurnNotificationGameOutcomeNotification)ReservedKeyboardKeys)
SavedMedia)SavedMediaType)Screen)DevilFruitAbilityType)IncomeTaxEventType)CommonChatException)	GameBoard)GameOutcome)GameTurn)GameType)PunkRecords)Shambles)WhosWho)ContextDataValue)Keyboard)	Character)SupabaseRest)Terminology)add_or_remove_bountyvalidate_amount)convert_seconds_to_durationget_remaining_durationget_elapsed_duration)get_ability_adjusted_datetimeget_ability_value)mention_markdown_userdelete_messagefull_media_sendget_message_urlfull_message_send"full_message_or_media_send_or_editget_deeplink)send_notification)get_current_languageset_current_language)get_bot_context_dataset_bot_context_data'get_random_user_context_inner_query_key)get_outcome_text)get_belly_formattedinbound_keyboardreturnc                     	 t          j        | j        t          j                           }|S # t
          t          t          t          f$ r t          t          j                  w xY w)zh
    Get the game from the keyboard
    :param inbound_keyboard: The keyboard
    :return: The game
    )r   	get_by_idinfor   DEFAULT_PRIMARY_KEYr   
IndexErrorKeyErrorAttributeErrorr   r   GAME_NOT_FOUND)rA   games      /app/src/service/game_service.pyget_game_from_keyboardrM   C   sc    :^!"6"JK
 
 *h? : : :!'"8999:s	   *- 7A$FrK   game_outcomecontextis_forced_endupdatesend_outcome_to_userc                 h	  K   t          | j        dz            }dx}}t          | j        dz            x}	}
|t          j        k    rt          j        }| j        }nB|t          j        k    rt          j        }| j        }n|}|}|rt          j        nt          j	        }	 t          j        | j                  }n3# t          j        $ r! t          j        d| j         d           Y dS w xY w|                                }|t          j        k    r"t          j        d| j         d| d           dS t          j        |                              t          j        | j        k    t          j        t          j        k    z                                            }|dk    rt          j        d| j         d	           dS |j        | _        |j        | _        |j        | _        || _        | j        }| j        }|                                sZt3          ||||	|t4          j        | j        |
           d{V  |,t3          ||||
|t4          j        | j        |
           d{V  || _        || _        |                                 r&|t          j        u rt;          j                    | _        |                                  ||                                  |                                   |rdS g }|r|!                    |           d}| "                                rl|                                 rX| #                                rDd}|!                    | j                   |t          j        u r|!                    | j                   |D ]y}d}|rMtH          j%        &                    tO          | |          tQ          | )                                                    }tU          ||tW          | ||                     d{V  z|                                 r| j,        t[          | j,        j.        /                                           ta          | d|d          }|j1        2                    tg          ||| j,        j.        j4        | j5        dd| j,        | j        gd	  	                   dS dS dS )aM  
    End the game, set the status and return the game
    :param game: The game
    :param game_outcome: The outcome
    :param context: The context
    :param is_forced_end: If the game was forced to end
    :param update: The update
    :param send_outcome_to_user: End user to send game outcome notification
    :return: None
       r   Game z$ no longer exists, skipping end_gameNz is not IN_PROGRESS (status: z1), skipping end_game to prevent double processing)statuszY status changed concurrently before claim, skipping end_game to prevent double processing)rO   pending_belly_amountrQ   tax_event_typeevent_idopponentFT )rN   is_for_group_global)captionchat_idedit_message_idadd_delete_buttonedit_only_caption_and_keyboard
group_chatauthorized_usersignore_bad_request_exception)6intwagerr    CHALLENGER_WONr   WONOPPONENT_WONLOST
FORCED_ENDDRAWr   rD   idr   loggingwarning
get_statusIN_PROGRESSrQ   whererV   execute
challengerrZ   no_wager_was_collectedr+   r   GAME	is_globalr   nowglobal_opponent_end_datesaveappendis_guess_based
has_winnerr   *GAME_OUTCOME_NOTIFICATION_TIME_TERMINOLOGYformatget_global_time_based_textget_guess_game_result_term_textget_terminologyr9   r   rb   r;   groupget_languageget_textapplicationcreate_taskr4   tg_group_id
message_id)rK   rN   rO   rP   rQ   rR   
half_wagerbounty_for_challengerbounty_for_opponentpending_bounty_for_challengerpending_bounty_for_opponentfinal_statuslatest_gameprevious_statusclaimed_rowsrt   rZ   notification_usersadd_time_and_terminologyufooter_textot_texts                         rL   end_gamer   S   sL     * $*q.))J233/BEdjSTnBUBUU!$?{111!~ $
	1	1	1!"j !+(0=Rz,,:?nTW--   MMMMNNN #."8"8":":O*000>DG > >/ > > >	
 	
 	
 	 	<(((	47"t{j6L'LM	N	N	 
 q>DG > > >	
 	
 	
 	 ",DO(DM"DJDKJ]H1133 "!!>-2W	
 	
 	
 		
 		
 		
 		
 		
 		
 		
 &#%@16#	 	 	 	 	 	 	 	 	 	 !DODM ~~ 7LK,DDD(0%OOIIKKK %' 8!!"6777$ 	5!1!1 	5doo6G6G 	5#'  	!!$/222 ;555%%dm444 [ [# 	!LSS*433/0D0D0F0FGG K  ,CD![,Y,YZZZZZZZZZZ ~~ 
DO7T_2??AABBB4LVZ[[[''-9 $"&/3?"&/!2-1
 
 
	
 	
 	
 	
 	

 
77s   B8 8,C('C(is_finished	user_turnterminologyremaining_seconds_to_startis_played_in_private_chattext_to_add_before_footerr\   challenger_has_finishedopponent_has_finishedc           	         d}d}|                                  }|                                 }|                                rCt          j                            |                                                                           }|||z  }|                                 r)| 	                                r|s|t          | |          z  }|r||t          j        ur|s||t          |          dz   z  }|t          j        u r6|t          j                            t!          | j                            z  }n|t          j        u r5|t          j                            t!          | j                            z  }n|t          j        z  }n| 	                                r;|s9|                     |          r|
s|t          j        z  }n|	s|t          j        z  }nw|su|r0|t          j                            t!          |                    z  }nC|0|t          j                            t5          |                    z  }n|r|t          j        z  }|rV|sT|                     |          r|	r|                     |          r(|
s&|t;          | 	                                           z  }| j        Yt          j                            |                                |                                tA          | j!                  ||          S t          j"                            |                                |                                t!          | j                  t!          | j                  tA          | j!                  ||          S )a  
    Get the text
    :param game: The game object
    :param is_finished: Is the game finished
    :param game_outcome: The game outcome
    :param user_turn: The user turn
    :param terminology: The character, in case of Who's Who
    :param remaining_seconds_to_start: The remaining seconds to start
    :param is_played_in_private_chat: Is the game played in private chat
    :param text_to_add_before_footer: The text to add before the footer
    :param is_for_group_global: If the text is for a group and the game is global
    :param challenger_has_finished: If the challenger has finished playing
    :param opponent_has_finished: If the opponent has finished playing
    :return: The text
    r[   N

add_turn_notification_time)#is_turn_basedget_typehas_difficulty_levelr   GAME_DIFFICULTYr   get_difficultyget_namer|   rw   r   r    NONEr   rg   GAME_RESULT_WINr2   rt   ri   rZ   GAME_RESULT_DRAWis_challengerGAME_GLOBAL_PENDING_CHALLENGERGAME_GLOBAL_PENDING_OPPONENT	GAME_TURNGAME_COUNTDOWNr-   GAME_STARTEDis_opponentget_auto_move_warningGAME_TEXT_WITHOUT_PLAYERSget_descriptionr@   rf   	GAME_TEXT)rK   r   rN   r   r   r   r   r   r\   r   r   added_ot_textdifficulty_textr   	game_types                  rL   r   r      s   : MO&&((M--//I%%'' [!1889L9L9N9N9W9W9Y9YZZ ,22 E!1!1 E:M E3D)DDD 6|/LHX4X4X 	S!8<[IIFRRM;555W4;;<QRVRa<b<bcccMM[555W4;;<QRVR_<`<`aaaMMW55MM			 6"5 6i(( 	B1F 	BWCCMM( 	BWAAM  	6 	6W.556KI6V6VWWWMM)5!7!>!>/0JKK" "  + 6!55 	`#` 	**	` 4K	`
   ++`
 5J` 	.dnnN^N^J^____}077  %%''
++
 
 	
 ##!!##do..dm,,DJ''      userc           	      4   |                                  sdS g }|                     |          }| }|                                 }|                                 }|                                 }|r| o| }| j        }	| j        }
n| }| j        }	| j        }
|rA|	                    t          j                            t          |	d                               |r|t          j        u r|r|sF|rD|rB|	                    t          j                            t#          |
|	d                               |                                 \  }}|s|r|s|rW|t          j        u r|sG|r|n|}|	                    t          j                            t)          |d                               |sX|rV|rTt+          ||z
  d          }|	                    t          j                            t)          |d                               dd                    |          z   S )z
    Get the text for a time based game in global chat
    :param game: The game
    :param user: The user
    :return: The text
    r[   T)	show_fullr   r   
)rw   r   r   get_outcomer   global_challenger_start_dateglobal_challenger_end_dateglobal_opponent_start_datery   r{   r   GAME_GLOBAL_CURRENT_TIMEr   r/   r    rg   GAME_GLOBAL_COMPLETION_TIMEr.   get_players_time_secondsGAME_GLOBAL_OPPONENT_TIMEr-   maxGAME_GLOBAL_REMAINING_TIMEjoin)rK   r   	text_listr   r   r   outcomer   self_is_still_playingself_start_timeself_end_timechallenger_secondsopponent_seconds
other_timeremaining_time_secondss                  rL   r   r   b  s    >> rI&&t,,M##K""$$K++--G"::<< 6$/ O8O4O;7$/95  
,33$_EEE 	
 	
 	
 	 
W(BBB{B C4 C9F C 	/66&}oQUVVV 	
 	
 	
 ,0+H+H+J+J((  
3 
 
	
%)CCCC+6L''<L
-44+J$GGG 	
 	
 	
  
2 
{ 
!$%7:J%JA!N!N.55+,BdSSS 	
 	
 	
 DIIi((((r   Tshould_add_already_guessed_textc                     |                                  rt          j        }nt          j        }|s|S t          j                            t          |           |          S )a  
    Get the text for a time based game in global mode, when the challenger has finished playing
    :param game: The game
    :param should_add_already_guessed_text: If it should add "You have already guessed correctly" text prefix
    :return: The text
    )has_opponentr   GAME_GLOBAL_GUESS_WAIT_OPPONENTr   !GAME_GLOBAL_GUESS_ALREADY_GUESSEDr   get_opponent_and_wager_text)rK   r   	wait_texts      rL   #get_global_text_challenger_finishedr     s`      ;;		:	* 4;;#D))9  r   c                     | j         dS t          j                            t	          | j                   |                                           S )zY
    Get the opponent and wager text
    :param game: The game
    :return: The text
    Nr[   )rZ   r   GAME_OPPONENT_AND_WAGERr   r2   get_wager_formattedrK   s    rL   r   r     sG     }r*11dm,,d.F.F.H.H  r   should_delete_messageshow_timeout_messagec           
      0  K   |r|rt          d          |r2t          | ||j        t          j        |j        ddd           d{V  n8|r6t          | |j        |j        |j        j        nd|j                   d{V  |	                                 dS )a  
    Delete game
    :param context: The context
    :param update: The update
    :param game: The game
    :param should_delete_message: If the message should be deleted
    :param show_timeout_message: If the message should be edited showing timeout
    :return: None
    zBshould_delete_message and show_timeout_message cannot be both TrueT)rO   rQ   rb   r]   r_   ra   r`   rd   N)rO   rb   r^   r   )

ValueErrorr4   rb   r   GAME_TIMEOUTr   r3   rt   
tg_user_iddelete_instance)rO   rQ   rK   r   r   s        rL   delete_gamer     s     "  _!5 _]^^^ 
( O+/")-	
 	
 	
 		
 		
 		
 		
 		
 		
 		
 		
 
 


 37?3JT_//PT	
 
 
 	
 	
 	
 	
 	
 	
 	
 	r   c           	        K   |t          |          }|                                }|t          j        u r%t	          |t
          j        | d           d{V  dS |                                r't	          |t
          j        | ddd           d{V  dS |t          j	        t          j
        fv rZ|j        }t          | |||j        t          j                                                   d{V sdS t#          j                    }t          j                                        }|j        t+          |t,          j        t          j                                                  }|j        t1          |          z   }	||	k     rh|j        |k    r\t
          j                            t9          |	                    }
t;          ||
| d|                                dd           d{V  dS n"d|_        d|_        |                                 |S )	z
    Validate the game
    :param update: The update
    :param context: The context
    :param inbound_keyboard: The keyboard
    :param game: The game
    :return: The game if valid, None otherwise
    NT)textrQ   rd   F)r   rQ   answer_callback
show_alertrd   hours)r]   rQ   r`   rc   ra   rd   r   ) rM   rp   r   rk   r7   r   GAME_FORCED_ENDr   
GAME_ENDEDAWAITING_SELECTIONAWAITING_OPPONENT_CONFIRMATIONrt   r,   rf   EnvGAME_MIN_WAGERget_intr   rx   GAME_CHALLENGE_LIMITgame_cooldown_start_timer1   r   GAME_COOLDOWN_DURATIONr   game_challenge_countGAME_CANNOT_INITIATEr   r.   r4   get_playersrz   )rQ   rO   rA   rK   rV   rt   rx   challenge_limitcooldown_duration_hourscooldown_endr   s              rL   validate_gamer     s       |%&677**F&&&0()-	
 
 
 	
 	
 	
 	
 	
 	
 	
 t 	0#!)-
 
 
 	
 	
 	
 	
 	
 	
 	
 t*/1Z[[[?
$GZS5G5O5O5Q5Q
 
 
 
 
 
 
 
 	 4 lnn"7??AA.:->%<*2244. .#
 &>-B B B L \!!2oEE%:AA.|<< G * '%*.)-)9)9););7;59           4 F  34
/6:
3!!!Kr   c                     t          j                                        t           j                            t          j                                        } | D ]'}t
          j        |_        |                                 (dS )z?
    Force all games in progress to end

    :return: None
    N)	r   selectrr   rV   not_inr   get_finishedrk   rz   )active_gamesrK   s     rL   force_end_all_activer  T  sh     ;==&&t{'9'9*:Q:S:S'T'TUUL   +		 r   c                   K   t          j                                        t           j        t          j        k    t           j                                        t           j        t          j
                    t          t          j                                                  z
  k     z  t           j                            d          t           j        t          j
                    t          t          j                                                  z
  k     z  z  t           j        t          j
                    t          t          j                                                  z
  k     z  z  t           j                            d          t           j                                        z  t           j        t          j
                    t          t          j                                                  z
  k    z   z            }|D ]B}t)          |t*          j        | d           d{V  t/          j        d|j         d           CdS )	zi
    End inactive games (games which last interaction was more than N seconds ago)
    :return: None
    )minutesFr   T)rP   NrU   z was ended due to inactivity)r   r  rr   rV   r   rq   r   is_nulldater   rx   r   r   &GAME_INACTIVE_TIME_SINCE_START_MINUTESr   r   last_interaction_date,GAME_INACTIVE_TIME_SINCE_INTERACTION_MINUTESrZ   GAME_GLOBAL_INACTIVE_HOURSr   r    r   rn   rE   rm   )rO   inactive_gamesrK   s      rL   end_inactive_gamesr  b  s      []]((	
.	. 2::<<I #C,V,^,^,`,`aaab 088??3 #C,V,^,^,`,`aaab2 *LNN(X(`(`(b(bcccd3"	
N .66u==}$$&&( 1<>>IC4R4Z4Z4\4\$]$]$]]_	
M-	
0 0Nd  D Dt[-wdKKKKKKKKKKBTWBBBCCCCD Dr   	game_turnc                    K   |                                 rdS |t          j        k    r|j        }|j        }n|j        }|j        }| j                            t          | |||                     dS )z
    Notify a user that it's their turn

    :param context: The context
    :param game: The game
    :param game_turn: The game turn
    :return: None
    N)rw   r!   
CHALLENGERrt   rZ   r   r   enqueue_game_turn_notification)rO   rK   r  r   rZ   s        rL   notify_game_turnr    s       ~~ H'''/	-	 ##&w	8TJJ    r   rZ   c                 <  K   t          j        t          j                                                   d{V  	 t          j        |j                  }n# t          $ r Y dS w xY w|j	        |j	        k    r't          | |t          ||                     d{V  dS dS )a  
    Enqueue a game turn notification. Waits for N time and if the game board stays unchanged,
    sends the notification

    :param context: The context
    :param user: The user
    :param opponent: The opponent
    :param game: The game
    :return: None
    N)asynciosleepr   #GAME_TURN_NOTIFICATION_TIME_SECONDSr   r   rD   rm   r   boardr9   r   )rO   r   rZ   rK   updated_games        rL   r  r    s       -?GGII
J
JJJJJJJJ~dg..    TZ''/CD(/S/STTTTTTTTTTT ('   A 
A"!A"c                 J  K   t          j        t          j                                                   d{V  	 t          j        |j                  }n# t          $ r Y dS w xY wt          |j
                  t          j        k    rt          | ||dd           d{V  dS dS )z
    Enqueue a game timeout. Waits for N time and if the opponent doesn't accept,
    the game is deleted
    :param context: The context
    :param update: The update
    :param game: The game
    :return: None
    NFT)r   r   )r  r  r   GAME_CONFIRMATION_TIMEOUTr   r   rD   rm   r   r   rV   r   r   )rO   rQ   rK   r  s       rL   enqueue_game_timeoutr    s       -5==??
@
@@@@@@@@~dg..    ,%&&**SSSV\]a
 
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
 TSr  c                     | j         | j        fS )zW
    Get the players of a game

    :param game: The game
    :return: The players
    )rt   rZ   r   s    rL   r   r     s     ?DM))r   should_resetc                    K   |s|t          d          |rd}d}nt          j        }|j        }t	          j        ||                              t          j        | j        k                                               dS )z
    Update the players' private screen
    :param game: The game
    :param user: The user
    :param should_reset: If True, reset the private screen
    :return: None
    Nz/If should_reset is False, game must be provided)private_screen_listprivate_screen_in_edit_id)r   r   PVT_GAME_GUESS_INPUTrm   r   rQ   rr   rs   )r   rK   r   r"  r#  s        rL   set_user_private_screenr%    s        LDLJKKK ,"$(!!$9$(G! 	K/";   eDGtw			
Fr   c                 &   t          j        | j                  }| j        xt          j        k    r t          di |j        S t          j        k    r)t          di |}|
                    d           |j        S 	 t          d| j         d          )zj
    Get the path of the final image of a guess game

    :param game: The game
    :return: The path
    T)highlight_answerz
Game type z is not a guess gameN )jsonloadsr  typer"   WHOS_WHOr%   
image_pathSHAMBLESr$   set_grid_imager   )rK   	json_dictshambless      rL   get_guess_game_final_image_pathr2    s     
4:&&I
)X''Y''22!)!6!6I!6!6H##T#:::&&I$)IIIJJJr   c                     |                                  }t          | t                    rt          j                            |          S t          j                            |          S )zx
    Get the text of the result term of a guess game

    :param terminology: The terminology
    :return: The text
    )get_markdown_mention
isinstancer(   r   GAME_RESULT_CHARACTERr   GAME_RESULT_TERM)r   term_mentions     rL   r   r   1  sV     3355L+y)) B,33LAAA#**<888r   remaining_secondsrun_game_functionplayerc           	      r  K   	 t          j        |j                  }n3# t           j        $ r! t	          j        d|j         d           Y dS w xY wt          |          gg}|dk    rt          j        |_	        |
                                 |j        G|                                s3t          |dd          }t          ||| |d|j        d           d{V   ||||           d{V  dS 	 t          |d|	          }t          ||| ||                                d
           d{V  n# t"          $ r Y nw xY w|dk    r9t%          j        d           d{V  t)          | |||dz
  ||           d{V  dS t%          j        d           d{V  t)          | |||dz
  ||           d{V  dS )aS  
    Countdown to start
    :param update: The update object
    :param context: The context object
    :param game: The game object
    :param remaining_seconds: The remaining time
    :param run_game_function: The function to run when the countdown is over
    :param player: The player who triggered the countdown
    :return: None
    rU   z% no longer exists, skipping countdownNr   FT)r   )r]   rQ   keyboardra   r_   rd   )r   )r]   rQ   r=  saved_media_namerd   
      )r   rD   rm   r   rn   ro   #get_guess_game_play_deeplink_buttonr   rq   rV   rz   rb   rw   r   r4   r   get_saved_media_namer	   r  r  guess_game_countdown_to_start)rQ   rO   rK   r9  r:  r;  play_deeplink_buttonr   s           rL   rC  rC  @  s     (~dg&&   NNNNOOO AFFGHA ,		 ?&t~~/?/?&tUdKKKG!-/3 $-1           v6666666664CTUUU)!6688)-
 
 
 	
 	
 	
 	
 	
 	
 	
 	
    
 2mB+GT#4r#9;Lf
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
 mA+GT#4q#8:KV
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
s!    ,AA1?D1 1
D>=D>send_to_usershould_send_to_all_playersschedule_next_sendc                    K   |s%|r#|                                  st          d          ||s|g}n)| j        g}| j        |                    | j                   |S )aA  
    Get the users to send the image to
    :param game: The game
    :param game: The game object
    :param send_to_user: The user to send the image to
    :param should_send_to_all_players: If the image should be sent to all players
    :param schedule_next_send: If the next send should be scheduled
    :return:
    z7Cannot schedule next send if not sending to all players)rw   r   rt   rZ   r{   )rK   rE  rF  rG  userss        rL   'get_guess_game_users_to_send_message_torJ    s{       & T*< TT^^EUEU TRSSS(B)N!_-=$LL'''Lr   c           
      b  K   t          | |||           d{V sdS t          |          \  }}||k    rt          j        nt          j        }t          ||||            d{V  d|_        ||k    r|n|}g }|                                s5t          t          j
        t          |j        |j                            gg}|                                }	t          |	          }
t!          |          }t#          |d           d{V  |j        dz  }t'          j        d|j         d	| d
|j         d|            t          j                            |
          dz   t1          d|          z   }t3          ||j        |t7          t8          j        |          d|           d{V  |                                rdS t#          |d           d{V  t'          j        d|j         d	| d
|j         d|            t          j                            |
          dz   t1          d|          z   }t3          ||j        |t7          t8          j        |          d|           d{V  |j        :t?          |d||	          }t3          |||j        |j        dd           d{V  dS dS )z
    Validate the answer
    :param update: The update object
    :param context: The context object
    :param game: The game object
    :param user: The user object
    :return: None
    N)rQ   Fr   urlTr   rT   zWAGER RESULT - Winner: user_id=z, original_bet_amount=z, total_wager_pool=z, amount_displayed=r   )
media_type	file_name)r^   r]   saved_mediaignore_forbidden_exceptionr=  zWAGER RESULT - Loser: user_id=rN   r   r]   rb   r_   ra   rd   ) "guess_game_should_end_after_answerr   r    rg   ri   r   should_update_modelrw   r'   r   PVT_KEY_GO_TO_MESSAGEr5   r   rb   r   r   r2  r%  rf   rn   rE   rm   GUESS_GAME_CORRECT_ANSWERr   r?   r4   r   r   r   PHOTO"GUESS_GAME_OPPONENT_CORRECT_ANSWERr   )rQ   rO   rK   r   rt   rZ   r   loseroutbound_keyboardr   term_text_additionr-  
bet_amountwinner_captionloser_captionr   s                   rL   guess_game_validate_answerra    s      4FGT4PPPPPPPP  't,,J&*j&8&8""k>V  4'&
9
9
99999999$D(**JJE.0>> 	
  6'II  3
  $3355K8EE5d;;J "$T
:
:
::::::::qJL  ]47  ]  ]R\  ]  ]quq{  ]  ]  Q[  ]  ]  ^  ^  ^)001CDD
	
4
,
,	- 
 .*>*UUU#'"          ~~  "%d
;
;
;;;;;;;;L  ]%(  ]  ]R\  ]  ]quq{  ]  ]  Q[  ]  ]  ^  ^  ^299:LMM
	
5*
-
-	. 
  .*>*UUU#'"          "4GUUU O+/)-
 
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
 #"r   c                 v    t           j        | j        i}t          t          j        |t          j        d          S )z^
    Get the play button for the game
    :param game: The game
    :return: The keyboard
    T)screenis_deeplink)r   rF   rm   r'   r   GRP_KEY_GAME_PLAYr   r$  )rK   rE   s     rL   rA  rA    s:     ':DGDD!40KY]   r   r  is_opponent_boardhint_was_issuedc                    |                                  r$|r"|| _        |rt          j                    | _        n!|| _        |rt          j                    | _        t          j                    | _        |                                  dS )z
    Save the game
    :param game: The game
    :param board: The board
    :param is_opponent_board: If it's an opponent board
    :param hint_was_issued: If the hint was issued
    :return: None
    N)	rw   opponent_boardr   rx   last_hint_opponent_dater  last_hint_dater  rz   )rK   r  rf  rg  s       rL   	save_gamerl    sy     ~~ 1- 1# 	:+3<>>D(
 	1"*,..D!)DIIKKKKKr   r   winnerwinner_textr[  
loser_text
group_textc                   K   |                                 }t          |          }	|                    d          s)d|                    dd          z
  }
|d|
z  z  }|d|
z  z  }||	z  }||	z  }g }|                                s5t          t          j        t          |j	        |j
                            gg}t          |d           d{V  | j                            t          | ||j        |	                     |                                rdS t          |d           d{V  | j                            t          | ||j        |	                     |j
        |j
        }|Vt!                      }t#          |j                                                   t)          |d||
          }t#          |           t+          | |||j	        dd           d{V  dS dS )a'  
    End a text based game
    :param context: The context
    :param game: The game
    :param outcome: The outcome
    :param winner: The winner
    :param winner_text: The winner text
    :param loser: The loser
    :param loser_text: The loser text
    :param group_text: The group text
    


   r   rL  TrN  Nr^   r=  rS  rT  )r   r   endswithcountrw   r'   r   rW  r5   r   rb   r%  r   r   r6   r   r:   r;   r   r   r   r4   )rO   rK   r   rm  rn  r[  ro  rp  r   r]  missing_new_linesr\  rb   player_languages                 rL   end_text_based_gamerz  +  s|     ,  $3355K8EE )) / 1 1$ ; ;;t///d...
 %%K$$J.0>> 	
  6'II  
 "&t
<
<
<<<<<<<<##[&*;FW	
 	
 	
   ~~  "%d
;
;
;;;;;;;;##Z)9DU	
 	
 	
   " $
244O !1!>!>!@!@AAA!$7P[\\\J 111! O+/)-
 
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
 #"r   rt   should_remove_bounty_challengershould_save_challengershould_remove_bounty_opponentshould_save_opponentshould_save_gameshould_set_cooldown_challenger#should_set_global_cooldown_opponentc           	      R  K   |"|rt          d          |	rt          d          |"|rt          d          |
rt          d          |rt          j        |j                  j        }||j        k     r>t          t          j        	                    t          |j                                      t          ||j        d| dd|j                   d{V  |
r<t          |t          j        t          j                                                  |_        |rt          j        |j                  j        }||j        k     r>t          t          j        	                    t          |j                                      t          ||j        dd| |j        d	           d{V  |	rt%          j                    }t)          |t          j        t          j                                                  }|j        ||j        t/          |
          z   k    r||_        d|_        n|xj        dz  c_        ||xj        dz  c_        ||_        t4          j        |_        ||r|                                 ||r|                                 |r|                                 dS dS )a(  
    Start the game, removing bounty from challenger and opponent
    :param update: The update object
    :param game: The game object
    :param challenger: The challenger
    :param opponent: The opponent
    :param should_remove_bounty_challenger: If the bounty should be removed from the challenger
    :param should_save_challenger: If the challenger should be saved
    :param should_remove_bounty_opponent: If the bounty should be removed from the opponent
    :param should_save_opponent: If the opponent should be saved
    :param should_save_game: If the game should be saved
    :param should_set_cooldown_challenger: If the game cooldown should be set for the challenger
    :param should_set_global_cooldown_opponent: If the global cooldown should be set for the opponent
    :return: None
    NzFChallenger must be provided if should_remove_bounty_challenger is TruezEChallenger must be provided if should_set_cooldown_challenger is TruezBOpponent must be provided if should_remove_bounty_opponent is TruezHOpponent must be provided if should_set_global_cooldown_opponent is TrueFT)addrQ   should_affect_pending_bountyshould_saverW   )r  r  rQ   rW   r  r      rT   )r   r   rD   rm   bountyrf   r   r   ACTION_INSUFFICIENT_BOUNTYr   r@   r+   r0   r   $GAME_GLOBAL_ACCEPT_COOLDOWN_DURATIONr   r   $game_accept_global_cooldown_end_dater   rx   r1   r   r   r   r   rZ   r   rq   rV   rz   )rQ   rK   rt   rZ   r{  r|  r}  r~  r  r  r  current_opponent_bountycurrent_challenger_bountyrx   r   s                  rL   'collect_game_wagers_and_set_in_progressr    s1     8 * 	X   * 	W   ( 	cabbb. 	Z   % 
 #'."="="D"TZ//%299:Mdj:Y:YZZ   #J)-!%
 
 
 	
 	
 	
 	
 	
 	
 	
 + 
8U!F4<<>>9
 9
5 ' 
$(N:=$A$A$H!$tz11%299:Mdj:Y:YZZ   #J)-!%
 
 
 	
 	
 	
 	
 	
 	
 	
 & 1lnn):!8&..00*
 *
 /7j9ILc<d<d<dddd 36J/./J++ ++q0++ 

a

 (DK "8 4 		 r   c                    |                      |          rt          j        nd}t          j                            ||                                 t          t          j	        | j
        it          j                            S )z{
    Get global game item text with deeplink
    :param game: The game
    :param user: The user
    :return: The text
    r[   )rE   rc  )r   r   USERr   GAME_GLOBAL_ITEM_DEEPLINKr   get_global_item_textr8   r   rF   rm   r   PVT_GAME_GLOBAL_START_OPPONENT)rK   r   
self_emojis      rL   "get_global_game_item_text_deeplinkr    st      $11$77?RJ,33!!##&:DGD8	
 	
 	
  r   max_items_per_categoryc                    t          j                    }d}t          |          dk    rdS t          |          D ]y\  }}||k    r>t	          t
          j                  }|t          j        	                    |          z  } n1|t          j
        	                    t          ||                     z  }zt          j        	                    |          S )z
    Get global challenges section text
    :param user: The user
    :param max_items_per_category: Max items per category
    :return: Global challenges section
    r[   r   )rc  )r   get_global_gameslen	enumerater8   r   PVT_GAME_GLOBAL_LISTr   VIEW_ALL_WITH_EMOJIr   GLOBAL_CHALLENGE_ITEMr  DAILY_REWARD_GLOBAL_CHALLENGE)r   r  global_challengesglobal_challenges_textirK   rM  s          rL   "get_global_challenges_section_textr    s     -//
""r.// 	
 	
4&&&f&ABBBC"g&A&H&H&M&MM"E'"?"F"F.tT::#
 #
 	
 0778NOOOr   r   c                     t           j                                        }| r!|t           j                                        z  }|S )z
    Get auto move seconds
    :param add_turn_notification_time: If turn notification time should be added
    :return: The seconds
    )r    GAME_TURN_AUTO_MOVE_TIME_SECONDSr   r  )r   secondss     rL   get_auto_move_secondsr  8  sA     2::<<G " E3:BBDDDNr   c                 v    t           j                            t          t	          |                               S )z
    Get auto move warning
    :param add_turn_notification_time: If turn notification time should be added
    :return: The warning
    r   )r   GAME_AUTO_MOVE_WARNINGr   r-   r  r   s    rL   r   r   H  s;     )00#!=WXXX	
 	
  r   auto_move_functionr   extra_wait_timec                 n  K   t          j        t          |                                                      d{V  |dk    rt          j        |           d{V  	 t	          j        |j                  }n# t          $ r Y dS w xY w|                                rdS  || |||||           d{V  dS )aW  
    Enqueue auto move
    :param update: The update
    :param context: The context
    :param game: The game
    :param user: The user
    :param auto_move_function: The auto move function
    :param message_id: Identifier of the message that will be updated in auto move
    :param extra_wait_time: Extra time to wait
    :return: None
    Nr   )	r  r  r  rw   r   rD   rm   r   r   )rQ   rO   rK   r   r  r   r  r  s           rL   enqueue_auto_mover  V  s      ( --$..2B2B.BCC
D
DDDDDDDDmO,,,,,,,,,~dg..    !! 

VWlD*d
S
SSSSSSSSSSs   A8 8
BBsent_message_idchallenger_textopponent_textr\  c                   K   |                     |          r|||_        |j        }|j        }|}	n|||_        |j        }|j        }|}	|s|q	 t          | |	||                                |j        |dddd
  
         d{V  nX# t          $ r,}
t          j
        d|j         d| d|
            Y d}
~
n'd}
~
ww xY w|t          j        d|j         d           |                                 dS )	a  
    Edit the other player message
    :param context: The context object
    :param game: The game object
    :param player: The player object
    :param sent_message_id: The id of the message that was just sent to the player
    :param challenger_text: The challenger text
    :param opponent_text: The opponent text
    :param outbound_keyboard: The outbound keyboard
    :return: None
    NT)	r]   r=  rc   r^   r_   rd   rR  ra   should_log_ignored_exceptionz/Failed to edit other player's message for game z (message_id z): z0Skipped editing other player's message for game z: no message id stored yet)r   challenger_message_idrZ   opponent_message_idrt   r4   r   r   r   rn   ro   rm   debugrz   )rO   rK   r;  r  r  r  r\  other_playerother_player_message_idother_player_textes              rL   edit_other_player_messager  {  s     ( &!! , &)8D&!]"&":)&'6D$!_"&"<+ $;$G	!)*!%!1!1!3!3$/ 7-1+//3-1            	 	 	O?$' ? ?6? ?;<? ?       	
 
	!
 	'tw ' ' '	
 	
 	

 	IIKKKKKs   6B 
B="B88B=c                   K   |                                 sdS |                                rdS |j        dS |j        dS |                                \  }}||k    rdS t          |t          j        |            d{V  dS )a)  
    Check if opponent has timed out for guessing. If so, end game giving challenger the win.
    In case this method returns False, every caller should exit, since it handles everything
    :param context: The context
    :param game: The game
    :return: Whether the opponent has timed out
    FTN)rw   r   r   r   r   r   r    rg   )rO   rK   r   r   s       rL   timeout_opponent_guess_gamer    s       >> u  t&.u&.u+/+H+H+J+J((,,,u 43W
=
========4r   c           	        K   |                                 sdS |                                rdS |                                sdS |j        dS |                                \  }}||z
  }|dk    rt          | |           d{V  dS 	 t          | t          j        t          |j
                  d           dS # t          $ r7 t          | t          j        |j
        t          |j
                             Y nw xY wt          j        |           d{V  	 t          j        |j
                  }n# t"          $ r Y dS w xY w|                                rdS t          | |           d{V  dS )a@  
    Enqueue timeout opponent guess game. If the game is not finished and timeout is not yet enqueued, waits till as much
    time has passed as the challenger took to guess, and if the game is still ongoing, it means the opponent has lost
    :param context: The context
    :param game: The game
    :return: None
    Nr   F)	inner_keytolerate_key_exceptionr  )rw   r   r   r   r   r  r<   r   GAME_OPPONENT_TIMEOUTstrrm   rH   r=   r  r  r   rD   r   )rO   rK   r   r   r9  r  s         rL   #enqueue_timeout_opponent_guess_gamer    s      >>     &.+/+H+H+J+J((*-==A)'4888888888
0$'ll#(		
 	
 	
 	
 	 
 
 
^947cRVRYll	
 	
 	
 	
 	
 	

 -)
*
********~dg..    !! 
%g|
<
<<<<<<<<<<s$   	/B: :>C;:C;D3 3
E Er   c                   K   |rt          j                    |_        nt          j                    |_        |                                 |                                r,|r,| j                            t          | |                     dS dS dS )z
    End the global guess game after a player has correctly finished
    :param context: The context object
    :param game: The game object
    :param is_challenger: Whether the player is the challenger
    N)	r   rx   r   ry   rz   r|   r   r   r  )rO   rK   r   s      rL   end_global_game_playerr  #  s        7*2,..''(0%IIKKK \ \''(KGUY(Z(Z[[[[[\ \ \ \r   c           	      2  K   |                                 sdS |                    |          rQt          | t          |          |j        t          | |                     d{V  t          | |           d{V  dS t          | |           d{V rdS dS )aa  
    Check if the challenger has finished or the opponent has timed out. If returns true, exit immediately since all
    eventual messages/triggers are done internally
    :param context: The context
    :param game: The game
    :param user: The user
    :return: True if the challenger has finished or the opponent has timed out, False otherwise.
    Fru  NT)r   r   r6   r   r   get_global_share_keyboardr  rO   rK   r   s      rL   +challenger_has_finished_or_opponent_timeoutr  9  s       '')) u $ 
/55O.w==	
 
 
 	
 	
 	
 	
 	
 	
 	
 *'4888888888t )$77777777 t5r   c                 F  K   ddl m} t          j                                        t          j        t          j        k    t          j        	                    t          j                              z            }|D ]&}| j                             || |                     'dS )zu
    Restart the hint thread if it's down for all games
    :param context: The context object
    :return: None
    r   )restart_hint_thread_if_downN)*src.chat.common.screens.screen_game_manager  r   r  rr   rV   r   rq   r+  in_r"   get_guess_based_listr   r   )rO   r  gamesrK   s       rL   %restart_hint_thread_if_down_all_gamesr  \  s       WVVVVV KMM	
.	.49==A^A`A`3a3ab E  T T''(C(CGT(R(RSSSST Tr   max_lenonly_lettersc                     |                                  xt          j        k    r t          }t          }nxt          j        k    r8 t          }t          }t          j        | 	                                          }d}nCt          j
        k    rt          }t          }n%	 t          d|                                             | j        Gd}d}d}|||k     r	 |t          k    r't          j        | 	                                          }nt          j        ||          }|                                  t          j        k    rt          ||          }n	  ||          }n6# t          $ r)}	t#          j        d|	 d	           |d
z  }d}Y d}	~	nd}	~	ww xY w|||k     |t'          d          t)          | |                                d           |                                 r$t)          | |                                d           ||fS t/          j        | j                  }
|                                 rt/          j        | j                  nd}d}|t          k    rM|
                    d          }t	          di |} |dd|i|
}|r|                    d            |dd|i|}nL|
                    d          }t          di |} |dd|i|
}|r|                    d            |dd|i|}||fS )z
    Get the boards for a guess game
    :param game: The game
    :param max_len: The maximum length of the terminology to generate
    :param only_letters: If True, only generate letters, if False, generate all characters
    :return: The boards
    TzUnsupported game type: Nr?  r   )r  r  )	grid_sizezRetrying board creation... ()r  zWFailed to generate a valid game board after multiple attempts due to missing resources.)rg  )rf  	characterr   r(  )r   r"   PUNK_RECORDSr#   r(   r.  r$   r*   get_grid_size_by_difficultyr   r,  r%   r   r  r)   get_random_characterget_random_terminologyrn   ro   r   rl  get_as_json_stringrw   r)  r*  ri  pop)rK   r  r  board_classterminology_typer  max_retriesattemptsrandom_terminologyr  r0  opponent_json_dictri  	char_dictchar	term_dictterms                    rL   !get_generic_boards_for_guess_gamer  m  s    --//"X""""%K(X"K*:4;N;N;P;PQQGLL!K(Ht}}HHIII zm; 6 6#y004@4U++--5 5&& 7C6Y 'l7 7 7& mmoo!*** ();w O O O +,> ? ?    Cq C C CDDDA# m; 6 6, =%&  A  A  A$0022DIIII>> 	PdE4466$OOOOe| 
4:&&I<@NN<L<LVD$7888RVN9$$MM+..	#00i0088d8i88 	O"";///([NN4N;MNNNMM-00	'44)44:::	:: 	Q""=111([PPTP=OPPN.  s   BE 
F)FFc                     t          |           \  }}|                     |          s|                                 s|n|S )zw
    Get the player board
    :param game: The game object
    :param user: The user object
    :return: The board
    )r  r   rw   )rK   r   challenger_boardri  s       rL   get_player_boardr    sG     (I'N'N$n#11$77ct~~?O?OcUccr   c                    K   |                                 rdS |                    |          rt          | |           d{V rdS |                    |          r|                                rdS dS )z
    Should proceed after hint sleep?
    :param context: The context
    :param game: The game
    :param user: The user
    :return: True if the hint sleep should be proceeded, False otherwise
    FNT)r   r   r  r   r   r  s      rL   should_proceed_after_hint_sleepr    s        u (CGT(R(R"R"R"R"R"R"R u $ D$@$@$B$B u4r   specific_winner_textspecific_loser_textc           
      <   ||}| j         dz  }t          j        d| j          d| d| d|            t          j                            |          dz   t          d|          z   }t          j                            |          dz   t          d	|          z   }||fS )
a	  
    Get the winner and loser text
    :param game: The game
    :param specific_winner_text: The specific winner text
    :param specific_loser_text: The specific loser text. If not set, will use the specific_winner_text
    :return: The winner and loser text
    NrT   z7WAGER RESULT - get_winner_loser_text: total_wager_pool=z, calculated_bet_amount=z, winner_display_amount=z, loser_display_amount=r   TF)rf   rn   rE   r   rX  r   r?   rZ  )rK   r  r  r^  rn  ro  s         rL   get_winner_loser_textr    s     "2qJL  C4:  C  Coy  C  C  T^  C  C  wA  C  C  D  D  D)001EFF
	
4
,
,	-  	299:MNN
	
5*
-
-	.  
""r   r[   detail_textc           	        K   	 | j         j        }n# t          $ r Y dS w xY w|dS |                                }|sdS |                                }||j        dS |j                                        |                                k    sdS |                                r|                    |          rt          ||           d{V  d}|||z  }|t          ||          z  }|t          |d          z  }t          j                            |          }||                    dd          }t!          ||| t#          ||                     d{V  dS dS )	ao  
    Should the guess game end after the answer is received?
    :param update: The update received
    :param context: The context
    :param game: The game
    :param user: The user
    :param detail_text: The detail text to add in the challenger has finished message
    :return: True if the guess game should end after the answer is received, False otherwise
    FNr[   )r   z



rr  )rQ   r=  T)effective_messager   rI   stripr   namelowerrw   r   r  r   r   r   rX  r   replacer6   r  )rQ   rO   rK   r   r  answerr   r   s           rL   rU  rU    s     ").   uu ~u\\^^F u&&((Kk.6u!!##v||~~55u ~~ D..t44 $Wd333333333"{"G-dD9996t]bcccc3::7CC"ooj(;;G.w==	
 
 
 	
 	
 	
 	
 	
 	
 	
 u4s    
c                 &    t          | dd          S )z[
    Get the text for the inline share
    :param game: The game
    :return: The text
    FT)r\   )r   r   s    rL   get_text_for_inline_sharer  L  s     D%T::::r   c                 T   t          |           }t          t          j        t          j        |j        it          j        d          gg}t          t          j
        t          |g|                                |          }|j                            | t          j        ||           |S )z
    Set a game sharing info in the user context and get the key
    :param context: The context
    :param game: The game
    :return: The key
    T)rE   rc  rd  )argsdescriptionr=  r  )r>   r'   r   re  r   rF   rm   r   r  r&   GAME_GLOBAL_INLINE_RESULT_SHAREr  r  rt   set_context_datar   INLINE_QUERY)rO   rK   r  r\  context_data_values        rL   !set_and_get_global_share_item_keyr   V  s     8@@I )*>H< 	  	

/ ,</!V--//", , , 	O$$,.@I %    r   c                     |                                 sg S |j        g S |                                rg S t          t          j        t          | |                    ggS )z
    Get the global share button
    :param context: The context
    :param game: The game
    :return: The global share button
    N)switch_inline_query)rw   rZ   r   r'   r   	KEY_SHAREr   )rO   rK   s     rL   r  r  z  sw     >> 	} 	 	 !$Egt$T$T  	
 r   )FNN)	NNNNFNFFF)T)TF)N)rB   N)NF)FF)	NNTTTTTTF)F)r   )r[   )r  r)  rn   r   r   typingr   r   peeweer   src.tg_compatr   src.tg_compat.errorr	   r
   r   r   src.tg_compat.extr   	constantsc	resourcesr   r   r   src.model.Gamer   src.model.GroupChatr   src.model.Userr   src.model.enums.ContextDataKeyr   src.model.enums.Emojir   src.model.enums.GameStatusr   src.model.enums.Notificationr   r   $src.model.enums.ReservedKeyboardKeysr   src.model.enums.SavedMediar   src.model.enums.SavedMediaTyper   src.model.enums.Screenr   1src.model.enums.devil_fruit.DevilFruitAbilityTyper   -src.model.enums.income_tax.IncomeTaxEventTyper   src.model.error.CommonChatErrorr   src.model.game.GameBoardr   src.model.game.GameOutcomer    src.model.game.GameTurnr!   src.model.game.GameTyper"   &src.model.game.punkrecords.PunkRecordsr#    src.model.game.shambles.Shamblesr$   src.model.game.whoswho.WhosWhor%   src.model.pojo.ContextDataValuer&   src.model.pojo.Keyboardr'   src.model.wiki.Characterr(   src.model.wiki.SupabaseRestr)   src.model.wiki.Terminologyr*   src.service.bounty_servicer+   r,   src.service.date_servicer-   r.   r/   src.service.devil_fruit_servicer0   r1   src.service.message_servicer2   r3   r4   r5   r6   r7   r8    src.service.notification_servicer9   src.service.language_servicer:   r;   src.utils.context_utilsr<   r=   r>   src.utils.phrase_utilsr?   src.utils.string_utilsr@   rM   DEFAULT_TYPEboolr   re   r  r   r   r   r   r   r   r  r  r  r  r  r   r%  r2  r   rC  listrJ  ra  rA  rl  rz  r  r  STANDARD_LIST_SIZEr  r  r   r  r  r  r  r  r  r  r  r  r  r  rU  r  r   r  r(  r   rL   <module>r3     s9      ( ( ( ( ( ( ( ( " " " " " " " "                   O O O O O O O O O O O O * * * * * *     < < < < < < < <       ) ) ) ) ) )       9 9 9 9 9 9 ' ' ' ' ' ' 1 1 1 1 1 1 V V V V V V V V E E E E E E 1 1 1 1 1 1 9 9 9 9 9 9 ) ) ) ) ) ) S S S S S S L L L L L L ? ? ? ? ? ? . . . . . . 2 2 2 2 2 2 , , , , , , , , , , , , > > > > > > 5 5 5 5 5 5 2 2 2 2 2 2 < < < < < < , , , , , , . . . . . . 4 4 4 4 4 4 2 2 2 2 2 2 L L L L L L L L         
 ] \ \ \ \ \ \ \                  ? > > > > > S S S S S S S S         
 4 3 3 3 3 3 6 6 6 6 6 6:X :$ : : : :(  !%g
 g

g
g
 &g
 	g

 g
 g
 g
 g
 g
Z !%#&*&+%) %$)"'b b
bb b 	b
 b !$b  $b  #b b "b  b 	b b b bJE)T E) E)# E) E) E) E)R 9= 
15   .d s    & #'!&, ,&,, ,  	,
 , 
, , , ,f 	R RR&R R 	R
 
D[R R R Rj   ;Dl&? ;DD ;D ;D ;D ;D|L$= T V^    6U&U.2U>BUJNU U U U6
(A 
6 
Y] 
 
 
 
2*d *uT4Z0 * * * * 9> 
15	   >K$ K3 K K K K09 9 9 9 9K
K
&K
 K
 	K

  K
 K
 
K
 K
 K
 K
\
"@DZ^	$Z   2[
[
)6[
>B[
JN[
	[
 [
 [
 [
|
d 
x 
 
 
 
 V[ 
/3NR	   B W
 W
&W

W
 W
 	W

 W
 W
 W
 W
 
W
 W
 W
 W
z ,0#'*.!%!+/05 
  	
 &* ! $(   %) *. 
   DT  #    ( /0.BP P
P(+PP P P P< d s      d s    * "T "T"T&"T "T 	"T
 !"T "T "T 
"T "T "T "TJG&G
G G 	G
 G G DN+G G G GT|/H PT Y]    @;=&;=.2;=	;= ;= ;= ;=~ KO\ \&\.2\CG\	\ \ \ \, & .2 :> 	       FT9R TW[ T T T T$ ;@Y! Y!
Y!Y!37Y!Y! Y! Y! Y!x	d4 	dt 	dh0F0P 	d 	d 	d 	d&.2:>	   0 GK# #
#&)#@C#	3Z# # # #H > >>&> > 	>
 > 
> > > >B;D ;S ; ; ; ;!|/H !PT !Y\ ! ! ! !H&.2	$x.     r   