diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl index cadf0bbb..e3197d70 100644 --- a/compiler/api/source/main_api.tl +++ b/compiler/api/source/main_api.tl @@ -108,7 +108,7 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus; chatEmpty#29562865 id:long = Chat; chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat; chatForbidden#6592a1a7 id:long title:string = Chat; -channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat; +channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull; @@ -193,9 +193,10 @@ messageActionPaymentRefunded#41b3e202 flags:# peer:Peer currency:string total_am messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long crypto_currency:flags.0?string crypto_amount:flags.0?long transaction_id:flags.1?string = MessageAction; messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction; messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction; -messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction; +messageActionStarGiftUnique#2e3ae60e flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_stars:flags.8?long can_transfer_at:flags.9?int can_resell_at:flags.10?int = MessageAction; messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction; messageActionPaidMessagesPrice#bcd71419 stars:long = MessageAction; +messageActionConferenceCall#2ffe2f7a flags:# missed:flags.0?true active:flags.1?true video:flags.4?true call_id:long duration:flags.2?int other_participants:flags.3?Vector = MessageAction; dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog; dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; @@ -440,6 +441,7 @@ updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update; updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update; updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update; updateSentPhoneCode#504aa18f sent_code:auth.SentCode = Update; +updateGroupCallChainBlocks#a477288f call:InputGroupCall sub_chain_id:int blocks:Vector next_offset:int = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -614,7 +616,7 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess webPageEmpty#211a1788 flags:# id:long url:flags.0?string = WebPage; webPagePending#b0d13e47 flags:# id:long url:flags.0?string date:int = WebPage; -webPage#e89c45b2 flags:# has_large_media:flags.13?true id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector = WebPage; +webPage#e89c45b2 flags:# has_large_media:flags.13?true video_cover_photo:flags.14?true id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector = WebPage; webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage; authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true unconfirmed:flags.5?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization; @@ -910,7 +912,7 @@ phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason; phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason; phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason; phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason; -phoneCallDiscardReasonAllowGroupCall#afe2b839 encrypted_key:bytes = PhoneCallDiscardReason; +phoneCallDiscardReasonMigrateConferenceCall#9fbbf1f7 slug:string = PhoneCallDiscardReason; dataJSON#7d748d04 data:string = DataJSON; @@ -965,11 +967,11 @@ inputStickerSetItem#32da9e9c flags:# document:InputDocument emoji:string mask_co inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall; phoneCallEmpty#5366c915 id:long = PhoneCall; -phoneCallWaiting#eed42858 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long protocol:PhoneCallProtocol receive_date:flags.0?int conference_call:flags.8?InputGroupCall = PhoneCall; -phoneCallRequested#45361c63 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_hash:bytes protocol:PhoneCallProtocol conference_call:flags.8?InputGroupCall = PhoneCall; -phoneCallAccepted#22fd7181 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_b:bytes protocol:PhoneCallProtocol conference_call:flags.8?InputGroupCall = PhoneCall; -phoneCall#3ba5940c flags:# p2p_allowed:flags.5?true video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector start_date:int custom_parameters:flags.7?DataJSON conference_call:flags.8?InputGroupCall = PhoneCall; -phoneCallDiscarded#f9d25503 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.6?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int conference_call:flags.8?InputGroupCall = PhoneCall; +phoneCallWaiting#c5226f17 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall; +phoneCallRequested#14b0ed0c flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall; +phoneCallAccepted#3660c311 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_b:bytes protocol:PhoneCallProtocol = PhoneCall; +phoneCall#30535af5 flags:# p2p_allowed:flags.5?true video:flags.6?true conference_supported:flags.8?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector start_date:int custom_parameters:flags.7?DataJSON = PhoneCall; +phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.6?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall; phoneConnection#9cc123c7 flags:# tcp:flags.0?true id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection; phoneConnectionWebrtc#635fe375 flags:# turn:flags.0?true stun:flags.1?true id:long ip:string ipv6:string port:int username:string password:string = PhoneConnection; @@ -1043,6 +1045,7 @@ channelAdminLogEventActionChangeEmojiStatus#3ea9feb1 prev_value:EmojiStatus new_ channelAdminLogEventActionChangeEmojiStickerSet#46d840ab prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction; channelAdminLogEventActionToggleSignatureProfiles#60a79c79 new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionParticipantSubExtend#64642db3 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction; +channelAdminLogEventActionToggleAutotranslation#c517f77e new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent; @@ -1310,7 +1313,7 @@ statsGraph#8ea464b6 flags:# json:DataJSON zoom_token:flags.0?string = StatsGraph stats.broadcastStats#396ca5fc period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev reactions_per_post:StatsAbsValueAndPrev views_per_story:StatsAbsValueAndPrev shares_per_story:StatsAbsValueAndPrev reactions_per_story:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph reactions_by_emotion_graph:StatsGraph story_interactions_graph:StatsGraph story_reactions_by_emotion_graph:StatsGraph recent_posts_interactions:Vector = stats.BroadcastStats; help.promoDataEmpty#98f6ac75 expires:int = help.PromoData; -help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector users:Vector psa_type:flags.1?string psa_message:flags.2?string = help.PromoData; +help.promoData#8a4d87a flags:# proxy:flags.0?true expires:int peer:flags.3?Peer psa_type:flags.1?string psa_message:flags.2?string pending_suggestions:Vector dismissed_suggestions:Vector custom_pending_suggestion:flags.4?PendingSuggestion chats:Vector users:Vector = help.PromoData; videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize; videoSizeEmojiMarkup#f85c413c emoji_id:long background_colors:Vector = VideoSize; @@ -1349,9 +1352,11 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked; stats.messageStats#7fe91c14 views_graph:StatsGraph reactions_by_emotion_graph:StatsGraph = stats.MessageStats; groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall; -groupCall#cdf8d3e3 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true rtmp_stream:flags.12?true listeners_hidden:flags.13?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int conference_from_call:flags.14?long = GroupCall; +groupCall#553b0ba1 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true rtmp_stream:flags.12?true listeners_hidden:flags.13?true conference:flags.14?true creator:flags.15?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int invite_link:flags.16?string = GroupCall; inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall; +inputGroupCallSlug#fe06823f slug:string = InputGroupCall; +inputGroupCallInviteMessage#8c10603f msg_id:int = InputGroupCall; groupCallParticipant#eba636fe flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true video_joined:flags.15?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long video:flags.6?GroupCallParticipantVideo presentation:flags.14?GroupCallParticipantVideo = GroupCallParticipant; @@ -1492,7 +1497,10 @@ inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice; inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice; inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:flags.2?true peer:InputPeer gift_id:long message:flags.1?TextWithEntities = InputInvoice; inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice; +inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice; inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice; +inputInvoiceBusinessBotTransferStars#f4997e42 bot:InputUser stars:long = InputInvoice; +inputInvoiceStarGiftResale#63cbc38c slug:string to_id:InputPeer = InputInvoice; payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice; @@ -1852,7 +1860,7 @@ starsTransactionPeerAPI#f9677aad = StarsTransactionPeer; starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption; -starsTransaction#a39fd94a flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true stargift_upgrade:flags.18?true id:string stars:StarsAmount date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int starref_commission_permille:flags.16?int starref_peer:flags.17?Peer starref_amount:flags.17?StarsAmount paid_messages:flags.19?int premium_gift_months:flags.20?int = StarsTransaction; +starsTransaction#a39fd94a flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true stargift_upgrade:flags.18?true business_transfer:flags.21?true stargift_resale:flags.22?true id:string stars:StarsAmount date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int starref_commission_permille:flags.16?int starref_peer:flags.17?Peer starref_amount:flags.17?StarsAmount paid_messages:flags.19?int premium_gift_months:flags.20?int = StarsTransaction; payments.starsStatus#6c9ce8ed flags:# balance:StarsAmount subscriptions:flags.1?Vector subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector next_offset:flags.0?string chats:Vector users:Vector = payments.StarsStatus; @@ -1890,8 +1898,8 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption; -starGift#2cc73c8 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long = StarGift; -starGiftUnique#5c62d151 flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector availability_issued:int availability_total:int gift_address:flags.3?string = StarGift; +starGift#c62aca28 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string = StarGift; +starGiftUnique#6411db89 flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long = StarGift; payments.starGiftsNotModified#a388a368 = payments.StarGifts; payments.starGifts#901689ea hash:int gifts:Vector = payments.StarGifts; @@ -1927,7 +1935,7 @@ botVerification#f93cd45c bot_id:long icon:long description:string = BotVerificat starGiftAttributeModel#39d99013 name:string document:Document rarity_permille:int = StarGiftAttribute; starGiftAttributePattern#13acff19 name:string document:Document rarity_permille:int = StarGiftAttribute; -starGiftAttributeBackdrop#94271762 name:string center_color:int edge_color:int pattern_color:int text_color:int rarity_permille:int = StarGiftAttribute; +starGiftAttributeBackdrop#d93d859c name:string backdrop_id:int center_color:int edge_color:int pattern_color:int text_color:int rarity_permille:int = StarGiftAttribute; starGiftAttributeOriginalDetails#e0bff26c flags:# sender_id:flags.0?Peer recipient_id:Peer date:int message:flags.1?TextWithEntities = StarGiftAttribute; payments.starGiftUpgradePreview#167bd90b sample_attributes:Vector = payments.StarGiftUpgradePreview; @@ -1939,12 +1947,13 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector = payments.Uni messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector = messages.WebPagePreview; -savedStarGift#6056dba5 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = SavedStarGift; +savedStarGift#dfda0499 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int = SavedStarGift; payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector next_offset:flags.0?string chats:Vector users:Vector = payments.SavedStarGifts; inputSavedStarGiftUser#69279795 msg_id:int = InputSavedStarGift; inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGift; +inputSavedStarGiftSlug#2085c238 slug:string = InputSavedStarGift; payments.starGiftWithdrawalUrl#84aa3a9c url:string = payments.StarGiftWithdrawalUrl; @@ -1967,6 +1976,18 @@ sponsoredPeer#c69708d3 flags:# random_id:bytes peer:Peer sponsor_info:flags.0?st contacts.sponsoredPeersEmpty#ea32b4b1 = contacts.SponsoredPeers; contacts.sponsoredPeers#eb032884 peers:Vector chats:Vector users:Vector = contacts.SponsoredPeers; +starGiftAttributeIdModel#48aaae3c document_id:long = StarGiftAttributeId; +starGiftAttributeIdPattern#4a162433 document_id:long = StarGiftAttributeId; +starGiftAttributeIdBackdrop#1f01c757 backdrop_id:int = StarGiftAttributeId; + +starGiftAttributeCounter#2eb1b658 attribute:StarGiftAttributeId count:int = StarGiftAttributeCounter; + +payments.resaleStarGifts#947a12df flags:# count:int gifts:Vector next_offset:flags.0?string attributes:flags.1?Vector attributes_hash:flags.1?long chats:Vector counters:flags.2?Vector users:Vector = payments.ResaleStarGifts; + +stories.canSendStoryCount#c387c04e count_remains:int = stories.CanSendStoryCount; + +pendingSuggestion#e7e82e12 suggestion:string title:TextWithEntities description:TextWithEntities url:string = PendingSuggestion; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -2487,6 +2508,7 @@ channels.setEmojiStickers#3cd930b7 channel:InputChannel stickerset:InputStickerS channels.restrictSponsoredMessages#9ae91519 channel:InputChannel restricted:Bool = Updates; channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; channels.updatePaidMessagesPrice#fc84653f channel:InputChannel send_paid_messages_stars:long = Updates; +channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates; bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON; bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool; @@ -2567,6 +2589,8 @@ payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password: payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool; payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector = Bool; payments.canPurchaseStore#4fdc5ea7 purpose:InputStorePaymentPurpose = Bool; +payments.getResaleStarGifts#7a5fa236 flags:# sort_by_price:flags.1?true sort_by_num:flags.2?true attributes_hash:flags.0?long gift_id:long attributes:flags.3?Vector offset:string limit:int = payments.ResaleStarGifts; +payments.updateStarGiftPrice#3baea4e1 stargift:InputSavedStarGift resell_stars:long = Updates; stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet; @@ -2581,7 +2605,7 @@ stickers.deleteStickerSet#87704394 stickerset:InputStickerSet = Bool; stickers.replaceSticker#4696459a sticker:InputDocument new_sticker:InputStickerSetItem = messages.StickerSet; phone.getCallConfig#55451fa9 = DataJSON; -phone.requestCall#a6c4600c flags:# video:flags.0?true user_id:InputUser conference_call:flags.1?InputGroupCall random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall; +phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall; phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall; phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall; phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool; @@ -2590,7 +2614,7 @@ phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhon phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool; phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool; phone.createGroupCall#48cdc6d8 flags:# rtmp_stream:flags.2?true peer:InputPeer random_id:int title:flags.0?string schedule_date:flags.1?int = Updates; -phone.joinGroupCall#d61e1df3 flags:# muted:flags.0?true video_stopped:flags.2?true call:InputGroupCall join_as:InputPeer invite_hash:flags.1?string key_fingerprint:flags.3?long params:DataJSON = Updates; +phone.joinGroupCall#8fb53057 flags:# muted:flags.0?true video_stopped:flags.2?true call:InputGroupCall join_as:InputPeer invite_hash:flags.1?string public_key:flags.3?int256 block:flags.3?bytes params:DataJSON = Updates; phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates; phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector = Updates; phone.discardGroupCall#7a777135 call:InputGroupCall = Updates; @@ -2611,7 +2635,12 @@ phone.leaveGroupCallPresentation#1c50d144 call:InputGroupCall = Updates; phone.getGroupCallStreamChannels#1ab21940 call:InputGroupCall = phone.GroupCallStreamChannels; phone.getGroupCallStreamRtmpUrl#deb3abbf peer:InputPeer revoke:Bool = phone.GroupCallStreamRtmpUrl; phone.saveCallLog#41248786 peer:InputPhoneCall file:InputFile = Bool; -phone.createConferenceCall#dfc909ab peer:InputPhoneCall key_fingerprint:long = phone.PhoneCall; +phone.createConferenceCall#7d0444bb flags:# muted:flags.0?true video_stopped:flags.2?true join:flags.3?true random_id:int public_key:flags.3?int256 block:flags.3?bytes params:flags.3?DataJSON = Updates; +phone.deleteConferenceCallParticipants#8ca60525 flags:# only_left:flags.0?true kick:flags.1?true call:InputGroupCall ids:Vector block:bytes = Updates; +phone.sendConferenceCallBroadcast#c6701900 call:InputGroupCall block:bytes = Updates; +phone.inviteConferenceCallParticipant#bcf22685 flags:# video:flags.0?true call:InputGroupCall user_id:InputUser = Updates; +phone.declineConferenceCallInvite#3c479971 msg_id:int = Updates; +phone.getGroupCallChainBlocks#ee9f88a6 call:InputGroupCall sub_chain_id:int offset:int limit:int = Updates; langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference; langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector = Vector; @@ -2644,7 +2673,7 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool; chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector; chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector = Updates; -stories.canSendStory#c7dfdfdd peer:InputPeer = Bool; +stories.canSendStory#30eb63f0 peer:InputPeer = stories.CanSendStoryCount; stories.sendStory#e4e6694b flags:# pinned:flags.2?true noforwards:flags.4?true fwd_modified:flags.7?true peer:InputPeer media:InputMedia media_areas:flags.5?Vector caption:flags.0?string entities:flags.1?Vector privacy_rules:Vector random_id:long period:flags.3?int fwd_from_id:flags.6?InputPeer fwd_from_story:flags.6?int = Updates; stories.editStory#b583ba46 flags:# peer:InputPeer id:int media:flags.0?InputMedia media_areas:flags.3?Vector caption:flags.1?string entities:flags.1?Vector privacy_rules:flags.2?Vector = Updates; stories.deleteStories#ae59db5f peer:InputPeer id:Vector = Vector; @@ -2687,4 +2716,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 201 +// LAYER 203 diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 97ba8a35..53bd71cf 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -409,6 +409,7 @@ def pyrogram_api(): Telegram Business answer_pre_checkout_query answer_shipping_query + delete_business_messages get_business_connection """, authorization=""" @@ -421,6 +422,7 @@ def pyrogram_api(): resend_code sign_in sign_in_bot + sign_in_qrcode sign_up get_password_hint check_password @@ -724,6 +726,7 @@ def pyrogram_api(): Authorization ActiveSession ActiveSessions + LoginToken SentCode TermsOfService """ diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index bf40b223..cbacb2c0 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -18,7 +18,7 @@ # along with Pyrofork. If not, see . __fork_name__ = "PyroFork" -__version__ = "2.3.61" +__version__ = "2.3.62" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __copyright__ = "Copyright (C) 2022-present Mayuri-Chan " diff --git a/pyrogram/client.py b/pyrogram/client.py index edf1c68d..e800969d 100644 --- a/pyrogram/client.py +++ b/pyrogram/client.py @@ -130,6 +130,9 @@ class Client(Methods): Pass a session string to load the session in-memory. Implies ``in_memory=True``. + use_qrcode (``bool``, *optional*): + Pass True to login using a QR code. + in_memory (``bool``, *optional*): Pass True to start an in-memory session that will be discarded as soon as the client stops. In order to reconnect again using an in-memory session without having to login again, you can use @@ -254,6 +257,7 @@ class Client(Methods): test_mode: Optional[bool] = False, bot_token: Optional[str] = None, session_string: Optional[str] = None, + use_qrcode: Optional[bool] = False, in_memory: Optional[bool] = None, mongodb: Optional[dict] = None, storage: Optional[Storage] = None, @@ -289,6 +293,7 @@ class Client(Methods): self.test_mode = test_mode self.bot_token = bot_token self.session_string = session_string + self.use_qrcode = use_qrcode self.in_memory = in_memory self.mongodb = mongodb self.phone_number = phone_number @@ -397,6 +402,15 @@ class Client(Methods): if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL): await self.invoke(raw.functions.updates.GetState()) + async def _wait_for_update_login_token(self): + """ + Wait for an UpdateLoginToken update from Telegram. + """ + while True: + update, _, _ = await self.dispatcher.updates_queue.get() + if isinstance(update, raw.types.UpdateLoginToken): + break + async def authorize(self) -> User: if self.bot_token: return await self.sign_in_bot(self.bot_token) @@ -404,52 +418,60 @@ class Client(Methods): print(f"Welcome to Pyrogram (version {__version__})") print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n" f"under the terms of the {__license__}.\n") + if not self.use_qrcode: + while True: + try: + if not self.phone_number: + while True: + print("Enter 'qrcode' if you want to login with qrcode.") + value = await ainput("Enter phone number or bot token: ") + + if not value: + continue + + if value.lower() == "qrcode": + self.use_qrcode = True + break + + confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower() + + if confirm == "y": + break + + if ":" in value: + self.bot_token = value + return await self.sign_in_bot(value) + else: + self.phone_number = value + + sent_code = await self.send_code(self.phone_number) + except BadRequest as e: + print(e.MESSAGE) + self.phone_number = None + self.bot_token = None + else: + break + + sent_code_descriptions = { + enums.SentCodeType.APP: "Telegram app", + enums.SentCodeType.SMS: "SMS", + enums.SentCodeType.CALL: "phone call", + enums.SentCodeType.FLASH_CALL: "phone flash call", + enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS", + enums.SentCodeType.EMAIL_CODE: "email code" + } + + print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}") while True: - try: - if not self.phone_number: - while True: - value = await ainput("Enter phone number or bot token: ") - - if not value: - continue - - confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower() - - if confirm == "y": - break - - if ":" in value: - self.bot_token = value - return await self.sign_in_bot(value) - else: - self.phone_number = value - - sent_code = await self.send_code(self.phone_number) - except BadRequest as e: - print(e.MESSAGE) - self.phone_number = None - self.bot_token = None - else: - break - - sent_code_descriptions = { - enums.SentCodeType.APP: "Telegram app", - enums.SentCodeType.SMS: "SMS", - enums.SentCodeType.CALL: "phone call", - enums.SentCodeType.FLASH_CALL: "phone flash call", - enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS", - enums.SentCodeType.EMAIL_CODE: "email code" - } - - print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}") - - while True: - if not self.phone_code: + if not self.use_qrcode and not self.phone_code: self.phone_code = await ainput("Enter confirmation code: ") try: - signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code) + if self.use_qrcode: + signed_in = await self.sign_in_qrcode() + else: + signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code) except BadRequest as e: print(e.MESSAGE) self.phone_code = None @@ -488,7 +510,15 @@ class Client(Methods): print(e.MESSAGE) self.password = None else: - break + if self.use_qrcode and isinstance(signed_in, raw.types.auth.LoginToken): + time_out = signed_in.expires - datetime.timestamp(datetime.now()) + try: + await asyncio.wait_for(self._wait_for_update_login_token(), timeout=time_out) + except asyncio.TimeoutError: + print("QR code expired, Requesting new Qr code...") + continue + else: + break if isinstance(signed_in, User): return signed_in diff --git a/pyrogram/connection/transport/tcp/tcp.py b/pyrogram/connection/transport/tcp/tcp.py index 1848ba35..4957c061 100644 --- a/pyrogram/connection/transport/tcp/tcp.py +++ b/pyrogram/connection/transport/tcp/tcp.py @@ -54,6 +54,14 @@ class TCP: self.lock = asyncio.Lock() self.loop = asyncio.get_event_loop() + self._closed = True + + @property + def closed(self) -> bool: + return ( + self._closed or self.writer is None or self.writer.is_closing() or self.reader is None + ) + async def _connect_via_proxy( self, @@ -123,11 +131,14 @@ class TCP: async def connect(self, address: Tuple[str, int]) -> None: try: await asyncio.wait_for(self._connect(address), TCP.TIMEOUT) + self._closed = False except asyncio.TimeoutError: # Re-raise as TimeoutError. asyncio.TimeoutError is deprecated in 3.11 + self._closed = True raise TimeoutError("Connection timed out") async def close(self) -> None: if self.writer is None: + self._closed = True return None try: @@ -135,10 +146,12 @@ class TCP: await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT) except Exception as e: log.info("Close exception: %s %s", type(e).__name__, e) + finally: + self._closed = True async def send(self, data: bytes) -> None: - if self.writer is None: - return None + if self.writer is None or self._closed: + raise OSError("Connection is closed") async with self.lock: try: @@ -146,9 +159,13 @@ class TCP: await self.writer.drain() except Exception as e: log.info("Send exception: %s %s", type(e).__name__, e) + self._closed = True raise OSError(e) async def recv(self, length: int = 0) -> Optional[bytes]: + if self._closed or self.reader is None: + return None + data = b"" while len(data) < length: @@ -158,11 +175,13 @@ class TCP: TCP.TIMEOUT ) except (OSError, asyncio.TimeoutError): + self._closed = True return None else: if chunk: data += chunk else: + self._closed = True return None return data diff --git a/pyrogram/filters.py b/pyrogram/filters.py index a7b17a60..8b00fe81 100644 --- a/pyrogram/filters.py +++ b/pyrogram/filters.py @@ -1,3 +1,4 @@ + # Pyrofork - Telegram MTProto API Client Library for Python # Copyright (C) 2017-present Dan # Copyright (C) 2022-present Mayuri-Chan @@ -250,7 +251,7 @@ react = create(reaction_filter) # region forwarded_filter async def forwarded_filter(_, __, m: Message): - return bool(m.forward_date) + return bool(m.forward_origin) forwarded = create(forwarded_filter) diff --git a/pyrogram/methods/auth/__init__.py b/pyrogram/methods/auth/__init__.py index a7d392fc..d5cab5c1 100644 --- a/pyrogram/methods/auth/__init__.py +++ b/pyrogram/methods/auth/__init__.py @@ -31,6 +31,7 @@ from .send_code import SendCode from .send_recovery_code import SendRecoveryCode from .sign_in import SignIn from .sign_in_bot import SignInBot +from .sign_in_qrcode import SignInQrcode from .sign_up import SignUp from .terminate import Terminate @@ -50,6 +51,7 @@ class Auth( SendRecoveryCode, SignIn, SignInBot, + SignInQrcode, SignUp, Terminate ): diff --git a/pyrogram/methods/auth/sign_in_qrcode.py b/pyrogram/methods/auth/sign_in_qrcode.py new file mode 100644 index 00000000..ffca3e80 --- /dev/null +++ b/pyrogram/methods/auth/sign_in_qrcode.py @@ -0,0 +1,139 @@ +# Pyrofork - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrofork. +# +# Pyrofork is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrofork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrofork. If not, see . + +import logging +from base64 import b64encode +from typing import Union + +import pyrogram +from pyrogram import raw +from pyrogram import types +from pyrogram.session import Session, Auth + +log = logging.getLogger(__name__) + +QRCODE_AVAIL = False +try: + import qrcode + QRCODE_AVAIL = True +except ImportError: + QRCODE_AVAIL = False + + +class SignInQrcode: + async def sign_in_qrcode( + self: "pyrogram.Client" + ) -> Union["types.User", "types.LoginToken"]: + """Authorize a user in Telegram with a QR code. + + .. include:: /_includes/usable-by/users.rst + + Returns: + :obj:`~pyrogram.types.User` | :obj:`pyrogram.types.LoginToken`, in case the + authorization completed, the user is returned. In case the QR code is + not scanned, a login token is returned. + + Raises: + ImportError: In case the qrcode library is not installed. + SessionPasswordNeeded: In case a password is needed to sign in. + """ + + if not QRCODE_AVAIL: + raise ImportError("qrcode is missing! " + "Please install it with `pip install qrcode`") + r = await self.session.invoke( + raw.functions.auth.ExportLoginToken( + api_id=self.api_id, + api_hash=self.api_hash, + except_ids=[] + ) + ) + if isinstance(r, raw.types.auth.LoginToken): + base64_token = b64encode(r.token).decode("utf-8") + login_url = f"tg://login?token={base64_token}" + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + qr.add_data(login_url) + qr.make(fit=True) + + print("Scan the QR code with your Telegram app.") + qr.print_ascii() + + return r + elif isinstance(r, raw.types.auth.LoginTokenSuccess): + await self.storage.user_id(r.authorization.user.id) + await self.storage.is_bot(False) + + return types.User._parse(self, r.authorization.user) + elif isinstance(r, raw.types.auth.LoginTokenMigrateTo): + # pylint: disable=access-member-before-definition + await self.session.stop() + + await self.storage.dc_id(r.dc_id) + await self.storage.auth_key( + await Auth( + self, await self.storage.dc_id(), + await self.storage.test_mode() + ).create() + ) + self.session = Session( + self, await self.storage.dc_id(), + await self.storage.auth_key(), await self.storage.test_mode() + ) + + await self.session.start() + r = await self.session.invoke( + raw.functions.auth.ImportLoginToken( + token=r.token + ) + ) + if isinstance(r, raw.types.auth.LoginToken): + base64_token = b64encode(r.token).decode("utf-8") + login_url = f"tg://login?token={base64_token}" + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + qr.add_data(login_url) + qr.make(fit=True) + + print("Scan the QR code below with your Telegram app.") + qr.print_ascii() + + return types.LoginToken( + self, + r.token, + r.expires + ) + elif isinstance(r, raw.types.auth.LoginTokenSuccess): + await self.storage.user_id(r.authorization.user.id) + await self.storage.is_bot(False) + + return types.User._parse(self, r.authorization.user) + else: + raise pyrogram.exceptions.RPCError( + "Unknown response type from Telegram API" + ) + return r diff --git a/pyrogram/methods/business/__init__.py b/pyrogram/methods/business/__init__.py index ac8140fb..2bf6fd21 100644 --- a/pyrogram/methods/business/__init__.py +++ b/pyrogram/methods/business/__init__.py @@ -1,5 +1,6 @@ # Pyrogram - Telegram MTProto API Client Library for Python # Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan # # This file is part of Pyrogram. # @@ -18,12 +19,14 @@ from .answer_pre_checkout_query import AnswerPreCheckoutQuery from .answer_shipping_query import AnswerShippingQuery +from .delete_business_messages import DeleteBusinessMessages from .get_business_connection import GetBusinessConnection class TelegramBusiness( AnswerPreCheckoutQuery, AnswerShippingQuery, + DeleteBusinessMessages, GetBusinessConnection, ): pass diff --git a/pyrogram/methods/business/delete_business_messages.py b/pyrogram/methods/business/delete_business_messages.py new file mode 100644 index 00000000..12011e2b --- /dev/null +++ b/pyrogram/methods/business/delete_business_messages.py @@ -0,0 +1,71 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Iterable, Union + +import pyrogram +from pyrogram import raw + + +class DeleteBusinessMessages: + async def delete_business_messages( + self: "pyrogram.Client", + business_connection_id: str, + message_ids: Union[int, Iterable[int]] + ) -> int: + """Delete messages on behalf of a business account. + + .. note:: + + Requires the `can_delete_sent_messages` business bot right to delete messages sent by the bot itself, + or the `can_delete_all_messages` business bot right to delete any message. + + .. include:: /_includes/usable-by/bots.rst + + Parameters: + business_connection_id (``str``): + Unique identifier of business connection on behalf of which to send the request. + + message_ids (``int`` | Iterable of ``int``): + An iterable of message identifiers to delete (integers) or a single message id. + All messages must be from the same chat. + + Returns: + ``int``: Amount of affected messages + + Example: + .. code-block:: python + + # Delete one message + await app.delete_business_messages(connection_id, message_id) + + # Delete multiple messages at once + await app.delete_business_messages(connection_id, list_of_message_ids) + """ + message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids] + + r = await self.invoke( + raw.functions.messages.DeleteMessages( + id=message_ids, + revoke=True + ), + business_connection_id=business_connection_id + ) + + return r.pts_count diff --git a/pyrogram/methods/decorators/on_error.py b/pyrogram/methods/decorators/on_error.py index d21d75bb..7c3294d1 100644 --- a/pyrogram/methods/decorators/on_error.py +++ b/pyrogram/methods/decorators/on_error.py @@ -28,7 +28,7 @@ class OnError: """Decorator for handling new errors. This does the same thing as :meth:`~pyrogram.Client.add_handler` using the - :obj:`~pyrogram.handlers.MessageHandler`. + :obj:`~pyrogram.handlers.ErrorHandler`. Parameters: errors (:obj:`~Exception`, *optional*): diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py index af2a539d..5689dc5a 100644 --- a/pyrogram/methods/messages/send_video.py +++ b/pyrogram/methods/messages/send_video.py @@ -58,6 +58,7 @@ class SendVideo: protect_content: bool = None, allow_paid_broadcast: bool = None, message_effect_id: int = None, + view_once: bool = None, invert_media: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -180,6 +181,10 @@ class SendVideo: message_effect_id (``int`` ``64-bit``, *optional*): Unique identifier of the message effect to be added to the message; for private chats only. + view_once (``bool``, *optional*): + Self-Destruct Timer. + If True, the photo will self-destruct after it was viewed. + invert_media (``bool``, *optional*): Inverts the position of the video and caption. @@ -298,7 +303,7 @@ class SendVideo: media = raw.types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(video) or "video/mp4", file=file, - ttl_seconds=ttl_seconds, + ttl_seconds=(1 << 31) - 1 if view_once else ttl_seconds, spoiler=has_spoiler, thumb=thumb, attributes=[ @@ -316,13 +321,13 @@ class SendVideo: elif re.match("^https?://", video): media = raw.types.InputMediaDocumentExternal( url=video, - ttl_seconds=ttl_seconds, + ttl_seconds=(1 << 31) - 1 if view_once else ttl_seconds, spoiler=has_spoiler, video_cover=vidcover_file, video_timestamp=start_timestamp ) else: - media = utils.get_input_media_from_file_id(video, FileType.VIDEO, ttl_seconds=ttl_seconds) + media = utils.get_input_media_from_file_id(video, FileType.VIDEO, ttl_seconds=(1 << 31) - 1 if view_once else ttl_seconds) media.spoiler = has_spoiler else: thumb = await self.save_file(thumb) @@ -330,7 +335,7 @@ class SendVideo: media = raw.types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(file_name or video.name) or "video/mp4", file=file, - ttl_seconds=ttl_seconds, + ttl_seconds=(1 << 31) - 1 if view_once else ttl_seconds, spoiler=has_spoiler, thumb=thumb, attributes=[ diff --git a/pyrogram/session/session.py b/pyrogram/session/session.py index c84a3cb4..57d16c95 100644 --- a/pyrogram/session/session.py +++ b/pyrogram/session/session.py @@ -417,6 +417,19 @@ class Session: while True: try: + if ( + self.connection is None + or self.connection.protocol is None + or getattr(self.connection.protocol, "closed", True) + ): + log.warning( + "[%s] Connection is closed or not established. Attempting to reconnect...", + self.client.name, + ) + await self.restart() + await asyncio.sleep(1) + continue + return await self.send(query, timeout=timeout) except (FloodWait, FloodPremiumWait) as e: amount = e.value @@ -438,6 +451,16 @@ class Session: query_name, str(e) or repr(e) ) + if isinstance(e, OSError) and retries > 1: + try: + await self.restart() + except Exception as restart_error: + log.warning( + "[%s] Failed to restart session: %s", + self.client.name, + str(restart_error) or repr(restart_error), + ) + await asyncio.sleep(0.5) return await self.invoke(query, retries - 1, timeout) diff --git a/pyrogram/types/authorization/__init__.py b/pyrogram/types/authorization/__init__.py index 0358badd..4f739486 100644 --- a/pyrogram/types/authorization/__init__.py +++ b/pyrogram/types/authorization/__init__.py @@ -19,12 +19,14 @@ from .active_session import ActiveSession from .active_sessions import ActiveSessions +from .login_token import LoginToken from .sent_code import SentCode from .terms_of_service import TermsOfService __all__ = [ "ActiveSession", "ActiveSessions", + "LoginToken", "SentCode", "TermsOfService", ] diff --git a/pyrogram/types/authorization/login_token.py b/pyrogram/types/authorization/login_token.py new file mode 100644 index 00000000..6b3473a9 --- /dev/null +++ b/pyrogram/types/authorization/login_token.py @@ -0,0 +1,37 @@ +# Pyrofork - Telegram MTProto API Client Library for Python +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrofork. +# +# Pyrofork is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrofork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrofork. If not, see . + +from ..object import Object + + +class LoginToken(Object): + """Contains info on a login token. + + Parameters: + token (``str``): + The login token. + + expires (``int``): + The expiration date of the token in UNIX format. + """ + + def __init__(self, *, token: str, expires: int): + super().__init__() + + self.token = token + self.expires = expires diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index e67f2315..df9ccb62 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -2922,6 +2922,8 @@ class Message(Object, Update): reply_in_chat_id: Union[int, str] = None, quote_text: str = None, quote_entities: List["types.MessageEntity"] = None, + schedule_date: datetime = None, + protect_content: bool = None, allow_paid_broadcast: bool = None, message_effect_id: int = None, view_once: bool = None, @@ -3011,6 +3013,12 @@ class Message(Object, Update): List of special entities that appear in quote_text, which can be specified instead of *parse_mode*. for reply_to_message only. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. + + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + allow_paid_broadcast (``bool``, *optional*): Pass True to allow the message to ignore regular broadcast limits for a small fee; for bots @@ -3085,6 +3093,8 @@ class Message(Object, Update): reply_to_chat_id=reply_to_chat_id, quote_text=quote_text, quote_entities=quote_entities, + schedule_date=schedule_date, + protect_content=protect_content, allow_paid_broadcast=allow_paid_broadcast, message_effect_id=message_effect_id, view_once=view_once, @@ -3637,9 +3647,11 @@ class Message(Object, Update): quote_entities: List["types.MessageEntity"] = None, allow_paid_broadcast: bool = None, message_effect_id: int = None, + view_once: bool = None, cover: Union[str, BinaryIO] = None, start_timestamp: int = None, schedule_date: datetime = None, + protect_content: bool = None, invert_media: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -3757,9 +3769,15 @@ class Message(Object, Update): schedule_date (:py:obj:`~datetime.datetime`, *optional*): Date when the message will be automatically sent. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + message_effect_id (``int`` ``64-bit``, *optional*): Unique identifier of the message effect to be added to the message; for private chats only. + view_once (``bool``, *optional*): + Pass True to send the video as a view-once message. + invert_media (``bool``, *optional*): Pass True to invert the video and caption position. @@ -3839,9 +3857,11 @@ class Message(Object, Update): quote_entities=quote_entities, allow_paid_broadcast=allow_paid_broadcast, message_effect_id=message_effect_id, + view_once=view_once, cover=cover, start_timestamp=start_timestamp, schedule_date=schedule_date, + protect_content=protect_content, invert_media=invert_media, reply_markup=reply_markup, progress=progress, diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index 776a8809..64acdb37 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -83,6 +83,9 @@ class Chat(Object): is_gifts_available (``bool``, *optional*): True, if star gifts can be received by this chat. + is_auto_translation_enabled (``bool``, *optional*): + True, if automatic translation is enabled in chat. + title (``str``, *optional*): Title, for supergroups, channels and basic group chats. @@ -236,6 +239,7 @@ class Chat(Object): is_paid_reactions_available: bool = None, is_slowmode_enabled: bool = None, is_gifts_available: bool = None, + is_auto_translation_enabled: bool = None, title: str = None, username: str = None, first_name: str = None, @@ -290,6 +294,7 @@ class Chat(Object): self.is_paid_reactions_available = is_paid_reactions_available self.is_slowmode_enabled = is_slowmode_enabled self.is_gifts_available = is_gifts_available + self.is_auto_translation_enabled = is_auto_translation_enabled self.title = title self.username = username self.first_name = first_name @@ -535,6 +540,7 @@ class Chat(Object): parsed_chat.is_antispam = full_chat.antispam parsed_chat.is_paid_reactions_available = full_chat.paid_reactions_available parsed_chat.is_gifts_available = getattr(full_chat, "stargifts_available", None) + parsed_chat.is_auto_translation_enabled = getattr(full_chat, "auto_translation", None) parsed_chat.gifts_count = getattr(full_chat, "stargifts_count", None) parsed_chat.folder_id = getattr(full_chat, "folder_id", None)