
    soj*g                     R   d dl Z d dlZd dlmZ d dlmZ d dlmZmZ d dl	m
c mc 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
lmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$Z$ d dl	m%Z% d dl&m'Z'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0m1Z1m2Z2 d dl3m4Z4m5Z5 d dl6m7Z7m8Z8 d dl9m:Z:m;Z;m<Z<m=Z= 	 d9dede>de?fdZ@dejA        ddfdZBdejA        deCddfd ZD	 	 d:dedeCd!ed"ededz  f
d#ZEd$e>de?fd%ZFded!edz  deGe         fd&ZHdedeGe         fd'ZIded(e d)e>d*ej        def
d+ZJ	 d;d$e>d!ed,ededz  fd-ZK	 d:d(e d$e>d,ededz  fd.ZL	 d9d(e d,ededz  fd/ZM	 d9d(e d,edej        fd0ZNd(e ddfd1ZOdejA        ddfd2ZPd3ed(e d4e j         ddfd5ZQd<d6ZRd(e d,edefd7ZSde?fd8ZTdS )=    N)Message)TelegramError)ContextTypesJobQueue)phrasesEnvironment)Crew)Group)	GroupChat)Leaderboard)LeaderboardCrew)LeaderboardUser)LegendaryPirate)User)Warlord)Feature)LeaderboardRankIndex)get_first_new_worldget_last_paradise)reset_bounty_poster_limit)set_current_language)warn_inactive_captains)default_date_format!get_remaining_time_from_next_cronget_next_run)&revoke_devil_fruit_from_inactive_users*warn_inactive_users_with_eaten_devil_fruit)0broadcast_to_chats_with_feature_enabled_dispatchfeature_is_enabled)mention_markdown_v2full_message_sendget_message_urlescape_valid_markdown_charsleaderboardglobal_leaderboard_message_idreturnc                 6   ddl m} ddlm} ddlm} ddlm} | j        du }d}d}d}	d}
t          | j
                  D ]\  }}|}|j        }t          |j                  t          j        u rht          j        |          }|t"          j                            t)          |j                  |                    |j        |j                            z  }t          |j                  t          j        u rkt3          j        |          }|S|	t"          j                            t)          |j                  |                    |j        |j                            z  }	"|
dz  }
|t"          j                            |j        t;          |j                  t=          |j        |j                   |!                                          z  } |            }|rt"          j"        nt"          j#        }|ht"          j$                            tK          |tL          j'        (                                tL          j)        *                                	                    }nd}|dk    rt"          j+        |z   }|	dk    rt"          j,        |	z   }	d}d}t[          | j.                  }|r|dk    rt          | j.                  D ]`\  }}|}|t"          j/                            |j        |j0        1                    d
          |j2        3                                          z  }at"          j4                            ||          }t"          j5                            || j6        | j7        |
||||	|| j8        rt"          j9        ndtu          |           ||d
                    S )z
    Gets the leaderboard message
    :param leaderboard: The leaderboard
    :param global_leaderboard_message_id: The global leaderboard message id
    :return: The leaderboard message
    r   )get_next_bounty_reset_time)get_remaining_duration)LogType)LogN    )
message_idchat_idchat_usernameT)	add_level)start_is_midnight);src.service.bounty_servicer(   src.service.date_servicer)   src.model.enums.LogTyper*   src.model.enums.Logr+   group	enumerateleaderboard_usersuserr   
rank_indexWARLORDr   get_latest_active_by_userr   LEADERBOARD_WARLORD_ROWformatr#   epithetget_deeplink_by_typeidLEGENDARY_PIRATEr    LEADERBOARD_LEGENDARY_PIRATE_ROWLEADERBOARD_USER_ROWpositionget_leaderboard_rank_messager    
tg_user_idtg_first_nameget_bounty_formattedLEADERBOARD_GLOBALLEADERBOARD_LOCAL#LEADERBOARD_VIEW_GLOBAL_LEADERBOARDr"   EnvUPDATES_CHAT_IDgetUPDATES_CHAT_USERNAMEget_or_noneLEADERBOARD_WARLORDSLEADERBOARD_LEGENDARY_PIRATESlenleaderboard_crewsLEADERBOARD_CREW_ROWcrewget_name_with_deeplinkcaptainget_markdown_mentionLEADERBOARD_CREWLEADERBOARDweekyearis_bounty_resetLEADERBOARD_VIEW_BOUNTIES_RESETr   )r$   r%   r(   r)   r*   r+   	is_globalcontent_textwarlords_textlegendary_pirates_texteffective_users_countindexleaderboard_userr:   warlordlegendary_piratenext_bounty_reset_timelocal_global_textview_global_leaderboard_text	crew_textcrew_items_texttotal_crewsleaderboard_crews                          '/app/src/service/leaderboard_service.pyget_leaderboard_messagers   .   s    FEEEEE??????//////''''''!T)ILM#,[-J#K#K  ,<%*   0 ;<<@T@\\\&@FFGW<CC+GO<<(('*EE  MM
 !!1!<==#45 5 1@0YZ^0_0_+&'*R*Y*Y/0@0HII,,W-EGWGZ[[+ + &
 "Q&!G8?? ),-=-HII#DOT5GHH))++	  LL 87996?^22WE^$0'.'R'Y'Y8+//11!7CCEE  (
 (
$$ (*$4}D##!(!FI_!_IOk344K R[1__'01N'O'O 	 	#E#0@w;BB ) %<<t<LL (==??    OO
 ,33KQQ	%%$3>3NV//TV2335NNN      contextc           	        K   ddl m}m} t          j                            t          j        j                  } ||          }t          | |           d{V  | j        	                    t          d                     t          j        d                                           t          j        dd                                           t          j                            t          j        j                  }|r$| j        	                     ||                      ns |t          t           j                                        |t          j        d	          z   
                    r'| j        	                    t)          |                      | j        	                    t+          |                      | j        	                    t-          |                      dS )z`
    Sends the weekly leaderboard to the group chat
    :param context: Context of callback
    r   )should_reset_bountyreset_bountyNT)reset_previous_leaderboard)can_join_crew)can_accept_new_memberscan_promote_first_mater-   )milliseconds)start_datetime)r3   rw   rx   datetimenowtimezoneutcmanage_leaderboardapplicationcreate_taskr   r   updateexecuter	   r   rN   CRON_SEND_LEADERBOARDrP   	timedeltar   r   r   )ru   rw   rx   r   r`   s        rr   send_leaderboardr      s     
 MLLLLLLL%.2283D3HIIC))#..O
 Wo
6
66666666 ##$=Y]$^$^$^___ 	Kd###++--- 	KtDIIIQQSSS &.2283D3HIIC 
I''W(=(=>>>>		%))++!3!C!C!CC	
 	
 	

 
 I 	''(>w(G(GHHH ##$J7$S$STTT ##$Nw$W$WXXXXXrt   r`   c           	      Z  K   t          | |           d{V }t          j                                        t          j        dk                                  t          j                                                  }|D ],}| j        	                    t          | |||                     -dS )z
    Manages the leaderboard
    :param context: Context of callback
    :param is_bounty_reset: Whether the bounty is reset
    :return: None
    NT)
create_and_send_leaderboardr
   selectwhere	is_activeorder_byrB   ascr   r   )ru   r`   global_leaderboardgroupsr7   s        rr   r   r      s        ;7OTTTTTTTT  ,....u$/FGGPPQVQYQ]Q]Q_Q_``F  
 
'''%I[\\	
 	
 	
 	

 
rt   r7   r   c                   K   ||t          d          t          ||                                nd           |ot          |                                          t
          j                                        k     rdS d |j        D             }t          d |D                       rdS t                      }||j        }|j        }nlt          j                                                                        d         }t          j                                                                        d         }t          j                                        t          j        |k    t          j        |k    t          j        |k                                               t          j                                                                        d         |_        t          j                                                                        d         |_        ||_        ||_        |                                 t-          ||           t/          |           t
          j                                        rt5          |||j        nd          }|&t9          | t:          j        |||g           d{V  n	 t?          | |t
          j         !                                           d{V }	|	j        |_        |                                 nC# tD          $ r6 tG          j$        d	t
          j         !                                            Y nw xY w|S )
a0  
    Creates a leaderboard list and sends it to the group chat
    :param context: Context of callback
    :param is_bounty_reset: Whether the bounty is reset
    :param group: The group to create the leaderboard for
    :param global_leaderboard: The global leaderboard
    :return: The leaderboard
    NzMIn order to create a local leaderboard, a global leaderboard must be providedc                      g | ]}|j         	|S  )r   .0gcs     rr   
<listcomp>z/create_and_send_leaderboard.<locals>.<listcomp>   s    'W'W'Wr",'W'W'W'Wrt   c              3   L   K   | ]}t          |t          j                   V   d S N)r   r   r]   r   s     rr   	<genexpr>z.create_and_send_leaderboard.<locals>.<genexpr>   s3      UU2%b'*=>>>UUUUUUrt   r   r-   )external_itemfilter_by_groups)r/   z%Failed to send global leaderboard to )%
ValueErrorr   get_languagerU   get_active_usersrN   LEADERBOARD_MIN_ACTIVE_USERSget_intgroup_chatsallr   r_   r^   r   r   isocalendardeleter   r7   r   r`   savecreate_leaderboard_userscreate_leaderboard_crewsSEND_MESSAGE_LEADERBOARDget_boolrs   r.   r   r   r]   r!   rO   rP   r   logging	exception)
ru   r`   r7   r   r   r$   r_   r^   ot_textmessages
             rr   r   r      sl      /7[
 
 	
 1B++---MMM u%%''((3+K+S+S+U+UUUF'W'WU5F'W'W'WUUUUUUU 	F--K %!&!& $$&&2244Q7 $$&&2244Q7 D +"2d":K<MQV<V giii  (,,..::<<Q?K(,,..::<<Q?KK"1K [%000[))) #,,.. ).@.L**RV
 
 B#)"'          	):Wc.A.E.E.G.G* * * $ $ $ $ $ $ *1);&  """"    !WC<O<S<S<U<UWW    
 s   2AL =MMrg   c                 R    t          j        |           }|                                S )z
    Gets the rank message of a leaderboard rank
    :param index: The leaderboard rank index
    :return: The leaderboard rank message
    )LeaderboardRankget_rank_by_indexget_emoji_and_rank_message)rg   leaderboard_ranks     rr   rG   rG   -  s'     )8(I%(P(P66888rt   c                 Z   g }d}g }|t          t          j        t          j                                      t          j        dk                                                        }|                    t          j	                               |                    t          j	                               t          d|          }|g }n|j        }|@t          j        t          j                                      t          j        dk              }n`t          j        t          j                                      t          j                            |                                                    }d |D             }t          t          j                                        t          j        t#                      j        k    t          j                    z  t          j        dk    z  t          j                            |          z  t          j                            |          z  t          j        dk    z                                t          j                                                            }	|	D ]>|v r8t3          | |t4          j                  }
|                    |
           |dz  } n?d}|	D ]`t;          fd|D                       sCt3          | |t4          j                  }
|                    |
           |dz  }|dz  }|dk    r nad}|	D ]`t;          fd	|D                       sCt3          | |t4          j                  }
|                    |
           |dz  }|dz  }|dk    r nat          t          j                                        t          j        tA                      j        k    t          j                    z  t          j        dk    z  t          j                            |          z  t          j                            |          z  t          j        dk    z                                t          j                                                            }d}|D ]`t;          fd
|D                       sCt3          | |t4          j!                  }
|                    |
           |dz  }|dz  }|dk    r na|tE          t          j#                              D ]>\  }}t3          | |j$        |dz   t4          j%                  }
|                    |
           ?tE          t          j#                              D ]K\  }}|j$        j        st3          | |j$        |dz   t4          j&                  }
|                    |
           L|S dS )z
    Creates a leaderboard list
    :param leaderboard: The leaderboard to create the users for
    :param group: The group to create the users for
    :return: The leaderboard users
    r-   NTc                 P    g | ]#}|j         t          j        j        k    |j        $S r   )r;   r   EMPERORrg   r:   )r   rh   s     rr   r   z,create_leaderboard_users.<locals>.<listcomp>f  s9     % % %&/*A*GGG 	GGGrt   Fr   c              3   2   K   | ]}|j         k    |V  d S r   r:   r   lur:   s     rr   r   z+create_leaderboard_users.<locals>.<genexpr>  )      EE"RW__2____EErt      c              3   2   K   | ]}|j         k    |V  d S r   r   r   s     rr   r   z+create_leaderboard_users.<locals>.<genexpr>  r   rt   c              3   2   K   | ]}|j         k    |V  d S r   r   r   s     rr   r   z+create_leaderboard_users.<locals>.<genexpr>  r   rt      )'listr   r   rB   r   .is_exempt_from_global_leaderboard_requirementsr   extendr   get_active_user_idsr   get_leaderboardr9   r   in_get_active_users_idslocation_levelr   level'get_is_not_arrested_statement_conditionis_adminnot_inbountyr   descsave_leaderboard_userr   PIRATE_KINGappendanyr   
FIRST_MATEr   	SUPERNOVAr8   get_active_order_by_bountyr:   r<   rC   )r$   r7   r9   rF   excluded_user_idsprevious_leaderboardprevious_leaderboard_userseligible_leaderboard_user_idseligible_pk_usersnew_world_usersrh   added_users_countparadise_usersrg   ri   rj   r:   s                   @rr   r   r   7  s    02H $&}'+K  U4F$NOOWYY(
 (
 	  !<!>!>??? 	  !D!F!FGGG )85(A(A#%'""%9%K" }37;tw3G3G3M3MNd"4
 4
%% 48;tw3G3G3M3MGKK2244554
 4
%% % :% % % #'	 $7$9$9$??;==?}%' w{{899; w~~/00	2
 {Q 

 

 
$+""$$	%	%# #O    $$$0ET8_-H1 1 $$%5666MHE %  	 	EEEE 1EEEEE 	0ET8_-D1 1 $$%5666MH" A%%  	 	EEEE 1EEEEE 	0ET8_-G1 1 $$%5666MH" A%% "&	 $5$7$7$==;==?}%' w{{899; w~~/00	2
 {Q 

 

 
$+""$$	%	%" "N  	 	EEEE 1EEEEE 	0ET8_-F1 1 $$%5666MH" B&& }'(J(L(LMM 	7 	7NE70EW\519o6M1 1 $$%56666'01[1]1]'^'^ 
	7 
	7#E##(2 0E %	0	1 1 $$%56666  ' }rt   c                    g }t          j                                        t           j        dk    t           j        dk    z                                t           j                                        t           j                                                  	                    t          j                                                  }t          |          D ]\  }}t                      }| |_        ||_        |                                |_        |dz   |_        |j        |_        |j        |_        |                                 |                    |           |S )z
    Creates a leaderboard list
    :param leaderboard: The leaderboard to create the crews for
    :return: The leaderboard crews
    Tr-   )r	   r   r   r   allow_view_in_searchr   r   r   total_gained_chest_amountlimitrN   LEADERBOARD_CREW_LIMITr   r8   r   r$   rX   get_captainrZ   rF   total_chest_amountr   r   )r$   rV   crewsrg   rX   rq   s         rr   r   r     s%    02 		$&4+D+LM	N	N	$*//##T%C%H%H%J%J	K	K	s)1133	4	4	 
 !'' 
3 
3t,;,=,='2$ $#'#3#3#5#5 $)AI!!%.2.L+  !12222rt   r:   rF   rankc                     t                      }| |_        ||_        ||_        |j        |_        |j        |_        |                                 |S )z
    Saves a leaderboard user
    :param leaderboard: The leaderboard
    :param user: The user
    :param position: The position
    :param rank: The rank
    )r   r$   r:   rF   rg   r;   r   r   )r$   r:   rF   r   rh   s        rr   r   r     sY     '((#.   ("&*"krt   
group_chatc                    ||j         }t          j                                        t          j         |k                                  t          j                                        t          j                                                                      d          	                    |           
                                }|S )a  
    Gets the current leaderboard
    :param index: The index of the leaderboard to get. Higher the index, older the leaderboard.
    :param group: The group to get the leaderboard for
    :param group_chat: The group chat to get the leaderboard for
    :return: The leaderboard
    Nr-   )r7   r   r   r   r   r_   r   r^   r   offsetfirst)rg   r7   r   r$   s       rr   r   r     s       		{ E)	*	*	+"''));+;+@+@+B+B	C	C	q		  rt   c                     t          ||          }||t          |          }|dS |j                            t          j        | k                                              }|S )a1  
    Gets the leaderboard user for the user
    :param user: The user to get the leaderboard user for
    :param index: The index of the leaderboard to get. Higher the index, older the leaderboard
    :param group_chat: The group chat to get the leaderboard user for
    :return: The leaderboard user
    r   N)r   r9   r   r   r:   r   )r:   rg   r   r$   rh   s        rr   get_leaderboard_userr     sp     "%J???Kz5%e,,t(3(E(K(K$) )egg  rt   c                 &    t          | d|          S )z
    Gets the current leaderboard user for the user
    :param user: The user to get the leaderboard user for
    :param group_chat: The group chat to get the leaderboard user for
    :return: The leaderboard user
    r   )rg   r   )r   )r:   r   s     rr   get_current_leaderboard_userr   6  s      A*EEEErt   c                 L    t          | |          }t          j        |          S )z
    Gets the current leaderboard rank for the user
    :param user: The user to get the leaderboard rank for
    :param group_chat: The group chat to get the leaderboard rank for
    :return: The leaderboard rank
    r   )r   r   get_rank_by_leaderboard_user)r:   r   rh   s      rr   get_current_leaderboard_rankr   C  s+     )ETV`(a(a(a78HIIIrt   c                 *   t          |           }|dS |j        t          j        k    o|                                  }|j        t          j        k    o|                                  }|s|r't          j        |_        |                                 dS dS )a  
    A Warlord or Legendary Pirate who appears in the (global) leaderboard with their special
    rank, and later loses that status (duration expiring or being manually revoked), would
    otherwise keep showing that rank until the next leaderboard is generated and overwrites it.
    This checks the user's current global leaderboard entry and, if it's stale, immediately
    resets it to Rookie instead of waiting for the next leaderboard
    :param user: The user to check
    :return: None
    N)	r   r;   r   r<   
is_warlordrC   is_legendary_pirateROOKIEr   )r:   rh   lost_warlord_statuslost_legendary_pirate_statuss       rr   #reset_expired_special_rank_for_userr   Q  s     )ET(J(J 	#';'CC]DOOL]L]H]  	#';'LL 	+((*** !
   :  &:&A#   rt   c                 d   K   t          j        | j        j                  }t	          |           dS )a  
    Job callback, scheduled to run at the exact moment a Warlord/Legendary Pirate's duration
    ends, that resets their leaderboard rank if it's gone stale
    :param context: Telegram context, contains the target user's id in job.data
    :return: None
    N)r   	get_by_idjobdatar   )ru   r:   s     rr   job_reset_expired_special_rankr  m  s0        011D'-----rt   	job_queueend_datec           
         t          |t          j                                        z
                                  d          }|                     t
          ||j        d|j         d|                                            dS )a  
    Schedules a one-off job to reset the user's leaderboard rank at the exact moment their
    Warlord/Legendary Pirate duration ends, rather than only catching it on the next leaderboard.
    Computed as a delay relative to now (rather than as an absolute datetime) so it lines up
    with however the bot's own clock already evaluates "is this user still a Warlord/Legendary
    Pirate", regardless of timezone configuration
    :param job_queue: The job queue to schedule the job on
    :param user: The user whose rank should be reset once their special status expires
    :param end_date: The datetime the user's special status ends
    :return: None
    r   reset_special_rank__)whenr   nameN)maxr   r   total_secondsrun_oncer  rB   	timestamp)r  r:   r  delay_secondss       rr    schedule_special_rank_expiry_jobr  y  s     H$5$9$9$;$;;JJLLaPPM&WC47CCX-?-?-A-ACC	      rt   c                    K   t          j                    D ]"}t          | j        |j        |j                   #t          j                    D ])}|j         t          | j        |j        |j                   *dS )a  
    On startup, (re)schedules the expiry job for every currently active Warlord/Legendary Pirate
    with a set end date. Needed because one-off jobs scheduled via schedule_special_rank_expiry_job
    live only in memory and are lost on every restart, so this re-creates them for any
    appointment that's still active and hasn't expired yet
    :param application: The bot application, used to access the job queue
    :return: None
    N)r   
get_activer  r  r:   r  r   )r   ri   rj   s      rr   )schedule_pending_special_rank_expiry_jobsr    s       %'' ` `()>gN^____+688  $0,%'7'<>N>W   rt   c                     t          | |          }t          j        |          }t          j        |           }||                    |          r|S |S )a  
    Get the highest active rank for a given user
    If the user has a special rank, the special rank is returned if it's higher than the user's
    leaderboard rank
    :param user: User
    :param group_chat: Group chat
    :return: Leaderboard rank
    r   )r   r   r   get_special_rank	is_higher)r:   r   rh   r   special_ranks        rr   get_highest_active_rankr    si     )ETV`(a(a(a )8(T) )
 %4$DT$J$JL/99,GGrt   c                  X    t          t          j                                                  S )z
    Gets the remaining time to the next leaderboard description
    :return: The remaining time to the next leaderboard description
    )r   rN   r   rP   r   rt   rr   &get_remaining_time_to_next_leaderboardr    s!     -S-F-J-J-L-LMMMrt   r   )NN)r   NN)r&   N)Ur   r   src.tg_compatr   src.tg_compat.errorr   src.tg_compat.extr   r   src.model.enums.LeaderboardRankmodelenumsr   	resourcesr   r   rN   src.model.Crewr	   src.model.Groupr
   src.model.GroupChatr   src.model.Leaderboardr   src.model.LeaderboardCrewr   src.model.LeaderboardUserr   src.model.LegendaryPirater   src.model.Userr   src.model.Warlordr   src.model.enums.Featurer   r   src.model.enums.Locationr   r   !src.service.bounty_poster_servicer   src.service.language_servicer   src.service.crew_servicer   r4   r   r   r   src.service.devil_fruit_servicer   r   src.service.group_servicer   r   src.service.message_servicer    r!   r"   r#   intstrrs   DEFAULT_TYPEr   boolr   r   rG   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r   rt   rr   <module>r5     s     ! ! ! ! ! ! - - - - - - 4 4 4 4 4 4 4 4 9 9 9 9 9 9 9 9 9 9 9 9 < < < < < < < <       ! ! ! ! ! ! ) ) ) ) ) ) - - - - - - 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5       % % % % % % + + + + + + @ @ @ @ @ @ K K K K K K K K G G G G G G = = = = = = ; ; ; ; ; ;         
                          DHa aa=@aa a a aH*YL$= *Y$ *Y *Y *Y *YZ
l&? 
RV 
[_ 
 
 
 
0 &*	V VVV V $	V
 4V V V Vr9 9 9 9 9 9V!V!%*T\V!	/V! V! V! V!r+ $:O    @$(47?N?^   , BF  5>4   4 <@ 
/8t   2 )-
F 
F

F%
Ft
F 
F 
F 
F )-J J
J%J$J J J J d  t        8	.,2K 	.PT 	. 	. 	. 	.#/7/@	   0   ($ I /    4N N N N N N Nrt   