
    soj,                     "   d dl Z d dl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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e
j        dedeez  dedededdfdZde
j        dedeez  dedededdfdZde
j        dedeez  dedededdfdZde
j        dedeez  dedededdfdZdZdedefdZ de
j        deez  deez  dededz  de!edz  ef         fdZ"de
j        deez  dedefdZ#de
j        dedededededed eddfd!Z$dS )"    N)Message)	Forbidden
BadRequestTelegramError
RetryAfter)ContextTypes)phrases)Group)	GroupChat)User)save_group_chat_error)full_message_sendcontextownerfrom_chat_id
message_id
should_pinprogress_message_idreturnc           
      b   K   | j                             t          | |||||                     dS )a  
    Dispatches the group broadcast (gcast) to a background task
    :param context: The context
    :param owner: The owner, used to send the final report
    :param from_chat_id: The chat id of the message to broadcast
    :param message_id: The id of the message to broadcast
    :param should_pin: True if the broadcast message should be pinned
    :param progress_message_id: The id of the progress message to edit with the final report
    :return: None
    N)applicationcreate_taskbroadcast_to_groupsr   r   r   r   r   r   s         %/app/src/service/broadcast_service.pybroadcast_to_groups_dispatchr      sH      & ##UL*jBU	
 	
        c                   K   d}d}d}d}	d}
t          j                                        t           j        dk              }|                                D ]}t          |j                  }|D ]}|dz  }t          | |j        |||j	                   d{V \  }}|:|dz  }t          |d           |r"|j        rd|_        |                                 i|dz  }|sqt          | |j        |j                   d{V r|	dz  }	|
dz  }
t          |d           t          | ||t          j        t          j                            |||          ||	|
           d{V  dS )a  
    Broadcasts a message to every group/topic the Bot is an active member of
    :param context: The context
    :param owner: The owner, used to send the final report
    :param from_chat_id: The chat id of the message to broadcast
    :param message_id: The id of the message to broadcast
    :param should_pin: True if the broadcast message should be pinned
    :param progress_message_id: The id of the progress message to edit with the final report
    :return: None
    r   T   Nz#Failed to broadcast message (gcast)Fz'Failed to pin broadcast message (gcast))r
   selectwhere	is_activeiteratorlistgroup_chats_copy_messagetg_group_idtg_topic_idr   save_pin_messager   _send_final_reportr	   BROADCAST_GROUPS_COMPLETEDBROADCAST_GROUPS_STATISTICSformat)r   r   r   r   r   r   total
successfulfailedpinned
pin_failedgroupsgroupr%   
group_chatcopied_messageis_permanent_failures                    r   r   r   *   s     & EJFFJ,....u$/FGGF"" ] ]'+E,='>'>% 	] 	]JQJE9F*L*jF\: : 4 4 4 4 4 40N0 %!%j2WXXX' !EO ! ',EOJJLLL!OJ !'5+<n>WXXXXXXXX ]!a
%j2[\\\\7	]: *+225*fMM	 	 	 	 	 	 	 	 	 	 	r   c           
      b   K   | j                             t          | |||||                     dS )a  
    Dispatches the player broadcast (pcast) to a background task
    :param context: The context
    :param owner: The owner, used to send the final report
    :param from_chat_id: The chat id of the message to broadcast
    :param message_id: The id of the message to broadcast
    :param should_pin: True if the broadcast message should be pinned
    :param progress_message_id: The id of the progress message to edit with the final report
    :return: None
    N)r   r   broadcast_to_playersr   s         r   broadcast_to_players_dispatchr;   p   sH      & ##UL*jBU	
 	
    r   c                 J  K   d}d}d}d}	d}
t          j                                        t           j        dk              }|                                D ]}|dz  }t          | |j        ||d           d{V \  }}|*|dz  }|r"|j        rd|_        |                                 T|dz  }|s\t          | |j        |j	                   d{V r|	dz  }	|
dz  }
t          | ||t          j        t          j                            |||          ||	|
           d{V  dS )a  
    Broadcasts a message to every registered player's private chat
    :param context: The context
    :param owner: The owner, used to send the final report
    :param from_chat_id: The chat id of the message to broadcast
    :param message_id: The id of the message to broadcast
    :param should_pin: True if the broadcast message should be pinned
    :param progress_message_id: The id of the progress message to edit with the final report
    :return: None
    r   Tr   NF)r   r    r!   r"   r#   r&   
tg_user_idr)   r*   r   r+   r	   BROADCAST_PLAYERS_COMPLETEDBROADCAST_PLAYERS_STATISTICSr.   )r   r   r   r   r   r   r/   r0   r1   r2   r3   playersplayerr7   r8   s                  r   r:   r:      s     & EJFFJ+----dn.DEEG""$$  
5BV&j$6
 6
 0
 0
 0
 0
 0
 0
,, !aKF# (8  $) a
 	gv'8.:STTTTTTTT 	aKFF!OJJ
+,33E:vNN	 	 	 	 	 	 	 	 	 	 	r   )zchat not foundzuser not foundzuser is deactivatedpeer_id_invaliderrorc                      t           t                    rdS t           t                    r"t           fdt          D                       rdS dS )az  
    Determines whether an error means the destination is permanently unreachable (Bot kicked/
    blocked, group or account deleted), as opposed to a transient error that might succeed if
    retried in a future broadcast.
    :param error: The error raised while broadcasting to a destination
    :return: True if the destination should be excluded from future broadcasts
    Tc              3   ^   K   | ]'}|t                                                    v V  (d S )N)strlower).0snippetrC   s     r   	<genexpr>z(_is_permanent_failure.<locals>.<genexpr>   sK       - -*13u::##%%%- - - - - -r   F)
isinstancer   r   any_PERMANENT_BAD_REQUEST_SNIPPETS)rC   s   `r   _is_permanent_failurerN      sq     %## t%$$  - - - -5T- - - * *  t5r   chat_idmessage_thread_idc                   K   t          d          D ]}	 | j                            ||||d           d{V }|dfc S # t          $ rh}|dk    r<t	          j        d| d           t          j        |j                   d{V  Y d}~zt	          j        d	| d
|            Y d}~ dS d}~wt          $ r}dt          |          fcY d}~c S d}~ww xY wdS )a  
    Copies a message to a chat, using Telegram's native copyMessage so the broadcast doesn't
    show a "Forwarded from" tag and preserves formatting/media/keyboards as-is.
    Retries once if rate limited, since a failure to broadcast to one destination must not stop
    the rest of the broadcast.
    :param context: The context
    :param chat_id: The destination chat id
    :param from_chat_id: The chat id of the message to copy
    :param message_id: The id of the message to copy
    :param message_thread_id: The forum topic id, if any
    :return: A tuple of (the copied message, or None if it could not be sent) and (True if the
    destination is permanently unreachable and should be excluded from future broadcasts)
       T)rO   r   r   rP   disable_notificationNFr   z#Rate limited while broadcasting to z
, retryingzFailed to broadcast to  after retrying: )NF)rangebotcopy_messager   loggingwarningasynciosleepretry_afterr   rN   )	r   rO   r   r   rP   attemptmessagerates	            r   r&   r&      sg     * 88 3 3	3#K44)%"3%) 5        G E>!!! 	 	 	!|| Yg Y Y YZZZmBN333333333OTgTTPRTTUUU;;;;;; 	3 	3 	3.r22222222222	3 ;s/   (A  
C
=B-B--C:C
CCc                   K   t          d          D ]}	 | j                            ||d           d{V   dS # t          $ rP}|dk    r$t	          j        |j                   d{V  Y d}~]t          j        d| d|            Y d}~ dS d}~wt          $ r&}t          j        d| d	|            Y d}~ dS d}~ww xY wdS )
a  
    Pins a message in a chat. Retries once if rate limited.
    A failure to pin must not interrupt the broadcast.
    :param context: The context
    :param chat_id: The chat id
    :param message_id: The id of the message to pin
    :return: True if the message was pinned
    rR   T)rO   r   rS   Nr   z#Failed to pin broadcast message in rT   Fz: )
rU   rV   pin_chat_messager   rZ   r[   r\   rX   rY   r   )r   rO   r   r]   r_   r`   s         r   r*   r*     sD      88  	+..JT /          44 	 	 	!||mBN333333333O`'``\^``aaa555555 	 	 	OQ'QQRQQRRR555555	 5s'   #;
C%B/BCB>>Ccompleted_phrasestatistics_textr2   r3   c                    K   |r t           j                            ||          nd}t          | |                    ||          |j        |           d{V  dS )a2  
    Edits the progress message with the final broadcast report
    :param context: The context
    :param owner: The owner
    :param progress_message_id: The id of the progress message to edit
    :param completed_phrase: The completed phrase template, expecting statistics and pin stats
    :param statistics_text: The broadcast statistics text
    :param should_pin: True if pin statistics should be included
    :param pinned: The number of successfully pinned messages
    :param pin_failed: The number of messages that failed to pin
    :return: None
     )rO   edit_message_idN)r	   BROADCAST_PIN_STATISTICSr.   r   r=   )	r   r   r   rc   rd   r   r2   r3   pin_statistics_texts	            r   r+   r+   5  s      0 HRY(//
CCCWY  1DEE +	           r   )%rZ   rX   src.tg_compatr   src.tg_compat.errorr   r   r   r   src.tg_compat.extr   	resourcesr	   src.model.Groupr
   src.model.GroupChatr   src.model.Userr   src.service.group_servicer   src.service.message_servicer   DEFAULT_TYPEintrF   boolr   r   r;   r:   rM   rN   tupler&   r*   r+    r   r   <module>rx      s     ! ! ! ! ! ! P P P P P P P P P P P P * * * * * *       ! ! ! ! ! ! ) ) ) ) ) )       ; ; ; ; ; ; 9 9 9 9 9 9& ) 	
   
   4C&CC )C 	C
 C C 
C C C CL& ) 	
   
   4>&>> )> 	>
 > > 
> > > >F#  4    *)&)3Y) )) 	)
 Tz) 7T>4 ) ) ) )X&14sHK	   > &     	 
         
           r   