mirror of
https://github.com/Mayuri-Chan/pyrofork.git
synced 2025-12-29 12:04:51 +00:00
Merge branch 'Mayuri-Chan:main' into main
This commit is contained in:
commit
b2aac1b811
72 changed files with 2245 additions and 469 deletions
|
|
@ -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<RestrictionReason> 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<Username> 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#fe685355 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 broadcast_messages_allowed:flags2.16?true monoforum:flags2.17?true forum_tabs:flags2.19?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> 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<Username> 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 linked_monoforum_id:flags2.18?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<BotInfo> 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<long> 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;
|
||||
messageActionPaidMessagesPrice#84b88578 flags:# broadcast_messages_allowed:flags.0?true 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<Peer> = 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;
|
||||
|
|
@ -340,7 +341,7 @@ updateBotCallbackQuery#b9cfc48d flags:# query_id:long user_id:long peer:Peer msg
|
|||
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
|
||||
updateInlineBotCallbackQuery#691e9052 flags:# query_id:long user_id:long msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
|
||||
updateReadChannelOutbox#b75f99a9 channel_id:long max_id:int = Update;
|
||||
updateDraftMessage#1b49ec6d flags:# peer:Peer top_msg_id:flags.0?int draft:DraftMessage = Update;
|
||||
updateDraftMessage#edfc111e flags:# peer:Peer top_msg_id:flags.0?int saved_peer_id:flags.1?Peer draft:DraftMessage = Update;
|
||||
updateReadFeaturedStickers#571d2742 = Update;
|
||||
updateRecentStickers#9a422c20 = Update;
|
||||
updateConfig#a229dd06 = Update;
|
||||
|
|
@ -356,10 +357,10 @@ updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
|
|||
updateLangPackTooLong#46560264 lang_code:string = Update;
|
||||
updateLangPack#56022f4d difference:LangPackDifference = Update;
|
||||
updateFavedStickers#e511996d = Update;
|
||||
updateChannelReadMessagesContents#ea29055d flags:# channel_id:long top_msg_id:flags.0?int messages:Vector<int> = Update;
|
||||
updateChannelReadMessagesContents#25f324f7 flags:# channel_id:long top_msg_id:flags.0?int saved_peer_id:flags.1?Peer messages:Vector<int> = Update;
|
||||
updateContactsReset#7084a7be = Update;
|
||||
updateChannelAvailableMessages#b23fc698 channel_id:long available_min_id:int = Update;
|
||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||
updateDialogUnreadMark#b658f23e flags:# unread:flags.0?true peer:DialogPeer saved_peer_id:flags.1?Peer = Update;
|
||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||
|
|
@ -393,7 +394,7 @@ updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJ
|
|||
updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector<BotCommand> = Update;
|
||||
updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector<long> = Update;
|
||||
updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update;
|
||||
updateMessageReactions#5e1b3cb8 flags:# peer:Peer msg_id:int top_msg_id:flags.0?int reactions:MessageReactions = Update;
|
||||
updateMessageReactions#1e297bfa flags:# peer:Peer msg_id:int top_msg_id:flags.0?int saved_peer_id:flags.1?Peer reactions:MessageReactions = Update;
|
||||
updateAttachMenuBots#17b7a20b = Update;
|
||||
updateWebViewResultSent#1592b79d query_id:long = Update;
|
||||
updateBotMenuButton#14b85813 bot_id:long button:BotMenuButton = Update;
|
||||
|
|
@ -440,6 +441,9 @@ 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<bytes> next_offset:int = Update;
|
||||
updateReadMonoForumInbox#77b0e372 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
updateReadMonoForumOutbox#a4a79376 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
|
|
@ -614,7 +618,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<WebPageAttribute> = 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<WebPageAttribute> = 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 +914,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 +969,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<PhoneConnection> 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<PhoneConnection> 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 +1047,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 +1315,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<PostInteractionCounters> = stats.BroadcastStats;
|
||||
|
||||
help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
|
||||
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> 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<string> dismissed_suggestions:Vector<string> custom_pending_suggestion:flags.4?PendingSuggestion chats:Vector<Chat> users:Vector<User> = 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<int> = VideoSize;
|
||||
|
|
@ -1349,9 +1354,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 +1499,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;
|
||||
|
||||
|
|
@ -1639,8 +1649,9 @@ stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count
|
|||
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
|
||||
inputReplyToMessage#22c0f6d5 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int = InputReplyTo;
|
||||
inputReplyToMessage#b07038b0 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer = InputReplyTo;
|
||||
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
||||
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
||||
|
||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||
|
||||
|
|
@ -1713,6 +1724,7 @@ storyReactionPublicRepost#cfcd0f13 peer_id:Peer story:StoryItem = StoryReaction;
|
|||
stories.storyReactionsList#aa5f789c flags:# count:int reactions:Vector<StoryReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryReactionsList;
|
||||
|
||||
savedDialog#bd87cb6c flags:# pinned:flags.2?true peer:Peer top_message:int = SavedDialog;
|
||||
monoForumDialog#64407ea7 flags:# unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_reactions_count:int draft:flags.1?DraftMessage = SavedDialog;
|
||||
|
||||
messages.savedDialogs#f83ae221 dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
messages.savedDialogsSlice#44ba9dd9 count:int dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
|
|
@ -1852,7 +1864,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<MessageMedia> 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<MessageMedia> 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<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
|
||||
|
||||
|
|
@ -1890,8 +1902,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<StarGiftAttribute> 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<StarGiftAttribute> 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<StarGift> = payments.StarGifts;
|
||||
|
|
@ -1927,7 +1939,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<StarGiftAttribute> = payments.StarGiftUpgradePreview;
|
||||
|
|
@ -1939,12 +1951,13 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.Uni
|
|||
|
||||
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = 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<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = 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 +1980,18 @@ sponsoredPeer#c69708d3 flags:# random_id:bytes peer:Peer sponsor_info:flags.0?st
|
|||
contacts.sponsoredPeersEmpty#ea32b4b1 = contacts.SponsoredPeers;
|
||||
contacts.sponsoredPeers#eb032884 peers:Vector<SponsoredPeer> chats:Vector<Chat> users:Vector<User> = 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<StarGift> next_offset:flags.0?string attributes:flags.1?Vector<StarGiftAttribute> attributes_hash:flags.1?long chats:Vector<Chat> counters:flags.2?Vector<StarGiftAttributeCounter> users:Vector<User> = 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;
|
||||
|
|
@ -2165,7 +2190,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
|||
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
|
||||
messages.sendMessage#fbf2340a flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.sendMedia#a550cd78 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#bb9fa475 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#38f0188c flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int reply_to:flags.22?InputReplyTo schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
||||
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
|
||||
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
|
||||
|
|
@ -2247,8 +2272,8 @@ messages.sendMultiMedia#1bf89d74 flags:# silent:flags.5?true background:flags.6?
|
|||
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
|
||||
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
|
||||
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
|
||||
messages.markDialogUnread#8c5006f8 flags:# unread:flags.0?true parent_peer:flags.1?InputPeer peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#21202222 flags:# parent_peer:flags.0?InputPeer = Vector<DialogPeer>;
|
||||
messages.clearAllDrafts#7e58ee9c = Bool;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
|
||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||
|
|
@ -2278,7 +2303,7 @@ messages.getOldFeaturedStickers#7ed094a1 offset:int limit:int hash:long = messag
|
|||
messages.getReplies#22ddd30c peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
||||
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
||||
messages.unpinAllMessages#ee22b9a8 flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.unpinAllMessages#62dd747 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.deleteChat#5bd0ee50 chat_id:long = Bool;
|
||||
messages.deletePhoneCallHistory#f9cbe409 flags:# revoke:flags.0?true = messages.AffectedFoundMessages;
|
||||
messages.checkHistoryImport#43fe19f3 import_head:string = messages.HistoryImportParsed;
|
||||
|
|
@ -2309,8 +2334,8 @@ messages.setChatAvailableReactions#864b2581 flags:# peer:InputPeer available_rea
|
|||
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
||||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
|
||||
messages.getUnreadReactions#3223495b flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.getUnreadReactions#bd7f90ac flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#9ec44f93 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages;
|
||||
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
|
||||
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
|
||||
|
|
@ -2342,9 +2367,9 @@ messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp;
|
|||
messages.requestAppWebView#53618bce flags:# write_allowed:flags.0?true compact:flags.7?true fullscreen:flags.8?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = WebViewResult;
|
||||
messages.setChatWallPaper#8ffacae1 flags:# for_both:flags.3?true revert:flags.4?true peer:InputPeer wallpaper:flags.0?InputWallPaper settings:flags.2?WallPaperSettings id:flags.1?int = Updates;
|
||||
messages.searchEmojiStickerSets#92b4494c flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.getSavedDialogs#5381d21a flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#3d9a414d peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#6e98102b flags:# peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getSavedDialogs#1e91fc99 flags:# exclude_pinned:flags.0?true parent_peer:flags.1?InputPeer offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#998ab009 flags:# parent_peer:flags.0?InputPeer peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#4dc5085f flags:# parent_peer:flags.0?InputPeer peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getPinnedSavedDialogs#d63d94e0 = messages.SavedDialogs;
|
||||
messages.toggleSavedDialogPin#ac81bbde flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.reorderPinnedSavedDialogs#8b716587 flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
|
||||
|
|
@ -2379,6 +2404,8 @@ messages.savePreparedInlineMessage#f21f7f2f flags:# result:InputBotInlineResult
|
|||
messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage;
|
||||
messages.searchStickers#29b1c66a flags:# emojis:flags.0?true q:string emoticon:string lang_code:Vector<string> offset:int limit:int hash:long = messages.FoundStickers;
|
||||
messages.reportMessagesDelivery#5a6d7395 flags:# push:flags.0?true peer:InputPeer id:Vector<int> = Bool;
|
||||
messages.getSavedDialogsByID#6f6f9c96 flags:# parent_peer:flags.1?InputPeer ids:Vector<InputPeer> = messages.SavedDialogs;
|
||||
messages.readSavedHistory#ba4a3b5b parent_peer:InputPeer peer:InputPeer max_id:int = Bool;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
|
||||
|
|
@ -2467,7 +2494,7 @@ channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates;
|
|||
channels.reorderUsernames#b45ced1d channel:InputChannel order:Vector<string> = Bool;
|
||||
channels.toggleUsername#50f24105 channel:InputChannel username:string active:Bool = Bool;
|
||||
channels.deactivateAllUsernames#a245dd3 channel:InputChannel = Bool;
|
||||
channels.toggleForum#a4298b29 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.toggleForum#3ff75734 channel:InputChannel enabled:Bool tabs:Bool = Updates;
|
||||
channels.createForumTopic#f40c0224 flags:# channel:InputChannel title:string icon_color:flags.0?int icon_emoji_id:flags.3?long random_id:long send_as:flags.2?InputPeer = Updates;
|
||||
channels.getForumTopics#de560d1 flags:# channel:InputChannel q:flags.0?string offset_date:int offset_id:int offset_topic:int limit:int = messages.ForumTopics;
|
||||
channels.getForumTopicsByID#b0831eb9 channel:InputChannel topics:Vector<int> = messages.ForumTopics;
|
||||
|
|
@ -2486,7 +2513,9 @@ channels.setBoostsToUnblockRestrictions#ad399cee channel:InputChannel boosts:int
|
|||
channels.setEmojiStickers#3cd930b7 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||
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.updatePaidMessagesPrice#4b12327b flags:# broadcast_messages_allowed:flags.0?true channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||
channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getMessageAuthor#ece2a0e6 channel:InputChannel id:int = User;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
|
|
@ -2567,6 +2596,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<InputSavedStarGift> = 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<StarGiftAttributeId> 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<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
|
||||
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
|
||||
|
|
@ -2581,7 +2612,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 +2621,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<InputUser> = Updates;
|
||||
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
|
||||
|
|
@ -2611,7 +2642,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<long> 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<string> = Vector<LangPackString>;
|
||||
|
|
@ -2644,7 +2680,7 @@ chatlists.hideChatlistUpdates#66e486fb chatlist:InputChatlist = Bool;
|
|||
chatlists.getLeaveChatlistSuggestions#fdbcd714 chatlist:InputChatlist = Vector<Peer>;
|
||||
chatlists.leaveChatlist#74fae13a chatlist:InputChatlist peers:Vector<InputPeer> = 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<MediaArea> caption:flags.0?string entities:flags.1?Vector<MessageEntity> privacy_rules:Vector<InputPrivacyRule> 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<MediaArea> caption:flags.1?string entities:flags.1?Vector<MessageEntity> privacy_rules:flags.2?Vector<InputPrivacyRule> = Updates;
|
||||
stories.deleteStories#ae59db5f peer:InputPeer id:Vector<int> = Vector<int>;
|
||||
|
|
@ -2687,4 +2723,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
|
|||
|
||||
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
|
||||
|
||||
// LAYER 201
|
||||
// LAYER 204
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ def pyrogram_api():
|
|||
stop_transmission
|
||||
export_session_string
|
||||
set_parse_mode
|
||||
ping
|
||||
""",
|
||||
conversation="""
|
||||
Conversation
|
||||
|
|
@ -364,16 +365,24 @@ def pyrogram_api():
|
|||
get_chat_gifts
|
||||
hide_gift
|
||||
refund_star_payment
|
||||
search_gifts_for_resale
|
||||
send_invoice
|
||||
send_paid_media
|
||||
send_paid_reaction
|
||||
send_payment_form
|
||||
send_gift
|
||||
send_resold_gift
|
||||
set_gift_resale_price
|
||||
set_pinned_gifts
|
||||
show_gift
|
||||
transfer_gift
|
||||
upgrade_gift
|
||||
get_stars_balance
|
||||
""",
|
||||
phone="""
|
||||
Phone
|
||||
get_call_members
|
||||
""",
|
||||
password="""
|
||||
Password
|
||||
enable_cloud_password
|
||||
|
|
@ -408,7 +417,11 @@ def pyrogram_api():
|
|||
Telegram Business
|
||||
answer_pre_checkout_query
|
||||
answer_shipping_query
|
||||
delete_business_messages
|
||||
get_business_connection
|
||||
get_business_account_gifts
|
||||
get_business_account_star_balance
|
||||
transfer_business_account_stars
|
||||
""",
|
||||
authorization="""
|
||||
Authorization
|
||||
|
|
@ -420,12 +433,11 @@ def pyrogram_api():
|
|||
resend_code
|
||||
sign_in
|
||||
sign_in_bot
|
||||
sign_up
|
||||
sign_in_qrcode
|
||||
get_password_hint
|
||||
check_password
|
||||
send_recovery_code
|
||||
recover_password
|
||||
accept_terms_of_service
|
||||
log_out
|
||||
get_active_sessions
|
||||
""",
|
||||
|
|
@ -483,6 +495,7 @@ def pyrogram_api():
|
|||
BusinessWeeklyOpen
|
||||
BusinessWorkingHours
|
||||
User
|
||||
Username
|
||||
Chat
|
||||
ChatPreview
|
||||
ChatPhoto
|
||||
|
|
@ -505,6 +518,7 @@ def pyrogram_api():
|
|||
PeerUser
|
||||
PeerChannel
|
||||
BotInfo
|
||||
GroupCallMember
|
||||
ChatColor
|
||||
CollectibleItemInfo
|
||||
BotVerification
|
||||
|
|
@ -603,6 +617,7 @@ def pyrogram_api():
|
|||
Invoice
|
||||
LabeledPrice
|
||||
PaidMedia
|
||||
PaidMessagePriceChanged
|
||||
PaymentForm
|
||||
PaymentInfo
|
||||
PaymentRefunded
|
||||
|
|
@ -712,6 +727,7 @@ def pyrogram_api():
|
|||
InputMessageContent
|
||||
InputMessageContent
|
||||
InputReplyToMessage
|
||||
InputReplyToMonoforum
|
||||
InputReplyToStory
|
||||
InputTextMessageContent
|
||||
InputLocationMessageContent
|
||||
|
|
@ -723,6 +739,7 @@ def pyrogram_api():
|
|||
Authorization
|
||||
ActiveSession
|
||||
ActiveSessions
|
||||
LoginToken
|
||||
SentCode
|
||||
TermsOfService
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ BOT_GAMES_DISABLED Bot games cannot be used in this type of chat
|
|||
BOT_GROUPS_BLOCKED This bot can't be added to groups
|
||||
BOT_INLINE_DISABLED The inline feature of the bot is disabled
|
||||
BOT_INVALID This is not a valid bot
|
||||
BOT_INVOICE_INVALID The provided invoice is invalid
|
||||
BOT_METHOD_INVALID The method can't be used by bots
|
||||
BOT_MISSING This method can only be run by a bot
|
||||
BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats
|
||||
|
|
@ -46,6 +47,7 @@ BROADCAST_CALLS_DISABLED Broadcast calls disabled
|
|||
BROADCAST_ID_INVALID The channel is invalid
|
||||
BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels
|
||||
BROADCAST_REQUIRED The request can only be used with a channel
|
||||
BUSINESS_BOT_MISSING Business bot missing
|
||||
BUTTON_DATA_INVALID The button callback data is invalid or too large
|
||||
BUTTON_ID_INVALID The button_id parameter is invalid
|
||||
BUTTON_TEXT_INVALID The specified button text is invalid
|
||||
|
|
@ -503,3 +505,4 @@ BOOSTS_EMPTY You can't modify the icon of the General topic.
|
|||
BOOST_NOT_MODIFIED You're already boosting the specified channel.
|
||||
PAYMENT_REQUIRED The payment is required
|
||||
BOOST_PEER_INVALID The specified `boost_peer` is invalid.
|
||||
STARS_AMOUNT_INVALID The specified `amount` is invalid.
|
||||
|
|
|
@ -44,3 +44,4 @@ GROUPCALL_ALREADY_STARTED The groupcall has already started, you can join direct
|
|||
GROUPCALL_FORBIDDEN The group call has already ended
|
||||
LIVE_DISABLED Story is disabled server-side
|
||||
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commenting
|
||||
ALLOW_PAYMENT_REQUIRED_X Payment of {value} stars is required to perform this action
|
||||
|
8
docs/source/api/enums/GiftForResaleOrder.rst
Normal file
8
docs/source/api/enums/GiftForResaleOrder.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
GiftAttributeType
|
||||
=================
|
||||
|
||||
.. autoclass:: pyrogram.enums.GiftForResaleOrder()
|
||||
:members:
|
||||
|
||||
.. raw:: html
|
||||
:file: ./cleanup.html
|
||||
8
docs/source/api/enums/MessageOriginType.rst
Normal file
8
docs/source/api/enums/MessageOriginType.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
MessageOriginType
|
||||
=================
|
||||
|
||||
.. autoclass:: pyrogram.enums.MessageOriginType()
|
||||
:members:
|
||||
|
||||
.. raw:: html
|
||||
:file: ./cleanup.html
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__fork_name__ = "PyroFork"
|
||||
__version__ = "2.3.61"
|
||||
__version__ = "2.3.67"
|
||||
__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)"
|
||||
__copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>"
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import pyrogram
|
|||
from pyrogram import __version__, __license__
|
||||
from pyrogram import enums
|
||||
from pyrogram import raw
|
||||
from pyrogram import types
|
||||
from pyrogram import utils
|
||||
from pyrogram.crypto import aes
|
||||
from pyrogram.errors import CDNFileHashMismatch
|
||||
|
|
@ -51,7 +52,7 @@ from pyrogram.handlers.handler import Handler
|
|||
from pyrogram.methods import Methods
|
||||
from pyrogram.session import Auth, Session
|
||||
from pyrogram.storage import FileStorage, MemoryStorage, Storage
|
||||
from pyrogram.types import User, TermsOfService
|
||||
from pyrogram.types import User
|
||||
from pyrogram.utils import ainput
|
||||
from .connection import Connection
|
||||
from .connection.transport import TCPAbridged
|
||||
|
|
@ -130,6 +131,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
|
||||
|
|
@ -229,6 +233,7 @@ class Client(Methods):
|
|||
PARENT_DIR = Path(sys.argv[0]).parent
|
||||
|
||||
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:joinchat/|\+))([\w-]+)$")
|
||||
UPGRADED_GIFT_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:nft/|\+))([\w-]+)$")
|
||||
WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None
|
||||
WORKDIR = PARENT_DIR
|
||||
|
||||
|
|
@ -258,6 +263,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,
|
||||
|
|
@ -272,7 +278,7 @@ class Client(Methods):
|
|||
skip_updates: bool = True,
|
||||
takeout: bool = None,
|
||||
sleep_threshold: int = Session.SLEEP_THRESHOLD,
|
||||
hide_password: Optional[bool] = False,
|
||||
hide_password: Optional[bool] = True,
|
||||
max_concurrent_transmissions: int = MAX_CONCURRENT_TRANSMISSIONS,
|
||||
client_platform: "enums.ClientPlatform" = enums.ClientPlatform.OTHER,
|
||||
max_message_cache_size: int = MAX_CACHE_SIZE,
|
||||
|
|
@ -295,6 +301,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
|
||||
|
|
@ -403,6 +410,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)
|
||||
|
|
@ -410,52 +426,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
|
||||
|
|
@ -494,33 +518,18 @@ class Client(Methods):
|
|||
print(e.MESSAGE)
|
||||
self.password = None
|
||||
else:
|
||||
if self.use_qrcode and isinstance(signed_in, types.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
|
||||
break
|
||||
|
||||
if isinstance(signed_in, User):
|
||||
return signed_in
|
||||
|
||||
while True:
|
||||
first_name = await ainput("Enter first name: ")
|
||||
last_name = await ainput("Enter last name (empty to skip): ")
|
||||
|
||||
try:
|
||||
signed_up = await self.sign_up(
|
||||
self.phone_number,
|
||||
sent_code.phone_code_hash,
|
||||
first_name,
|
||||
last_name
|
||||
)
|
||||
except BadRequest as e:
|
||||
print(e.MESSAGE)
|
||||
else:
|
||||
break
|
||||
|
||||
if isinstance(signed_in, TermsOfService):
|
||||
print("\n" + signed_in.text + "\n")
|
||||
await self.accept_terms_of_service(signed_in.id)
|
||||
|
||||
return signed_up
|
||||
|
||||
def set_parse_mode(self, parse_mode: Optional["enums.ParseMode"]):
|
||||
"""Set the parse mode to be used globally by the client.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import asyncio
|
|||
import inspect
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
from typing import Any
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw, types, utils
|
||||
|
|
@ -337,59 +338,88 @@ class Dispatcher:
|
|||
async def handler_worker(self, lock: asyncio.Lock):
|
||||
while True:
|
||||
packet = await self.updates_queue.get()
|
||||
|
||||
if packet is None:
|
||||
break
|
||||
await self._process_packet(packet, lock)
|
||||
|
||||
async def _process_packet(
|
||||
self,
|
||||
packet: tuple[raw.core.TLObject, dict[int, types.Update], dict[int, types.Update]],
|
||||
lock: asyncio.Lock,
|
||||
try:
|
||||
await self._handle_packet(packet, lock)
|
||||
except pyrogram.StopPropagation:
|
||||
pass
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
finally:
|
||||
self.updates_queue.task_done()
|
||||
|
||||
async def _handle_packet(self, packet, lock: asyncio.Lock):
|
||||
update, users, chats = packet
|
||||
parser = self.update_parsers.get(type(update))
|
||||
|
||||
parsed_update, handler_type = (
|
||||
await parser(update, users, chats)
|
||||
if parser is not None else (None, type(None))
|
||||
)
|
||||
async with lock:
|
||||
await self._dispatch_to_handlers(update, users, chats, parsed_update, handler_type)
|
||||
|
||||
|
||||
async def _dispatch_to_handlers(
|
||||
self, update, users, chats, parsed_update, handler_type,
|
||||
):
|
||||
for group in self.groups.values():
|
||||
for handler in group:
|
||||
args = await self._match_handler(
|
||||
handler, update, users, chats, parsed_update, handler_type,
|
||||
)
|
||||
if args is None:
|
||||
continue
|
||||
|
||||
try:
|
||||
await self._execute_handler(handler, *args)
|
||||
except pyrogram.StopPropagation:
|
||||
raise
|
||||
except pyrogram.ContinuePropagation:
|
||||
continue
|
||||
except Exception as error:
|
||||
if parsed_update is not None:
|
||||
await self._handle_exception(parsed_update, error)
|
||||
break
|
||||
|
||||
async def _match_handler(
|
||||
self, handler, update, users, chats, parsed_update, handler_type,
|
||||
):
|
||||
try:
|
||||
update, users, chats = packet
|
||||
parser = self.update_parsers.get(type(update))
|
||||
|
||||
if parser is not None:
|
||||
parsed_result = parser(update, users, chats)
|
||||
if inspect.isawaitable(parsed_result):
|
||||
parsed_update, handler_type = await parsed_result
|
||||
else:
|
||||
parsed_update, handler_type = parsed_result
|
||||
else:
|
||||
parsed_update, handler_type = (None, type(None))
|
||||
|
||||
async with lock:
|
||||
for group in self.groups.values():
|
||||
for handler in group:
|
||||
try:
|
||||
if parsed_update is not None:
|
||||
if isinstance(handler, handler_type) and await handler.check(
|
||||
self.client, parsed_update
|
||||
):
|
||||
await self._execute_callback(handler, parsed_update)
|
||||
break
|
||||
elif isinstance(handler, RawUpdateHandler):
|
||||
await self._execute_callback(handler, update, users, chats)
|
||||
break
|
||||
except (pyrogram.StopPropagation, pyrogram.ContinuePropagation) as e:
|
||||
if isinstance(e, pyrogram.StopPropagation):
|
||||
raise
|
||||
except Exception as exception:
|
||||
if parsed_update is not None:
|
||||
await self._handle_exception(parsed_update, exception)
|
||||
except pyrogram.StopPropagation:
|
||||
pass
|
||||
if isinstance(handler, handler_type):
|
||||
if await handler.check(self.client, parsed_update):
|
||||
return (parsed_update,)
|
||||
elif isinstance(handler, RawUpdateHandler):
|
||||
if await handler.check(self.client, update):
|
||||
return (update, users, chats)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
finally:
|
||||
self.updates_queue.task_done()
|
||||
|
||||
async def _handle_exception(self, parsed_update: types.Update, exception: Exception):
|
||||
return None
|
||||
|
||||
async def _execute_handler(self, handler, *args: Any):
|
||||
if inspect.iscoroutinefunction(handler.callback):
|
||||
await handler.callback(self.client, *args)
|
||||
else:
|
||||
await self.loop.run_in_executor(
|
||||
self.client.executor,
|
||||
handler.callback,
|
||||
self.client,
|
||||
*args
|
||||
)
|
||||
|
||||
async def _handle_exception(
|
||||
self, parsed_update: types.Update, exception: Exception,
|
||||
):
|
||||
handled_error = False
|
||||
for error_handler in self.error_handlers:
|
||||
try:
|
||||
if await error_handler.check(self.client, parsed_update, exception):
|
||||
if await error_handler.check(
|
||||
self.client, parsed_update, exception,
|
||||
):
|
||||
handled_error = True
|
||||
break
|
||||
except pyrogram.StopPropagation:
|
||||
|
|
@ -401,11 +431,3 @@ class Dispatcher:
|
|||
|
||||
if not handled_error:
|
||||
log.exception("Unhandled exception: %s", exception)
|
||||
|
||||
async def _execute_callback(self, handler: Handler, *args):
|
||||
if inspect.iscoroutinefunction(handler.callback):
|
||||
await handler.callback(self.client, *args)
|
||||
else:
|
||||
await self.client.loop.run_in_executor(
|
||||
self.client.executor, handler.callback, self.client, *args
|
||||
)
|
||||
|
|
@ -27,6 +27,7 @@ from .chat_type import ChatType
|
|||
from .client_platform import ClientPlatform
|
||||
from .folder_color import FolderColor
|
||||
from .gift_attribute_type import GiftAttributeType
|
||||
from .gift_for_resale_order import GiftForResaleOrder
|
||||
from .listerner_types import ListenerTypes
|
||||
from .message_entity_type import MessageEntityType
|
||||
from .message_media_type import MessageMediaType
|
||||
|
|
@ -55,6 +56,7 @@ __all__ = [
|
|||
'ClientPlatform',
|
||||
'FolderColor',
|
||||
'GiftAttributeType',
|
||||
'GiftForResaleOrder',
|
||||
'ListenerTypes',
|
||||
'MessageEntityType',
|
||||
'MessageMediaType',
|
||||
|
|
|
|||
|
|
@ -39,3 +39,9 @@ class ChatType(AutoName):
|
|||
|
||||
CHANNEL = auto()
|
||||
"Chat is a channel"
|
||||
|
||||
FORUM = auto()
|
||||
"Chat is a forum"
|
||||
|
||||
MONOFORUM = auto()
|
||||
"Chat is a monoforum"
|
||||
|
|
|
|||
|
|
@ -17,29 +17,19 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
from enum import auto
|
||||
|
||||
from .auto_name import AutoName
|
||||
|
||||
|
||||
class AcceptTermsOfService:
|
||||
async def accept_terms_of_service(
|
||||
self: "pyrogram.Client",
|
||||
terms_of_service_id: str
|
||||
) -> bool:
|
||||
"""Accept the given terms of service.
|
||||
class GiftForResaleOrder(AutoName):
|
||||
"""Describes order in which upgraded gifts for resale will be sorted. Used in :meth:`~pyrogram.Client.search_gifts_for_resale`."""
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
PRICE = auto()
|
||||
"The gifts will be sorted by their price from the lowest to the highest"
|
||||
|
||||
Parameters:
|
||||
terms_of_service_id (``str``):
|
||||
The terms of service identifier.
|
||||
"""
|
||||
r = await self.invoke(
|
||||
raw.functions.help.AcceptTermsOfService(
|
||||
id=raw.types.DataJSON(
|
||||
data=terms_of_service_id
|
||||
)
|
||||
)
|
||||
)
|
||||
CHANGE_DATE = auto()
|
||||
"The gifts will be sorted by the last date when their price was changed from the newest to the oldest"
|
||||
|
||||
return bool(r)
|
||||
NUMBER = auto()
|
||||
"The gifts will be sorted by their number from the smallest to the largest"
|
||||
|
|
@ -132,3 +132,6 @@ class MessageServiceType(AutoName):
|
|||
|
||||
SCREENSHOT_TAKEN = auto()
|
||||
"Screenshot taken"
|
||||
|
||||
PAID_MESSAGE_PRICE_CHANGED = auto()
|
||||
"Paid message price changed"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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)
|
||||
|
|
@ -889,7 +890,12 @@ def command(commands: Union[str, List[str]], prefixes: Union[str, List[str]] = "
|
|||
command_re = re.compile(r"([\"'])(.*?)(?<!\\)\1|(\S+)")
|
||||
|
||||
async def func(flt, client: pyrogram.Client, message: Message):
|
||||
usernames = []
|
||||
username = client.me.username or ""
|
||||
if client.me.usernames:
|
||||
usernames.append(username)
|
||||
for user in client.me.usernames:
|
||||
usernames.append(user.username)
|
||||
text = message.text or message.caption
|
||||
message.command = None
|
||||
|
||||
|
|
@ -903,6 +909,24 @@ def command(commands: Union[str, List[str]], prefixes: Union[str, List[str]] = "
|
|||
without_prefix = text[len(prefix):]
|
||||
|
||||
for cmd in flt.commands:
|
||||
if usernames:
|
||||
for username in usernames:
|
||||
if not re.match(rf"^(?:{cmd}(?:@?{username})?)(?:\s|$)", without_prefix,
|
||||
flags=re.IGNORECASE if not flt.case_sensitive else 0):
|
||||
continue
|
||||
|
||||
without_command = re.sub(rf"{cmd}(?:@?{username})?\s?", "", without_prefix, count=1,
|
||||
flags=re.IGNORECASE if not flt.case_sensitive else 0)
|
||||
|
||||
# match.groups are 1-indexed, group(1) is the quote, group(2) is the text
|
||||
# between the quotes, group(3) is unquoted, whitespace-split text
|
||||
|
||||
# Remove the escape character from the arguments
|
||||
message.command = [cmd] + [
|
||||
re.sub(r"\\([\"'])", r"\1", m.group(2) or m.group(3) or "")
|
||||
for m in command_re.finditer(without_command)
|
||||
]
|
||||
return True
|
||||
if not re.match(rf"^(?:{cmd}(?:@?{username})?)(?:\s|$)", without_prefix,
|
||||
flags=re.IGNORECASE if not flt.case_sensitive else 0):
|
||||
continue
|
||||
|
|
@ -1010,12 +1034,22 @@ class user(Filter, set):
|
|||
)
|
||||
|
||||
async def __call__(self, _, message: Message):
|
||||
is_usernames_in_filters = False
|
||||
if message.from_user and message.from_user.usernames:
|
||||
for username in message.from_user.usernames:
|
||||
if (
|
||||
username.username in self
|
||||
or username.username.lower() in self
|
||||
):
|
||||
is_usernames_in_filters = True
|
||||
break
|
||||
return (message.from_user
|
||||
and (message.from_user.id in self
|
||||
or (message.from_user.username
|
||||
and message.from_user.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user.is_self)))
|
||||
and message.from_user.is_self))
|
||||
or is_usernames_in_filters)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
|
|
@ -1043,6 +1077,15 @@ class chat(Filter, set):
|
|||
|
||||
async def __call__(self, _, message: Union[Message, Story]):
|
||||
if isinstance(message, Story):
|
||||
is_usernames_in_filters = False
|
||||
if message.sender_chat and message.sender_chat.usernames:
|
||||
for username in message.sender_chat.usernames:
|
||||
if (
|
||||
username.username in self
|
||||
or username.username.lower() in self
|
||||
):
|
||||
is_usernames_in_filters = True
|
||||
break
|
||||
return (
|
||||
message.sender_chat
|
||||
and (
|
||||
|
|
@ -1061,8 +1104,17 @@ class chat(Filter, set):
|
|||
and message.from_user.username.lower() in self
|
||||
)
|
||||
)
|
||||
)
|
||||
) or is_usernames_in_filters
|
||||
else:
|
||||
is_usernames_in_filters = False
|
||||
if message.chat and message.chat.usernames:
|
||||
for username in message.chat.usernames:
|
||||
if (
|
||||
username.username in self
|
||||
or username.username.lower() in self
|
||||
):
|
||||
is_usernames_in_filters = True
|
||||
break
|
||||
return (message.chat
|
||||
and (message.chat.id in self
|
||||
or (message.chat.username
|
||||
|
|
@ -1070,7 +1122,10 @@ class chat(Filter, set):
|
|||
or ("me" in self
|
||||
and message.from_user
|
||||
and message.from_user.is_self
|
||||
and not message.outgoing)))
|
||||
and not message.outgoing))
|
||||
or (is_usernames_in_filters
|
||||
and not message.outgoing)
|
||||
)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ from .password import Password
|
|||
from .pyromod import Pyromod
|
||||
from .stickers import Stickers
|
||||
from .payments import Payments
|
||||
from .phone import Phone
|
||||
from .users import Users
|
||||
from .utilities import Utilities
|
||||
from .business import TelegramBusiness
|
||||
|
|
@ -42,6 +43,7 @@ class Methods(
|
|||
Password,
|
||||
Pyromod,
|
||||
Payments,
|
||||
Phone,
|
||||
Chats,
|
||||
Stickers,
|
||||
Users,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .accept_terms_of_service import AcceptTermsOfService
|
||||
from .check_password import CheckPassword
|
||||
from .connect import Connect
|
||||
from .disconnect import Disconnect
|
||||
|
|
@ -31,12 +30,11 @@ from .send_code import SendCode
|
|||
from .send_recovery_code import SendRecoveryCode
|
||||
from .sign_in import SignIn
|
||||
from .sign_in_bot import SignInBot
|
||||
from .sign_up import SignUp
|
||||
from .sign_in_qrcode import SignInQrcode
|
||||
from .terminate import Terminate
|
||||
|
||||
|
||||
class Auth(
|
||||
AcceptTermsOfService,
|
||||
CheckPassword,
|
||||
Connect,
|
||||
Disconnect,
|
||||
|
|
@ -50,7 +48,7 @@ class Auth(
|
|||
SendRecoveryCode,
|
||||
SignIn,
|
||||
SignInBot,
|
||||
SignUp,
|
||||
SignInQrcode,
|
||||
Terminate
|
||||
):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ from typing import Union
|
|||
import pyrogram
|
||||
from pyrogram import raw
|
||||
from pyrogram import types
|
||||
from pyrogram.errors import PhoneNumberUnoccupied
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -49,15 +50,13 @@ class SignIn:
|
|||
The valid confirmation code you received (either as Telegram message or as SMS in your phone number).
|
||||
|
||||
Returns:
|
||||
:obj:`~pyrogram.types.User` | :obj:`~pyrogram.types.TermsOfService` | bool: On success, in case the
|
||||
authorization completed, the user is returned. In case the phone number needs to be registered first AND the
|
||||
terms of services accepted (with :meth:`~pyrogram.Client.accept_terms_of_service`), an object containing
|
||||
them is returned. In case the phone number needs to be registered, but the terms of services don't need to
|
||||
be accepted, False is returned instead.
|
||||
:obj:`~pyrogram.types.User` | bool: On success, in case the
|
||||
authorization completed, the user is returned.
|
||||
|
||||
Raises:
|
||||
BadRequest: In case the arguments are invalid.
|
||||
SessionPasswordNeeded: In case a password is needed to sign in.
|
||||
PhoneNumberUnoccupied: In case the phone number is not registered on Telegram.
|
||||
"""
|
||||
phone_number = phone_number.strip(" +")
|
||||
|
||||
|
|
@ -70,10 +69,7 @@ class SignIn:
|
|||
)
|
||||
|
||||
if isinstance(r, raw.types.auth.AuthorizationSignUpRequired):
|
||||
if r.terms_of_service:
|
||||
return types.TermsOfService._parse(terms_of_service=r.terms_of_service)
|
||||
|
||||
return False
|
||||
raise PhoneNumberUnoccupied("The phone number is not registered on Telegram. Please use official Telegram app to register it.")
|
||||
else:
|
||||
await self.storage.user_id(r.user.id)
|
||||
await self.storage.is_bot(False)
|
||||
|
|
|
|||
111
pyrogram/methods/auth/sign_in_qrcode.py
Normal file
111
pyrogram/methods/auth/sign_in_qrcode.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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__)
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
try:
|
||||
import qrcode
|
||||
except ImportError:
|
||||
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 types.LoginToken._parse(r)
|
||||
if 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)
|
||||
if 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.LoginTokenSuccess):
|
||||
await self.storage.user_id(r.authorization.user.id)
|
||||
await self.storage.is_bot(False)
|
||||
|
||||
return types.User._parse(self, r.authorization.user)
|
||||
raise pyrogram.exceptions.RPCError(
|
||||
"Unknown response type from Telegram API"
|
||||
)
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
from pyrogram import types
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SignUp:
|
||||
async def sign_up(
|
||||
self: "pyrogram.Client",
|
||||
phone_number: str,
|
||||
phone_code_hash: str,
|
||||
first_name: str,
|
||||
last_name: str = ""
|
||||
) -> "types.User":
|
||||
"""Register a new user in Telegram.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
phone_number (``str``):
|
||||
Phone number in international format (includes the country prefix).
|
||||
|
||||
phone_code_hash (``str``):
|
||||
Code identifier taken from the result of :meth:`~pyrogram.Client.send_code`.
|
||||
|
||||
first_name (``str``):
|
||||
New user first name.
|
||||
|
||||
last_name (``str``, *optional*):
|
||||
New user last name. Defaults to "" (empty string, no last name).
|
||||
|
||||
Returns:
|
||||
:obj:`~pyrogram.types.User`: On success, the new registered user is returned.
|
||||
|
||||
Raises:
|
||||
BadRequest: In case the arguments are invalid.
|
||||
"""
|
||||
phone_number = phone_number.strip(" +")
|
||||
|
||||
r = await self.invoke(
|
||||
raw.functions.auth.SignUp(
|
||||
phone_number=phone_number,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
phone_code_hash=phone_code_hash
|
||||
)
|
||||
)
|
||||
|
||||
await self.storage.user_id(r.user.id)
|
||||
await self.storage.is_bot(False)
|
||||
|
||||
return types.User._parse(self, r.user)
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
|
||||
#
|
||||
# This file is part of Pyrogram.
|
||||
#
|
||||
|
|
@ -18,12 +19,20 @@
|
|||
|
||||
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
|
||||
from .get_business_account_gifts import GetBusinessAccountGifts
|
||||
from .get_business_account_star_balance import GetBusinessAccountStarBalance
|
||||
from .transfer_business_account_stars import TransferBusinessAccountStars
|
||||
|
||||
|
||||
class TelegramBusiness(
|
||||
AnswerPreCheckoutQuery,
|
||||
AnswerShippingQuery,
|
||||
DeleteBusinessMessages,
|
||||
GetBusinessConnection,
|
||||
GetBusinessAccountGifts,
|
||||
GetBusinessAccountStarBalance,
|
||||
TransferBusinessAccountStars,
|
||||
):
|
||||
pass
|
||||
|
|
|
|||
71
pyrogram/methods/business/delete_business_messages.py
Normal file
71
pyrogram/methods/business/delete_business_messages.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
129
pyrogram/methods/business/get_business_account_gifts.py
Normal file
129
pyrogram/methods/business/get_business_account_gifts.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw, types
|
||||
|
||||
|
||||
class GetBusinessAccountGifts:
|
||||
async def get_business_account_gifts(
|
||||
self: "pyrogram.Client",
|
||||
business_connection_id: str,
|
||||
exclude_unsaved: Optional[bool] = None,
|
||||
exclude_saved: Optional[bool] = None,
|
||||
exclude_unlimited: Optional[bool] = None,
|
||||
exclude_limited: Optional[bool] = None,
|
||||
exclude_upgraded: Optional[bool] = None,
|
||||
sort_by_price: Optional[bool] = None,
|
||||
limit: int = 0,
|
||||
offset: str = "",
|
||||
):
|
||||
"""Return the gifts received and owned by a managed business account.
|
||||
|
||||
.. note::
|
||||
|
||||
Requires the `can_view_gifts_and_stars` business bot right.
|
||||
|
||||
.. include:: /_includes/usable-by/bots.rst
|
||||
|
||||
Parameters:
|
||||
business_connection_id (``str``):
|
||||
Unique identifier of business connection on behalf of which to send the request.
|
||||
|
||||
exclude_unsaved (``bool``, *optional*):
|
||||
Pass True to exclude gifts that aren’t saved to the account’s profile page.
|
||||
|
||||
exclude_saved (``bool``, *optional*):
|
||||
Pass True to exclude gifts that are saved to the account’s profile page.
|
||||
|
||||
exclude_unlimited (``bool``, *optional*):
|
||||
Pass True to exclude gifts that can be purchased an unlimited number of times.
|
||||
|
||||
exclude_limited (``bool``, *optional*):
|
||||
Pass True to exclude gifts that can be purchased a limited number of times.
|
||||
|
||||
exclude_upgraded (``bool``, *optional*):
|
||||
Pass True to exclude upgraded gifts.
|
||||
|
||||
sort_by_price (``bool``, *optional*):
|
||||
Pass True to sort results by gift price instead of send date. Sorting is applied before pagination.
|
||||
|
||||
offset (``str``, *optional*):
|
||||
Offset of the first entry to return as received from the previous request.
|
||||
|
||||
limit (``int``, *optional*):
|
||||
The maximum number of gifts to be returned.
|
||||
|
||||
Returns:
|
||||
``Generator``: A generator yielding :obj:`~pyrogram.types.Gift` objects.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
async for gift in app.get_business_account_gifts(connection_id):
|
||||
print(gift)
|
||||
"""
|
||||
current = 0
|
||||
total = abs(limit) or (1 << 31) - 1
|
||||
limit = min(100, total)
|
||||
|
||||
connection_info = await self.get_business_connection(business_connection_id)
|
||||
|
||||
while True:
|
||||
r = await self.invoke(
|
||||
raw.functions.payments.GetSavedStarGifts(
|
||||
peer=await self.resolve_peer(connection_info.user.id),
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
exclude_unsaved=exclude_unsaved,
|
||||
exclude_saved=exclude_saved,
|
||||
exclude_unlimited=exclude_unlimited,
|
||||
exclude_limited=exclude_limited,
|
||||
exclude_unique=exclude_upgraded,
|
||||
sort_by_value=sort_by_price
|
||||
),
|
||||
sleep_threshold=60,
|
||||
business_connection_id=business_connection_id
|
||||
)
|
||||
|
||||
users = {i.id: i for i in r.users}
|
||||
chats = {i.id: i for i in r.chats}
|
||||
|
||||
user_star_gifts = [
|
||||
await types.Gift._parse_saved(self, gift, users, chats)
|
||||
for gift in r.gifts
|
||||
]
|
||||
|
||||
if not user_star_gifts:
|
||||
return
|
||||
|
||||
for gift in user_star_gifts:
|
||||
yield gift
|
||||
|
||||
current += 1
|
||||
|
||||
if current >= total:
|
||||
return
|
||||
|
||||
offset = r.next_offset
|
||||
|
||||
if not offset:
|
||||
return
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Optional, Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
class GetBusinessAccountStarBalance:
|
||||
async def get_business_account_star_balance(
|
||||
self: "pyrogram.Client",
|
||||
business_connection_id: str,
|
||||
) -> int:
|
||||
"""Return the amount of Telegram Stars owned by a managed business account.
|
||||
|
||||
.. note::
|
||||
|
||||
Requires the `can_view_gifts_and_stars` business bot right.
|
||||
|
||||
.. include:: /_includes/usable-by/bots.rst
|
||||
|
||||
Parameters:
|
||||
business_connection_id (``str``):
|
||||
Unique identifier of business connection on behalf of which to send the request.
|
||||
|
||||
Returns:
|
||||
``int``: On success, the current stars balance is returned.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
# Get stars balance
|
||||
await app.get_business_account_star_balance("connection_id")
|
||||
"""
|
||||
connection_info = await self.get_business_connection(business_connection_id)
|
||||
|
||||
r = await self.invoke(
|
||||
raw.functions.payments.GetStarsStatus(
|
||||
peer=await self.resolve_peer(connection_info.user.id),
|
||||
),
|
||||
business_connection_id=business_connection_id
|
||||
)
|
||||
|
||||
return r.balance.amount
|
||||
72
pyrogram/methods/business/transfer_business_account_stars.py
Normal file
72
pyrogram/methods/business/transfer_business_account_stars.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
class TransferBusinessAccountStars:
|
||||
async def transfer_business_account_stars(
|
||||
self: "pyrogram.Client",
|
||||
business_connection_id: str,
|
||||
star_count: int,
|
||||
) -> bool:
|
||||
"""Transfers Telegram Stars from the business account balance to the bot’s balance.
|
||||
|
||||
.. note::
|
||||
|
||||
Requires the `can_transfer_stars` business bot right.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
business_connection_id (``str``):
|
||||
Unique identifier of the business connection.
|
||||
|
||||
star_count (``int`` | ``str``):
|
||||
Number of Telegram Stars to transfer, 1-10000.
|
||||
|
||||
Returns:
|
||||
``bool``: On success, True is returned.
|
||||
"""
|
||||
# Why telegram won't let us just use InputPeerSelf :(
|
||||
if self.me:
|
||||
bot_id = self.me.id
|
||||
else:
|
||||
bot_id = (
|
||||
await self.invoke(raw.functions.users.GetUsers(id=[raw.types.InputPeerSelf()]))
|
||||
)[0].id
|
||||
|
||||
invoice = raw.types.InputInvoiceBusinessBotTransferStars(
|
||||
bot=await self.resolve_peer(bot_id), stars=star_count
|
||||
)
|
||||
|
||||
payment_form = await self.invoke(
|
||||
raw.functions.payments.GetPaymentForm(invoice=invoice),
|
||||
business_connection_id=business_connection_id,
|
||||
)
|
||||
|
||||
await self.invoke(
|
||||
raw.functions.payments.SendStarsForm(
|
||||
form_id=payment_form.form_id,
|
||||
invoice=invoice,
|
||||
),
|
||||
business_connection_id=business_connection_id,
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
@ -24,26 +24,33 @@ from pyrogram.filters import Filter
|
|||
|
||||
|
||||
class OnError:
|
||||
def on_error(self=None, errors=None) -> Callable:
|
||||
def on_error(
|
||||
self=None,
|
||||
errors=None,
|
||||
group: int = 0,
|
||||
) -> Callable:
|
||||
"""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*):
|
||||
Pass one or more errors to allow only a subset of errors to be passed
|
||||
in your function.
|
||||
|
||||
group (``int``, *optional*):
|
||||
The group identifier, defaults to 0.
|
||||
"""
|
||||
|
||||
def decorator(func: Callable) -> Callable:
|
||||
if isinstance(self, pyrogram.Client):
|
||||
self.add_handler(pyrogram.handlers.ErrorHandler(func, errors), 0)
|
||||
self.add_handler(pyrogram.handlers.ErrorHandler(func, errors), group)
|
||||
elif isinstance(self, Filter) or self is None:
|
||||
if not hasattr(func, "handlers"):
|
||||
func.handlers = []
|
||||
|
||||
func.handlers.append((pyrogram.handlers.ErrorHandler(func, self), 0))
|
||||
func.handlers.append((pyrogram.handlers.ErrorHandler(func, self), group))
|
||||
|
||||
return func
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ async def get_chunk(
|
|||
from_message_id: int = 0,
|
||||
from_date: datetime = utils.zero_datetime(),
|
||||
min_id: int = 0,
|
||||
max_id: int = 0
|
||||
max_id: int = 0,
|
||||
reverse: Optional[bool] = None
|
||||
):
|
||||
messages = await client.invoke(
|
||||
raw.functions.messages.GetHistory(
|
||||
|
|
@ -48,6 +49,8 @@ async def get_chunk(
|
|||
),
|
||||
sleep_threshold=60
|
||||
)
|
||||
if reverse:
|
||||
messages.messages.reverse()
|
||||
|
||||
return await utils.parse_messages(client, messages, replies=0)
|
||||
|
||||
|
|
@ -61,7 +64,8 @@ class GetChatHistory:
|
|||
offset_id: int = 0,
|
||||
offset_date: datetime = utils.zero_datetime(),
|
||||
min_id: int = 0,
|
||||
max_id: int = 0
|
||||
max_id: int = 0,
|
||||
reverse: Optional[bool] = None
|
||||
) -> Optional[AsyncGenerator["types.Message", None]]:
|
||||
"""Get messages from a chat history.
|
||||
|
||||
|
|
@ -96,6 +100,9 @@ class GetChatHistory:
|
|||
max_id: (``int``, *optional*):
|
||||
The maximum message id. you will not get any message which have id greater than max_id.
|
||||
|
||||
reverse (``bool``, *optional*):
|
||||
Pass True to retrieve the messages in reversed order (from older to most recent).
|
||||
|
||||
Returns:
|
||||
``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
|
||||
|
||||
|
|
@ -118,7 +125,8 @@ class GetChatHistory:
|
|||
from_message_id=offset_id,
|
||||
from_date=offset_date,
|
||||
min_id=min_id,
|
||||
max_id=max_id
|
||||
max_id=max_id,
|
||||
reverse=reverse
|
||||
)
|
||||
|
||||
if not messages:
|
||||
|
|
|
|||
|
|
@ -78,6 +78,6 @@ class GetScheduledMessages:
|
|||
|
||||
r = await self.invoke(rpc, sleep_threshold=-1)
|
||||
|
||||
messages = await utils.parse_messages(self, r)
|
||||
messages = await utils.parse_messages(self, r, is_scheduled=True)
|
||||
|
||||
return messages if is_iterable else messages[0] if messages else None
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class SendAnimation:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -145,6 +146,11 @@ class SendAnimation:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -226,6 +232,7 @@ class SendAnimation:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class SendAudio:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
message_effect_id: int = None,
|
||||
|
|
@ -137,6 +138,11 @@ class SendAudio:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -216,6 +222,7 @@ class SendAudio:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class SendCachedMedia:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -104,6 +105,11 @@ class SendCachedMedia:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -144,6 +150,7 @@ class SendCachedMedia:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class SendContact:
|
|||
business_connection_id: str = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -95,6 +96,11 @@ class SendContact:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -139,6 +145,7 @@ class SendContact:
|
|||
reply_to_message_id=reply_to_message_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class SendDice:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -91,6 +92,11 @@ class SendDice:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -143,6 +149,7 @@ class SendDice:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class SendDocument:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
message_effect_id: int = None,
|
||||
|
|
@ -129,6 +130,11 @@ class SendDocument:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -203,6 +209,7 @@ class SendDocument:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class SendLocation:
|
|||
business_connection_id: str = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -89,6 +90,11 @@ class SendLocation:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
reply_to_message_id (``int``, *optional*):
|
||||
If the message is a reply, ID of the original message
|
||||
|
||||
|
|
@ -136,6 +142,7 @@ class SendLocation:
|
|||
reply_to_message_id=reply_to_message_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ import os
|
|||
import re
|
||||
from datetime import datetime
|
||||
from pymediainfo import MediaInfo
|
||||
from typing import Union, List, Optional
|
||||
from typing import (
|
||||
Union,
|
||||
List,
|
||||
Optional,
|
||||
Callable,
|
||||
)
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import enums
|
||||
|
|
@ -35,7 +40,6 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class SendMediaGroup:
|
||||
# TODO: Add progress parameter
|
||||
async def send_media_group(
|
||||
self: "pyrogram.Client",
|
||||
chat_id: Union[int, str],
|
||||
|
|
@ -52,6 +56,7 @@ class SendMediaGroup:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -59,7 +64,9 @@ class SendMediaGroup:
|
|||
protect_content: bool = None,
|
||||
allow_paid_broadcast: bool = None,
|
||||
message_effect_id: int = None,
|
||||
invert_media: bool = None
|
||||
invert_media: bool = None,
|
||||
progress: Callable = None,
|
||||
progress_args: tuple = (),
|
||||
) -> List["types.Message"]:
|
||||
"""Send a group of photos or videos as an album.
|
||||
|
||||
|
|
@ -98,6 +105,11 @@ class SendMediaGroup:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -126,6 +138,28 @@ class SendMediaGroup:
|
|||
invert_media (``bool``, *optional*):
|
||||
Inverts the position of the media and caption.
|
||||
|
||||
progress (``Callable``, *optional*):
|
||||
Pass a callback function to view the file transmission progress.
|
||||
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||
detailed description) and will be called back each time a new file chunk has been successfully
|
||||
transmitted.
|
||||
|
||||
progress_args (``tuple``, *optional*):
|
||||
Extra custom arguments for the progress callback function.
|
||||
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||
object or a Client instance in order to edit the message with the updated progress status.
|
||||
|
||||
Other Parameters:
|
||||
current (``int``):
|
||||
The amount of bytes transmitted so far.
|
||||
|
||||
total (``int``):
|
||||
The total size of the file.
|
||||
|
||||
*args (``tuple``, *optional*):
|
||||
Extra custom arguments as defined in the ``progress_args`` parameter.
|
||||
You can either keep ``*args`` or add every single extra argument in your function signature.
|
||||
|
||||
Returns:
|
||||
List of :obj:`~pyrogram.types.Message`: On success, a list of the sent messages is returned.
|
||||
|
||||
|
|
@ -152,23 +186,25 @@ class SendMediaGroup:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
parse_mode=parse_mode,
|
||||
)
|
||||
|
||||
for i in media:
|
||||
if isinstance(i, types.InputMediaPhoto):
|
||||
if isinstance(i.media, str):
|
||||
if os.path.isfile(i.media):
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedPhoto(
|
||||
file=await self.save_file(i.media),
|
||||
spoiler=i.has_spoiler
|
||||
)
|
||||
)
|
||||
file=file,
|
||||
spoiler=i.has_spoiler,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaPhoto(
|
||||
|
|
@ -177,7 +213,7 @@ class SendMediaGroup:
|
|||
access_hash=media.photo.access_hash,
|
||||
file_reference=media.photo.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
elif re.match("^https?://", i.media):
|
||||
media = await self.invoke(
|
||||
|
|
@ -185,9 +221,9 @@ class SendMediaGroup:
|
|||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaPhotoExternal(
|
||||
url=i.media,
|
||||
spoiler=i.has_spoiler
|
||||
)
|
||||
)
|
||||
spoiler=i.has_spoiler,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaPhoto(
|
||||
|
|
@ -196,19 +232,20 @@ class SendMediaGroup:
|
|||
access_hash=media.photo.access_hash,
|
||||
file_reference=media.photo.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
else:
|
||||
media = utils.get_input_media_from_file_id(i.media, FileType.PHOTO)
|
||||
else:
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedPhoto(
|
||||
file=await self.save_file(i.media),
|
||||
spoiler=i.has_spoiler
|
||||
)
|
||||
)
|
||||
file=file,
|
||||
spoiler=i.has_spoiler,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaPhoto(
|
||||
|
|
@ -217,7 +254,7 @@ class SendMediaGroup:
|
|||
access_hash=media.photo.access_hash,
|
||||
file_reference=media.photo.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
elif (
|
||||
isinstance(i, types.InputMediaVideo)
|
||||
|
|
@ -241,22 +278,25 @@ class SendMediaGroup:
|
|||
w=i.width,
|
||||
h=i.height
|
||||
),
|
||||
raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or os.path.basename(i.media)),
|
||||
]
|
||||
if is_animation:
|
||||
attributes.append(raw.types.DocumentAttributeAnimated())
|
||||
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
spoiler=i.has_spoiler,
|
||||
mime_type=self.guess_mime_type(i.media) or "video/mp4",
|
||||
nosound_video=is_animation,
|
||||
attributes=attributes
|
||||
)
|
||||
)
|
||||
attributes=attributes,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
|
|
@ -265,7 +305,7 @@ class SendMediaGroup:
|
|||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
elif re.match("^https?://", i.media):
|
||||
media = await self.invoke(
|
||||
|
|
@ -273,9 +313,9 @@ class SendMediaGroup:
|
|||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaDocumentExternal(
|
||||
url=i.media,
|
||||
spoiler=i.has_spoiler
|
||||
)
|
||||
)
|
||||
spoiler=i.has_spoiler,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
|
|
@ -284,17 +324,19 @@ class SendMediaGroup:
|
|||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
else:
|
||||
media = utils.get_input_media_from_file_id(i.media, FileType.VIDEO)
|
||||
else:
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
spoiler=i.has_spoiler,
|
||||
mime_type=self.guess_mime_type(getattr(i.media, "name", "video.mp4")) or "video/mp4",
|
||||
attributes=[
|
||||
|
|
@ -304,10 +346,10 @@ class SendMediaGroup:
|
|||
w=i.width,
|
||||
h=i.height
|
||||
),
|
||||
raw.types.DocumentAttributeFilename(file_name=getattr(i.media, "name", "video.mp4"))
|
||||
]
|
||||
)
|
||||
)
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or getattr(i.media, "name", "video.mp4")),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
|
|
@ -316,127 +358,135 @@ class SendMediaGroup:
|
|||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
),
|
||||
spoiler=i.has_spoiler
|
||||
spoiler=i.has_spoiler,
|
||||
)
|
||||
elif isinstance(i, types.InputMediaAudio):
|
||||
if isinstance(i.media, str):
|
||||
if os.path.isfile(i.media):
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
mime_type=self.guess_mime_type(i.media) or "audio/mpeg",
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
attributes=[
|
||||
raw.types.DocumentAttributeAudio(
|
||||
duration=i.duration,
|
||||
performer=i.performer,
|
||||
title=i.title
|
||||
),
|
||||
raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
|
||||
]
|
||||
)
|
||||
)
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or os.path.basename(i.media)),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
elif re.match("^https?://", i.media):
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaDocumentExternal(
|
||||
url=i.media
|
||||
)
|
||||
)
|
||||
url=i.media,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
else:
|
||||
media = utils.get_input_media_from_file_id(i.media, FileType.AUDIO)
|
||||
else:
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
mime_type=self.guess_mime_type(getattr(i.media, "name", "audio.mp3")) or "audio/mpeg",
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
attributes=[
|
||||
raw.types.DocumentAttributeAudio(
|
||||
duration=i.duration,
|
||||
performer=i.performer,
|
||||
title=i.title
|
||||
),
|
||||
raw.types.DocumentAttributeFilename(file_name=getattr(i.media, "name", "audio.mp3"))
|
||||
]
|
||||
)
|
||||
)
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or getattr(i.media, "name", "audio.mp3")),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
elif isinstance(i, types.InputMediaDocument):
|
||||
if isinstance(i.media, str):
|
||||
if os.path.isfile(i.media):
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaUploadedDocument(
|
||||
mime_type=self.guess_mime_type(i.media) or "application/zip",
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
attributes=[
|
||||
raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
|
||||
]
|
||||
)
|
||||
)
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or os.path.basename(i.media)),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
elif re.match("^https?://", i.media):
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=raw.types.InputMediaDocumentExternal(
|
||||
url=i.media
|
||||
)
|
||||
)
|
||||
url=i.media,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
else:
|
||||
media = utils.get_input_media_from_file_id(i.media, FileType.DOCUMENT)
|
||||
else:
|
||||
thumb = await self.save_file(i.thumb)
|
||||
file = await self.save_file(i.media, progress=progress, progress_args=progress_args)
|
||||
media = await self.invoke(
|
||||
raw.functions.messages.UploadMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
|
|
@ -444,21 +494,21 @@ class SendMediaGroup:
|
|||
mime_type=self.guess_mime_type(
|
||||
getattr(i.media, "name", "file.zip")
|
||||
) or "application/zip",
|
||||
file=await self.save_file(i.media),
|
||||
thumb=await self.save_file(i.thumb),
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
attributes=[
|
||||
raw.types.DocumentAttributeFilename(file_name=getattr(i.media, "name", "file.zip"))
|
||||
]
|
||||
)
|
||||
)
|
||||
raw.types.DocumentAttributeFilename(file_name=i.file_name or getattr(i.media, "name", "file.zip")),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
media = raw.types.InputMediaDocument(
|
||||
id=raw.types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=media.document.file_reference
|
||||
)
|
||||
file_reference=media.document.file_reference,
|
||||
),
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"{i.__class__.__name__} is not a supported type for send_media_group")
|
||||
|
|
@ -467,8 +517,8 @@ class SendMediaGroup:
|
|||
raw.types.InputSingleMedia(
|
||||
media=media,
|
||||
random_id=self.rnd_id(),
|
||||
**(await utils.parse_text_entities(self, i.caption, i.parse_mode, i.caption_entities))
|
||||
)
|
||||
**(await utils.parse_text_entities(self, i.caption, i.parse_mode, i.caption_entities)),
|
||||
),
|
||||
)
|
||||
|
||||
rpc = raw.functions.messages.SendMultiMedia(
|
||||
|
|
@ -480,7 +530,7 @@ class SendMediaGroup:
|
|||
noforwards=protect_content,
|
||||
allow_paid_floodskip=allow_paid_broadcast,
|
||||
effect=message_effect_id,
|
||||
invert_media=invert_media
|
||||
invert_media=invert_media,
|
||||
)
|
||||
|
||||
if business_connection_id is not None:
|
||||
|
|
@ -489,7 +539,7 @@ class SendMediaGroup:
|
|||
connection_id=business_connection_id,
|
||||
query=rpc
|
||||
),
|
||||
sleep_threshold=60
|
||||
sleep_threshold=60,
|
||||
)
|
||||
else:
|
||||
r = await self.invoke(rpc, sleep_threshold=60)
|
||||
|
|
@ -505,7 +555,7 @@ class SendMediaGroup:
|
|||
r.updates
|
||||
)],
|
||||
users=r.users,
|
||||
chats=r.chats
|
||||
chats=r.chats,
|
||||
),
|
||||
business_connection_id=business_connection_id
|
||||
business_connection_id=business_connection_id,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class SendMessage:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: int = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -100,6 +101,11 @@ class SendMessage:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of the monoforum.
|
||||
for reply to message from a monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -174,6 +180,7 @@ class SendMessage:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class SendPhoto:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -122,6 +123,11 @@ class SendPhoto:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -203,6 +209,7 @@ class SendPhoto:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class SendSticker:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -104,6 +105,11 @@ class SendSticker:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -178,6 +184,7 @@ class SendSticker:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class SendVideo:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
cover: Union[str, BinaryIO] = None,
|
||||
|
|
@ -58,6 +59,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",
|
||||
|
|
@ -150,6 +152,11 @@ class SendVideo:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -180,6 +187,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.
|
||||
|
||||
|
|
@ -246,6 +257,7 @@ class SendVideo:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
@ -298,7 +310,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 +328,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 +342,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=[
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class SendVideoNote:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
|
|
@ -118,6 +119,11 @@ class SendVideoNote:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -197,6 +203,7 @@ class SendVideoNote:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class SendVoice:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -121,6 +122,11 @@ class SendVoice:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -189,6 +195,7 @@ class SendVoice:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class SendWebPage:
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
reply_to_chat_id: Union[int, str] = None,
|
||||
reply_to_monoforum_id: Union[int, str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
schedule_date: datetime = None,
|
||||
|
|
@ -106,6 +107,11 @@ class SendWebPage:
|
|||
for reply to message from another chat.
|
||||
You can also use chat public link in form of *t.me/<username>* (str).
|
||||
|
||||
reply_to_monoforum_id (``int`` | ``str``, *optional*):
|
||||
Unique identifier for the target user of monoforum.
|
||||
for reply to message from monoforum.
|
||||
for channel administrators only.
|
||||
|
||||
quote_text (``str``, *optional*):
|
||||
Text to quote.
|
||||
for reply_to_message only.
|
||||
|
|
@ -161,6 +167,7 @@ class SendWebPage:
|
|||
reply_to_story_id=reply_to_story_id,
|
||||
message_thread_id=message_thread_id,
|
||||
reply_to_chat_id=reply_to_chat_id,
|
||||
reply_to_monoforum_id=reply_to_monoforum_id,
|
||||
quote_text=quote_text,
|
||||
quote_entities=quote_entities,
|
||||
parse_mode=parse_mode
|
||||
|
|
|
|||
|
|
@ -31,11 +31,15 @@ from .get_chat_gifts_count import GetChatGiftsCount
|
|||
from .get_chat_gifts import GetChatGifts
|
||||
from .hide_gift import HideGift
|
||||
from .refund_stars_payment import RefundStarPayment
|
||||
from .search_gifts_for_resale import SearchGiftsForResale
|
||||
from .send_invoice import SendInvoice
|
||||
from .send_paid_media import SendPaidMedia
|
||||
from .send_paid_reaction import SendPaidReaction
|
||||
from .send_payment_form import SendPaymentForm
|
||||
from .send_gift import SendGift
|
||||
from .send_resold_gift import SendResoldGift
|
||||
from .set_gift_resale_price import SetGiftResalePrice
|
||||
from .set_pinned_gifts import SetPinnedGifts
|
||||
from .show_gift import ShowGift
|
||||
from .transfer_gift import TransferGift
|
||||
from .upgrade_gift import UpgradeGift
|
||||
|
|
@ -55,11 +59,15 @@ class Payments(
|
|||
GetChatGifts,
|
||||
HideGift,
|
||||
RefundStarPayment,
|
||||
SearchGiftsForResale,
|
||||
SendPaidReaction,
|
||||
SendPaidMedia,
|
||||
SendInvoice,
|
||||
SendPaymentForm,
|
||||
SendGift,
|
||||
SendResoldGift,
|
||||
SetGiftResalePrice,
|
||||
SetPinnedGifts,
|
||||
ShowGift,
|
||||
TransferGift,
|
||||
UpgradeGift
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class GetUpgradedGift:
|
|||
# Get information about upgraded gift by slug
|
||||
gift = await client.get_upgraded_gift("SignetRing-903")
|
||||
"""
|
||||
match = re.match(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:nft/|\+))([\w-]+)$", link)
|
||||
match = self.UPGRADED_GIFT_RE.match(link)
|
||||
|
||||
if match:
|
||||
slug = match.group(1)
|
||||
|
|
|
|||
110
pyrogram/methods/payments/search_gifts_for_resale.py
Normal file
110
pyrogram/methods/payments/search_gifts_for_resale.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import enums, raw, types
|
||||
|
||||
|
||||
class SearchGiftsForResale:
|
||||
async def search_gifts_for_resale(
|
||||
self: "pyrogram.Client",
|
||||
gift_id: int,
|
||||
order: "enums.GiftForResaleOrder" = enums.GiftForResaleOrder.CHANGE_DATE,
|
||||
attributes: Optional[List["types.UpgradedGiftAttributeId"]] = None,
|
||||
limit: int = 0,
|
||||
offset: str = ""
|
||||
):
|
||||
"""Get upgraded gifts that can be bought from other owners.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
gift_id (``int``):
|
||||
Identifier of the regular gift that was upgraded to a unique gift.
|
||||
|
||||
order (:obj:`~pyrogram.enums.GiftForResaleOrder`):
|
||||
Order in which the results will be sorted.
|
||||
|
||||
attributes (List of :obj:`~pyrogram.types.UpgradedGiftAttributeId`, *optional*):
|
||||
Attributes used to filter received gifts.
|
||||
If multiple attributes of the same type are specified, then all of them are allowed.
|
||||
If none attributes of specific type are specified, then all values for this attribute type are allowed.
|
||||
|
||||
limit (``int``, *optional*):
|
||||
The maximum number of gifts to return. Default is 0 (no limit).
|
||||
|
||||
offset (``str``, *optional*):
|
||||
The offset from which to start returning results. Default is "" (no offset).
|
||||
|
||||
Returns:
|
||||
``Generator``: A generator yielding :obj:`~pyrogram.types.Gift` objects.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
async for gift in app.search_gifts_for_resale(gift_id=123456):
|
||||
print(gift)
|
||||
|
||||
# Buy first gift from resale market
|
||||
async for gift in app.search_gifts_for_resale(gift_id=123456, limit=1):
|
||||
await app.send_resold_gift(gift_link=gift.link, new_owner_chat_id="me") # or just use await gift.buy()
|
||||
"""
|
||||
current = 0
|
||||
total = abs(limit) or (1 << 31) - 1
|
||||
limit = min(100, total)
|
||||
|
||||
while True:
|
||||
r = await self.invoke(
|
||||
raw.functions.payments.GetResaleStarGifts(
|
||||
gift_id=gift_id,
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
sort_by_price=order == enums.GiftForResaleOrder.PRICE,
|
||||
sort_by_num=order == enums.GiftForResaleOrder.NUMBER,
|
||||
attributes=[attr.write() for attr in attributes] if attributes else None,
|
||||
|
||||
),
|
||||
sleep_threshold=60
|
||||
)
|
||||
|
||||
users = {i.id: i for i in r.users}
|
||||
chats = {i.id: i for i in r.chats}
|
||||
|
||||
gifts = [
|
||||
await types.Gift._parse(self, gift, users, chats)
|
||||
for gift in r.gifts
|
||||
]
|
||||
|
||||
if not gifts:
|
||||
return
|
||||
|
||||
for gift in gifts:
|
||||
yield gift
|
||||
|
||||
current += 1
|
||||
|
||||
if current >= total:
|
||||
return
|
||||
|
||||
offset = r.next_offset
|
||||
|
||||
if not offset:
|
||||
return
|
||||
89
pyrogram/methods/payments/send_resold_gift.py
Normal file
89
pyrogram/methods/payments/send_resold_gift.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from typing import Optional, Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw, types, utils
|
||||
|
||||
|
||||
class SendResoldGift:
|
||||
async def send_resold_gift(
|
||||
self: "pyrogram.Client",
|
||||
gift_link: str,
|
||||
new_owner_chat_id: Union[int, str],
|
||||
) -> Optional["types.Message"]:
|
||||
"""Send an upgraded gift that is available for resale to another user or channel chat.
|
||||
|
||||
.. note::
|
||||
|
||||
Gifts already owned by the current user must be transferred using :meth:`~pyrogram.Client.transfer_gift` and can't be passed to this method.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
gift_link (``str``):
|
||||
Link to the gift.
|
||||
|
||||
new_owner_chat_id (``int`` | ``str``):
|
||||
Unique identifier (int) or username (str) of the target chat you want to transfer the star gift to.
|
||||
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||
|
||||
Returns:
|
||||
:obj:`~pyrogram.types.Message`: On success, the sent message is returned.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
# Transfer gift to another user
|
||||
await app.send_resold_gift(gift_link="https://t.me/nft/NekoHelmet-9215", new_owner_chat_id=123)
|
||||
"""
|
||||
match = self.UPGRADED_GIFT_RE.match(gift_link)
|
||||
|
||||
if not match:
|
||||
raise ValueError(
|
||||
"Invalid gift link provided."
|
||||
)
|
||||
|
||||
peer = await self.resolve_peer(new_owner_chat_id)
|
||||
|
||||
invoice = raw.types.InputInvoiceStarGiftResale(
|
||||
slug=match.group(1),
|
||||
to_id=peer
|
||||
)
|
||||
|
||||
r = await self.invoke(
|
||||
raw.functions.payments.SendStarsForm(
|
||||
form_id=(await self.invoke(
|
||||
raw.functions.payments.GetPaymentForm(
|
||||
invoice=invoice
|
||||
),
|
||||
)).form_id,
|
||||
invoice=invoice
|
||||
),
|
||||
)
|
||||
|
||||
messages = await utils.parse_messages(
|
||||
client=self,
|
||||
messages=r.updates if isinstance(r, raw.types.payments.PaymentResult) else r
|
||||
)
|
||||
|
||||
return messages[0] if messages else None
|
||||
82
pyrogram/methods/payments/set_gift_resale_price.py
Normal file
82
pyrogram/methods/payments/set_gift_resale_price.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
class SetGiftResalePrice:
|
||||
async def set_gift_resale_price(
|
||||
self: "pyrogram.Client",
|
||||
owned_gift_id: str,
|
||||
resale_star_count: int
|
||||
) -> bool:
|
||||
"""Change resale price of a unique gift owned by the current user.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
owned_gift_id (``str``):
|
||||
Unique identifier of the target gift.
|
||||
For a user gift, you can use the message ID (int) of the gift message.
|
||||
For a channel gift, you can use the packed format `chatID_savedID` (str).
|
||||
For a upgraded gift, you can use the gift link.
|
||||
|
||||
resale_star_count (``int``):
|
||||
The new price for the unique gift. Pass 0 to disallow gift resale.
|
||||
|
||||
Returns:
|
||||
``bool``: On success, True is returned.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
# Change resale price of a unique gift
|
||||
await app.set_gift_resale_price(owned_gift_id="123456", resale_star_count=100)
|
||||
"""
|
||||
if not isinstance(owned_gift_id, str):
|
||||
raise ValueError(f"owned_gift_id has to be str, but {type(owned_gift_id)} was provided")
|
||||
|
||||
saved_gift_match = re.match(r"^(-\d+)_(\d+)$", owned_gift_id)
|
||||
slug_match = self.UPGRADED_GIFT_RE.match(owned_gift_id)
|
||||
|
||||
if saved_gift_match:
|
||||
stargift = raw.types.InputSavedStarGiftChat(
|
||||
peer=await self.resolve_peer(saved_gift_match.group(1)),
|
||||
saved_id=int(saved_gift_match.group(2))
|
||||
)
|
||||
elif slug_match:
|
||||
stargift = raw.types.InputSavedStarGiftSlug(
|
||||
slug=slug_match.group(1)
|
||||
)
|
||||
else:
|
||||
stargift = raw.types.InputSavedStarGiftUser(
|
||||
msg_id=int(owned_gift_id)
|
||||
)
|
||||
|
||||
await self.invoke(
|
||||
raw.functions.payments.UpdateStarGiftPrice(
|
||||
stargift=stargift,
|
||||
resell_stars=resale_star_count
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
95
pyrogram/methods/payments/set_pinned_gifts.py
Normal file
95
pyrogram/methods/payments/set_pinned_gifts.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
from typing import List, Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
class SetPinnedGifts:
|
||||
async def set_pinned_gifts(
|
||||
self: "pyrogram.Client",
|
||||
owner_id: Union[int, str],
|
||||
owned_gift_ids: List[str],
|
||||
) -> bool:
|
||||
"""Change the list of pinned gifts on the current user.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
owner_id (``int`` | ``str``):
|
||||
Unique identifier (int) or username (str) of the target chat.
|
||||
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||
|
||||
owned_gift_ids (List of ``str``):
|
||||
New list of pinned gifts.
|
||||
All gifts must be upgraded and saved on the profile page first.
|
||||
For a user gift, you can use the message ID (int) of the gift message.
|
||||
For a channel gift, you can use the packed format `chatID_savedID` (str).
|
||||
For a upgraded gift, you can use the gift link.
|
||||
|
||||
Returns:
|
||||
``bool``: On success, True is returned.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
# Set pinned gifts in user profile
|
||||
await app.set_pinned_gifts(received_gift_ids=["123", "456"])
|
||||
"""
|
||||
stargifts = []
|
||||
|
||||
for gift in owned_gift_ids:
|
||||
if not isinstance(gift, str):
|
||||
raise ValueError(f"gift id has to be str, but {type(gift)} was provided")
|
||||
|
||||
saved_gift_match = re.match(r"^(\d+)_(\d+)$", str(gift))
|
||||
slug_match = self.UPGRADED_GIFT_RE.match(str(gift))
|
||||
|
||||
if saved_gift_match:
|
||||
stargifts.append(
|
||||
raw.types.InputSavedStarGiftChat(
|
||||
peer=await self.resolve_peer(saved_gift_match.group(1)),
|
||||
saved_id=int(saved_gift_match.group(2))
|
||||
)
|
||||
)
|
||||
elif slug_match:
|
||||
stargifts.append(
|
||||
raw.types.InputSavedStarGiftSlug(
|
||||
slug=slug_match.group(1)
|
||||
)
|
||||
)
|
||||
else:
|
||||
stargifts.append(
|
||||
raw.types.InputSavedStarGiftUser(
|
||||
msg_id=int(gift)
|
||||
)
|
||||
)
|
||||
|
||||
r = await self.invoke(
|
||||
raw.functions.payments.ToggleStarGiftsPinnedToTop(
|
||||
peer=await self.resolve_peer(owner_id),
|
||||
stargift=stargifts
|
||||
)
|
||||
)
|
||||
|
||||
return r
|
||||
25
pyrogram/methods/phone/__init__.py
Normal file
25
pyrogram/methods/phone/__init__.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .get_call_members import GetCallMembers
|
||||
|
||||
|
||||
class Phone(
|
||||
GetCallMembers
|
||||
):
|
||||
pass
|
||||
103
pyrogram/methods/phone/get_call_members.py
Normal file
103
pyrogram/methods/phone/get_call_members.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Union, AsyncGenerator
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import types, raw
|
||||
|
||||
|
||||
class GetCallMembers:
|
||||
async def get_call_members(
|
||||
self: "pyrogram.Client",
|
||||
chat_id: Union[int, str],
|
||||
limit: int = 0
|
||||
) -> AsyncGenerator["types.GroupCallMember", None]:
|
||||
"""Get the members list of a chat call.
|
||||
|
||||
A chat can be either a basic group or a supergroup.
|
||||
|
||||
.. include:: /_includes/usable-by/users.rst
|
||||
|
||||
Parameters:
|
||||
chat_id (``int`` | ``str``):
|
||||
Unique identifier (int) or username (str) of the target chat.
|
||||
|
||||
limit (``int``, *optional*):
|
||||
Limits the number of members to be retrieved.
|
||||
|
||||
Returns:
|
||||
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.GroupCallMember` objects is returned.
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
# Get members
|
||||
async for member in app.get_call_members(chat_id):
|
||||
print(member)
|
||||
"""
|
||||
peer = await self.resolve_peer(chat_id)
|
||||
|
||||
if isinstance(peer, raw.types.InputPeerChannel):
|
||||
r = await self.invoke(raw.functions.channels.GetFullChannel(channel=peer))
|
||||
elif isinstance(peer, raw.types.InputPeerChat):
|
||||
r = await self.invoke(raw.functions.messages.GetFullChat(chat_id=peer.chat_id))
|
||||
else:
|
||||
raise ValueError("Target chat should be group, supergroup or channel.")
|
||||
|
||||
full_chat = r.full_chat
|
||||
|
||||
if not getattr(full_chat, "call", None):
|
||||
raise ValueError("There is no active call in this chat.")
|
||||
|
||||
current = 0
|
||||
offset = ""
|
||||
total = abs(limit) or (1 << 31) - 1
|
||||
limit = min(20, total)
|
||||
|
||||
while True:
|
||||
r = await self.invoke(
|
||||
raw.functions.phone.GetGroupParticipants(
|
||||
call=full_chat.call,
|
||||
ids=[],
|
||||
sources=[],
|
||||
offset=offset,
|
||||
limit=limit
|
||||
),
|
||||
sleep_threshold=60
|
||||
)
|
||||
|
||||
users = {u.id: u for u in r.users}
|
||||
chats = {c.id: c for c in r.chats}
|
||||
members = [
|
||||
types.GroupCallMember._parse(self, member, users, chats)
|
||||
for member in r.participants
|
||||
]
|
||||
|
||||
if not members:
|
||||
return
|
||||
|
||||
offset = r.next_offset
|
||||
|
||||
for member in members:
|
||||
yield member
|
||||
|
||||
current += 1
|
||||
|
||||
if current >= total:
|
||||
return
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
from .add_handler import AddHandler
|
||||
from .export_session_string import ExportSessionString
|
||||
from .ping import Ping
|
||||
from .remove_handler import RemoveHandler
|
||||
from .remove_error_handler import RemoveErrorHandler
|
||||
from .restart import Restart
|
||||
|
|
@ -32,6 +33,7 @@ from .stop_transmission import StopTransmission
|
|||
class Utilities(
|
||||
AddHandler,
|
||||
ExportSessionString,
|
||||
Ping,
|
||||
RemoveHandler,
|
||||
RemoveErrorHandler,
|
||||
Restart,
|
||||
|
|
|
|||
46
pyrogram/methods/utilities/ping.py
Normal file
46
pyrogram/methods/utilities/ping.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from time import time
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
class Ping:
|
||||
async def ping(self: "pyrogram.Client"):
|
||||
"""Measure the round-trip time (RTT) to the Telegram server.
|
||||
|
||||
The ping method sends a request to the Telegram server and measures the time it takes to receive a response.
|
||||
This can be useful for monitoring network latency and ensuring a stable connection to the server.
|
||||
|
||||
Returns:
|
||||
float: The round-trip time in milliseconds (ms).
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
latency = await app.ping()
|
||||
print(f"Ping: {latency} ms")
|
||||
"""
|
||||
start_time = time()
|
||||
await self.invoke(
|
||||
raw.functions.ping.Ping(ping_id=self.rnd_id()),
|
||||
)
|
||||
return round((time() - start_time) * 1000.0, 3)
|
||||
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
46
pyrogram/types/authorization/login_token.py
Normal file
46
pyrogram/types/authorization/login_token.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ..object import Object
|
||||
|
||||
from pyrogram import raw
|
||||
|
||||
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def _parse(login_token: "raw.base.LoginToken") -> "LoginToken":
|
||||
return LoginToken(
|
||||
token=login_token.token,
|
||||
expires=login_token.expires,
|
||||
)
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import raw, types
|
||||
from pyrogram import enums, raw, types
|
||||
from ..object import Object
|
||||
from typing import Union
|
||||
|
||||
|
|
@ -99,15 +99,21 @@ class KeyboardButton(Object):
|
|||
|
||||
if isinstance(b, raw.types.KeyboardButtonRequestPeer):
|
||||
if isinstance(b.peer_type, raw.types.RequestPeerTypeBroadcast):
|
||||
user_privileges = getattr(b.peer_type, "user_admin_rights", None)
|
||||
bot_privileges = getattr(b.peer_type, "bot_admin_rights", None)
|
||||
return KeyboardButton(
|
||||
text=b.text,
|
||||
request_chat=types.RequestPeerTypeChannel(
|
||||
is_creator=b.peer_type.creator,
|
||||
is_username=b.peer_type.has_username,
|
||||
max=b.max_quantity
|
||||
max=b.max_quantity,
|
||||
user_privileges=user_privileges,
|
||||
bot_privileges=bot_privileges
|
||||
)
|
||||
)
|
||||
if isinstance(b.peer_type, raw.types.RequestPeerTypeChat):
|
||||
user_privileges = getattr(b.peer_type, "user_admin_rights", None)
|
||||
bot_privileges = getattr(b.peer_type, "bot_admin_rights", None)
|
||||
return KeyboardButton(
|
||||
text=b.text,
|
||||
request_chat=types.RequestPeerTypeChat(
|
||||
|
|
@ -115,7 +121,9 @@ class KeyboardButton(Object):
|
|||
is_bot_participant=b.peer_type.bot_participant,
|
||||
is_username=b.peer_type.has_username,
|
||||
is_forum=b.peer_type.forum,
|
||||
max=b.max_quantity
|
||||
max=b.max_quantity,
|
||||
user_privileges=user_privileges,
|
||||
bot_privileges=bot_privileges
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -135,13 +143,52 @@ class KeyboardButton(Object):
|
|||
elif self.request_location:
|
||||
return raw.types.KeyboardButtonRequestGeoLocation(text=self.text)
|
||||
elif self.request_chat:
|
||||
user_privileges = self.request_chat.user_privileges
|
||||
bot_privileges = self.request_chat.bot_privileges
|
||||
|
||||
user_admin_rights = raw.types.ChatAdminRights(
|
||||
change_info=user_privileges.can_change_info,
|
||||
post_messages=user_privileges.can_post_messages,
|
||||
post_stories=user_privileges.can_post_stories,
|
||||
edit_messages=user_privileges.can_edit_messages,
|
||||
edit_stories=user_privileges.can_post_stories,
|
||||
delete_messages=user_privileges.can_delete_messages,
|
||||
delete_stories=user_privileges.can_delete_stories,
|
||||
ban_users=user_privileges.can_restrict_members,
|
||||
invite_users=user_privileges.can_invite_users,
|
||||
pin_messages=user_privileges.can_pin_messages,
|
||||
add_admins=user_privileges.can_promote_members,
|
||||
anonymous=user_privileges.is_anonymous,
|
||||
manage_call=user_privileges.can_manage_video_chats,
|
||||
other=user_privileges.can_manage_chat
|
||||
) if user_privileges else None
|
||||
|
||||
bot_admin_rights = raw.types.ChatAdminRights(
|
||||
change_info=bot_privileges.can_change_info,
|
||||
post_messages=bot_privileges.can_post_messages,
|
||||
post_stories=bot_privileges.can_post_stories,
|
||||
edit_messages=bot_privileges.can_edit_messages,
|
||||
edit_stories=bot_privileges.can_post_stories,
|
||||
delete_messages=bot_privileges.can_delete_messages,
|
||||
delete_stories=bot_privileges.can_delete_stories,
|
||||
ban_users=bot_privileges.can_restrict_members,
|
||||
invite_users=bot_privileges.can_invite_users,
|
||||
pin_messages=bot_privileges.can_pin_messages,
|
||||
add_admins=bot_privileges.can_promote_members,
|
||||
anonymous=bot_privileges.is_anonymous,
|
||||
manage_call=bot_privileges.can_manage_video_chats,
|
||||
other=bot_privileges.can_manage_chat
|
||||
) if bot_privileges else None
|
||||
|
||||
if isinstance(self.request_chat, types.RequestPeerTypeChannel):
|
||||
return raw.types.InputKeyboardButtonRequestPeer(
|
||||
text=self.text,
|
||||
button_id=self.request_chat.button_id,
|
||||
peer_type=raw.types.RequestPeerTypeBroadcast(
|
||||
creator=self.request_chat.is_creator,
|
||||
has_username=self.request_chat.is_username
|
||||
has_username=self.request_chat.is_username,
|
||||
user_admin_rights=user_admin_rights,
|
||||
bot_admin_rights=bot_admin_rights
|
||||
),
|
||||
max_quantity=self.request_chat.max,
|
||||
name_requested=self.request_chat.is_name_requested,
|
||||
|
|
@ -155,7 +202,9 @@ class KeyboardButton(Object):
|
|||
creator=self.request_chat.is_creator,
|
||||
bot_participant=self.request_chat.is_bot_participant,
|
||||
has_username=self.request_chat.is_username,
|
||||
forum=self.request_chat.is_forum
|
||||
forum=self.request_chat.is_forum,
|
||||
user_admin_rights=user_admin_rights,
|
||||
bot_admin_rights=bot_admin_rights
|
||||
),
|
||||
max_quantity=self.request_chat.max,
|
||||
name_requested=self.request_chat.is_name_requested,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import types
|
||||
|
||||
from ..object import Object
|
||||
|
||||
|
||||
|
|
@ -47,17 +49,25 @@ class RequestPeerTypeChannel(Object):
|
|||
is_photo_requested (``bool``, *optional*):
|
||||
If True, Channel photo is requested.
|
||||
default True.
|
||||
|
||||
user_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
|
||||
Privileged actions that an user administrator is able to take.
|
||||
|
||||
bot_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
|
||||
Privileged actions that a bot administrator is able to take.
|
||||
""" # TODO user_admin_rights, bot_admin_rights
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
button_id: int=0,
|
||||
is_creator: bool=None,
|
||||
is_username: bool=None,
|
||||
max: int=1,
|
||||
is_name_requested: bool=True,
|
||||
is_username_requested: bool=True,
|
||||
is_photo_requested: bool=True
|
||||
button_id: int = 0,
|
||||
is_creator: bool = None,
|
||||
is_username: bool = None,
|
||||
max: int = 1,
|
||||
is_name_requested: bool = True,
|
||||
is_username_requested: bool = True,
|
||||
is_photo_requested: bool = True,
|
||||
user_privileges: "types.ChatPrivileges" = None,
|
||||
bot_privileges: "types.ChatPrivileges" = None
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
|
|
@ -68,3 +78,6 @@ class RequestPeerTypeChannel(Object):
|
|||
self.is_name_requested = is_name_requested
|
||||
self.is_username_requested = is_username_requested
|
||||
self.is_photo_requested = is_photo_requested
|
||||
self.user_privileges = user_privileges
|
||||
self.bot_privileges = bot_privileges
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import types
|
||||
|
||||
from ..object import Object
|
||||
|
||||
|
||||
|
|
@ -53,19 +55,27 @@ class RequestPeerTypeChat(Object):
|
|||
is_photo_requested (``bool``, *optional*):
|
||||
If True, Chat photo is requested.
|
||||
default True.
|
||||
|
||||
user_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
|
||||
Privileged actions that an user administrator is able to take.
|
||||
|
||||
bot_privileges (:obj:`~pyrogram.types.ChatPrivileges`, *optional*):
|
||||
Privileged actions that a bot administrator is able to take.
|
||||
""" # TODO user_admin_rights, bot_admin_rights
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
button_id: int=0,
|
||||
is_creator: bool=None,
|
||||
is_bot_participant: bool=None,
|
||||
is_username: bool=None,
|
||||
is_forum: bool=None,
|
||||
max: int=1,
|
||||
is_name_requested: bool=True,
|
||||
is_username_requested: bool=True,
|
||||
is_photo_requested: bool=True
|
||||
button_id: int = 0,
|
||||
is_creator: bool = None,
|
||||
is_bot_participant: bool = None,
|
||||
is_username: bool = None,
|
||||
is_forum: bool = None,
|
||||
max: int = 1,
|
||||
is_name_requested: bool = True,
|
||||
is_username_requested: bool = True,
|
||||
is_photo_requested: bool = True,
|
||||
user_privileges: "types.ChatPrivileges" = None,
|
||||
bot_privileges: "types.ChatPrivileges" = None
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
|
|
@ -78,3 +88,5 @@ class RequestPeerTypeChat(Object):
|
|||
self.is_name_requested = is_name_requested
|
||||
self.is_username_requested = is_username_requested
|
||||
self.is_photo_requested = is_photo_requested
|
||||
self.user_privileges = user_privileges
|
||||
self.bot_privileges = bot_privileges
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ class InputMediaAudio(InputMedia):
|
|||
|
||||
title (``str``, *optional*):
|
||||
Title of the audio
|
||||
|
||||
file_name (``str``, *optional*):
|
||||
File name of the audio sent.
|
||||
Defaults to file's path basename.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
|
@ -73,7 +77,8 @@ class InputMediaAudio(InputMedia):
|
|||
caption_entities: List[MessageEntity] = None,
|
||||
duration: int = 0,
|
||||
performer: str = "",
|
||||
title: str = ""
|
||||
title: str = "",
|
||||
file_name: str = None
|
||||
):
|
||||
super().__init__(media, caption, parse_mode, caption_entities)
|
||||
|
||||
|
|
@ -81,3 +86,4 @@ class InputMediaAudio(InputMedia):
|
|||
self.duration = duration
|
||||
self.performer = performer
|
||||
self.title = title
|
||||
self.file_name = file_name
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ class InputMediaDocument(InputMedia):
|
|||
|
||||
caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
|
||||
List of special entities that appear in the caption, which can be specified instead of *parse_mode*.
|
||||
|
||||
file_name (``str``, *optional*):
|
||||
File name of the document sent.
|
||||
Defaults to file's path basename.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
|
@ -59,8 +63,10 @@ class InputMediaDocument(InputMedia):
|
|||
thumb: str = None,
|
||||
caption: str = "",
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
caption_entities: List[MessageEntity] = None
|
||||
caption_entities: List[MessageEntity] = None,
|
||||
file_name: str = None
|
||||
):
|
||||
super().__init__(media, caption, parse_mode, caption_entities)
|
||||
|
||||
self.thumb = thumb
|
||||
self.file_name = file_name
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ class InputMediaVideo(InputMedia):
|
|||
duration (``int``, *optional*):
|
||||
Video duration.
|
||||
|
||||
file_name (``str``, *optional*):
|
||||
File name of the video sent.
|
||||
Defaults to file's path basename.
|
||||
|
||||
supports_streaming (``bool``, *optional*):
|
||||
Pass True, if the uploaded video is suitable for streaming.
|
||||
|
||||
|
|
@ -79,6 +83,7 @@ class InputMediaVideo(InputMedia):
|
|||
width: int = 0,
|
||||
height: int = 0,
|
||||
duration: int = 0,
|
||||
file_name: str = None,
|
||||
supports_streaming: bool = True,
|
||||
has_spoiler: bool = None,
|
||||
):
|
||||
|
|
@ -88,5 +93,6 @@ class InputMediaVideo(InputMedia):
|
|||
self.width = width
|
||||
self.height = height
|
||||
self.duration = duration
|
||||
self.file_name = file_name
|
||||
self.supports_streaming = supports_streaming
|
||||
self.has_spoiler = has_spoiler
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
from .input_message_content import InputMessageContent
|
||||
from .input_reply_to_message import InputReplyToMessage
|
||||
from .input_reply_to_monoforum import InputReplyToMonoforum
|
||||
from .input_reply_to_story import InputReplyToStory
|
||||
from .input_text_message_content import InputTextMessageContent
|
||||
from .input_location_message_content import InputLocationMessageContent
|
||||
|
|
@ -29,6 +30,7 @@ from .input_invoice_message_content import InputInvoiceMessageContent
|
|||
__all__ = [
|
||||
"InputMessageContent",
|
||||
"InputReplyToMessage",
|
||||
"InputReplyToMonoforum",
|
||||
"InputReplyToStory",
|
||||
"InputTextMessageContent",
|
||||
"InputLocationMessageContent",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import raw
|
||||
from ..object import Object
|
||||
|
||||
|
||||
class InputReplyToMonoforum(Object):
|
||||
"""Contains information about a target replied monoforum.
|
||||
|
||||
|
||||
Parameters:
|
||||
monoforum_peer (:obj:`~pyrogram.raw.types.InputPeer`):
|
||||
An InputPeer.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, *,
|
||||
monoforum_peer: "raw.types.InputPeer"
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.monoforum_peer = monoforum_peer
|
||||
|
||||
def write(self):
|
||||
return raw.types.InputReplyToMonoForum(
|
||||
monoforum_peer_id=self.monoforum_peer
|
||||
).write()
|
||||
|
|
@ -480,6 +480,7 @@ class Message(Object, Update):
|
|||
gift_code: "types.GiftCode" = None,
|
||||
gift: "types.Gift" = None,
|
||||
screenshot_taken: "types.ScreenshotTaken" = None,
|
||||
paid_message_price_changed: "types.PaidMessagePriceChanged" = None,
|
||||
invoice: "types.Invoice" = None,
|
||||
story: Union["types.MessageStory", "types.Story"] = None,
|
||||
alternative_videos: List["types.AlternativeVideo"] = None,
|
||||
|
|
@ -596,6 +597,7 @@ class Message(Object, Update):
|
|||
self.gift_code = gift_code
|
||||
self.gift = gift
|
||||
self.screenshot_taken = screenshot_taken
|
||||
self.paid_message_price_changed = paid_message_price_changed
|
||||
self.invoice = invoice
|
||||
self.story = story
|
||||
self.video = video
|
||||
|
|
@ -760,6 +762,7 @@ class Message(Object, Update):
|
|||
gift_code = None
|
||||
gift = None
|
||||
screenshot_taken = None
|
||||
paid_message_price_changed = None
|
||||
|
||||
service_type = None
|
||||
chat_join_type = None
|
||||
|
|
@ -808,7 +811,7 @@ class Message(Object, Update):
|
|||
service_type = enums.MessageServiceType.BOT_ALLOWED
|
||||
elif isinstance(action, raw.types.MessageActionRequestedPeer) or isinstance(action, raw.types.MessageActionRequestedPeerSentMe):
|
||||
chats_shared = await types.RequestedChats._parse(client, action)
|
||||
service_type = enums.MessageServiceType.ChatShared
|
||||
service_type = enums.MessageServiceType.CHAT_SHARED
|
||||
elif isinstance(action, raw.types.MessageActionTopicCreate):
|
||||
forum_topic_created = types.ForumTopicCreated._parse(message)
|
||||
service_type = enums.MessageServiceType.FORUM_TOPIC_CREATED
|
||||
|
|
@ -881,6 +884,9 @@ class Message(Object, Update):
|
|||
elif isinstance(action, raw.types.MessageActionScreenshotTaken):
|
||||
screenshot_taken = types.ScreenshotTaken()
|
||||
service_type = enums.MessageServiceType.SCREENSHOT_TAKEN
|
||||
elif isinstance(action, raw.types.MessageActionPaidMessagesPrice):
|
||||
paid_message_price_changed = types.PaidMessagePriceChanged._parse(action)
|
||||
service_type = enums.MessageServiceType.PAID_MESSAGE_PRICE_CHANGED
|
||||
|
||||
parsed_message = Message(
|
||||
id=message.id,
|
||||
|
|
@ -926,6 +932,7 @@ class Message(Object, Update):
|
|||
contact_registered=contact_registered,
|
||||
gift_code=gift_code,
|
||||
screenshot_taken=screenshot_taken,
|
||||
paid_message_price_changed=paid_message_price_changed,
|
||||
raw=message,
|
||||
chat_join_type=chat_join_type,
|
||||
client=client
|
||||
|
|
@ -970,7 +977,7 @@ class Message(Object, Update):
|
|||
else:
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id
|
||||
parsed_message.is_topic_message = True
|
||||
elif parsed_message.chat.is_forum and parsed_message.message_thread_id is None:
|
||||
elif parsed_message.chat.type == enums.ChatType.FORUM and parsed_message.message_thread_id is None:
|
||||
parsed_message.message_thread_id = 1
|
||||
parsed_message.is_topic_message = True
|
||||
|
||||
|
|
@ -1299,7 +1306,7 @@ class Message(Object, Update):
|
|||
pass
|
||||
else:
|
||||
parsed_message.reply_to_story = reply_to_story
|
||||
if parsed_message.chat.is_forum and parsed_message.message_thread_id is None:
|
||||
if parsed_message.chat.type == enums.ChatType.FORUM and parsed_message.message_thread_id is None:
|
||||
parsed_message.message_thread_id = 1
|
||||
parsed_message.is_topic_message = True
|
||||
|
||||
|
|
@ -1314,9 +1321,14 @@ class Message(Object, Update):
|
|||
self.chat.type in (enums.ChatType.GROUP, enums.ChatType.SUPERGROUP, enums.ChatType.CHANNEL)
|
||||
and self.chat.username
|
||||
):
|
||||
if self.chat.type == enums.ChatType.SUPERGROUP and self.message_thread_id:
|
||||
return f"https://t.me/{self.chat.username}/{self.message_thread_id}/{self.id}"
|
||||
return f"https://t.me/{self.chat.username}/{self.id}"
|
||||
else:
|
||||
return f"https://t.me/c/{utils.get_channel_id(self.chat.id)}/{self.id}"
|
||||
if self.chat.type == enums.ChatType.PRIVATE:
|
||||
return f"tg://openmessage?user_id={self.from_user.id}&message_id={self.id}"
|
||||
if self.message_thread_id:
|
||||
return f"https://t.me/c/{utils.get_channel_id(self.chat.id)}/{self.message_thread_id}/{self.id}"
|
||||
return f"https://t.me/c/{utils.get_channel_id(self.chat.id)}/{self.id}"
|
||||
|
||||
@property
|
||||
def content(self) -> str:
|
||||
|
|
@ -2779,7 +2791,9 @@ class Message(Object, Update):
|
|||
allow_paid_broadcast: bool = None,
|
||||
message_effect_id: int = None,
|
||||
parse_mode: Optional["enums.ParseMode"] = None,
|
||||
invert_media: bool = None
|
||||
invert_media: bool = None,
|
||||
progress: Callable = None,
|
||||
progress_args: tuple = (),
|
||||
) -> List["types.Message"]:
|
||||
"""Bound method *reply_media_group* of :obj:`~pyrogram.types.Message`.
|
||||
|
||||
|
|
@ -2840,6 +2854,28 @@ class Message(Object, Update):
|
|||
invert_media (``bool``, *optional*):
|
||||
Inverts the position of the media and caption.
|
||||
|
||||
progress (``Callable``, *optional*):
|
||||
Pass a callback function to view the file transmission progress.
|
||||
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||
detailed description) and will be called back each time a new file chunk has been successfully
|
||||
transmitted.
|
||||
|
||||
progress_args (``tuple``, *optional*):
|
||||
Extra custom arguments for the progress callback function.
|
||||
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||
object or a Client instance in order to edit the message with the updated progress status.
|
||||
|
||||
Other Parameters:
|
||||
current (``int``):
|
||||
The amount of bytes transmitted so far.
|
||||
|
||||
total (``int``):
|
||||
The total size of the file.
|
||||
|
||||
*args (``tuple``, *optional*):
|
||||
Extra custom arguments as defined in the ``progress_args`` parameter.
|
||||
You can either keep ``*args`` or add every single extra argument in your function signature.
|
||||
|
||||
Returns:
|
||||
On success, a :obj:`~pyrogram.types.Messages` object is returned containing all the
|
||||
single messages sent.
|
||||
|
|
@ -2878,7 +2914,9 @@ class Message(Object, Update):
|
|||
quote_entities=quote_entities,
|
||||
allow_paid_broadcast=allow_paid_broadcast,
|
||||
message_effect_id=message_effect_id,
|
||||
invert_media=invert_media
|
||||
invert_media=invert_media,
|
||||
progress=progress,
|
||||
progress_args=progress_args,
|
||||
)
|
||||
|
||||
async def reply_photo(
|
||||
|
|
@ -2896,6 +2934,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,
|
||||
|
|
@ -2985,6 +3025,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
|
||||
|
||||
|
|
@ -3059,6 +3105,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,
|
||||
|
|
@ -3611,9 +3659,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",
|
||||
|
|
@ -3731,9 +3781,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.
|
||||
|
||||
|
|
@ -3813,9 +3869,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,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class Wallpaper(Object):
|
|||
self,
|
||||
id: int,
|
||||
slug: str,
|
||||
document: "types.Document",
|
||||
document: "types.Document" = None,
|
||||
is_creator: bool = None,
|
||||
is_default: bool = None,
|
||||
is_pattern: bool = None,
|
||||
|
|
@ -73,7 +73,9 @@ class Wallpaper(Object):
|
|||
|
||||
@staticmethod
|
||||
def _parse(client: "pyrogram.Client", wallpaper: "raw.base.WallPaper") -> "Wallpaper":
|
||||
doc = wallpaper.document
|
||||
doc = None
|
||||
if not isinstance(wallpaper, raw.types.WallPaperNoFile):
|
||||
doc = wallpaper.document
|
||||
attributes = {type(i): i for i in doc.attributes}
|
||||
|
||||
file_name = getattr(
|
||||
|
|
@ -84,7 +86,7 @@ class Wallpaper(Object):
|
|||
return Wallpaper(
|
||||
id=wallpaper.id,
|
||||
slug=wallpaper.slug,
|
||||
document=types.Document._parse(client, doc, file_name),
|
||||
document=types.Document._parse(client, doc, file_name) if doc is not None else None,
|
||||
is_creator=getattr(wallpaper, "creator", None),
|
||||
is_default=getattr(wallpaper, "default", None),
|
||||
is_pattern=getattr(wallpaper, "pattern", None),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ from .input_stars_transaction import InputStarsTransaction
|
|||
from .invoice import Invoice
|
||||
from .labeled_price import LabeledPrice
|
||||
from .paid_media import PaidMedia
|
||||
from .paid_message_price_changed import PaidMessagePriceChanged
|
||||
from .payment_form import PaymentForm
|
||||
from .payment_info import PaymentInfo
|
||||
from .payment_refunded import PaymentRefunded
|
||||
|
|
@ -46,6 +47,7 @@ __all__ = [
|
|||
"Invoice",
|
||||
"LabeledPrice",
|
||||
"PaidMedia",
|
||||
"PaidMessagePriceChanged",
|
||||
"PaymentForm",
|
||||
"PaymentInfo",
|
||||
"PaymentRefunded",
|
||||
|
|
|
|||
|
|
@ -77,13 +77,16 @@ class Gift(Object):
|
|||
User who sent the star gift.
|
||||
|
||||
owner (:obj:`~pyrogram.types.Chat`, *optional*):
|
||||
Current gift owner.
|
||||
Only available if the nfts is in telegram.
|
||||
|
||||
owner_name (``str``, *optional*):
|
||||
Name of the user who received the star gift.
|
||||
|
||||
owner_address (``str``, *optional*):
|
||||
Address of the gift owner in TON blockchain.
|
||||
Only available if the nfts is in ton network.
|
||||
|
||||
ton_address (``str``, *optional*):
|
||||
Only available if the nfts is in ton network.
|
||||
|
||||
price (``int``, *optional*):
|
||||
Price of this gift in stars.
|
||||
|
|
@ -163,6 +166,7 @@ class Gift(Object):
|
|||
owner: Optional["types.Chat"] = None,
|
||||
owner_name: Optional[str] = None,
|
||||
owner_address: Optional[str] = None,
|
||||
ton_address: Optional[str] = None,
|
||||
price: Optional[int] = None,
|
||||
convert_price: Optional[int] = None,
|
||||
upgrade_price: Optional[int] = None,
|
||||
|
|
@ -201,6 +205,7 @@ class Gift(Object):
|
|||
self.owner = owner
|
||||
self.owner_name = owner_name
|
||||
self.owner_address = owner_address
|
||||
self.ton_address = ton_address
|
||||
self.price = price
|
||||
self.convert_price = convert_price
|
||||
self.upgrade_price = upgrade_price
|
||||
|
|
@ -277,9 +282,15 @@ class Gift(Object):
|
|||
) or None,
|
||||
available_amount=getattr(star_gift, "availability_issued", None),
|
||||
total_amount=getattr(star_gift, "availability_total", None),
|
||||
owner=types.Chat._parse_chat(client, users.get(owner_id) or chats.get(owner_id)),
|
||||
owner=(
|
||||
types.Chat._parse_chat(client, users.get(owner_id) or
|
||||
chats.get(owner_id))
|
||||
if owner_id is not None
|
||||
else None
|
||||
),
|
||||
owner_name=getattr(star_gift, "owner_name", None),
|
||||
owner_address=getattr(star_gift, "owner_address", None),
|
||||
ton_address=getattr(star_gift, "gift_address", None),
|
||||
is_upgraded=True,
|
||||
raw=star_gift,
|
||||
client=client
|
||||
|
|
|
|||
49
pyrogram/types/payments/paid_message_price_changed.py
Normal file
49
pyrogram/types/payments/paid_message_price_changed.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Pyrofork - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import List, Union
|
||||
|
||||
from pyrogram import raw
|
||||
from pyrogram import types
|
||||
from ..object import Object
|
||||
|
||||
|
||||
class PaidMessagePriceChanged(Object):
|
||||
"""A PaidMessagePriceChanged.
|
||||
|
||||
Parameters:
|
||||
stars_amount (``int``):
|
||||
Amount of stars.
|
||||
|
||||
extended_media (List of :obj:`~pyrogram.types.Animation` | :obj:`~pyrogram.types.ExtendedMediaPreview` | :obj:`~pyrogram.types.Photo` | :obj:`~pyrogram.types.Video`, *optional*):
|
||||
Extended media.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
stars_amount: int,
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.stars_amount = stars_amount
|
||||
|
||||
@staticmethod
|
||||
def _parse(action: "raw.types.MessageActionPaidMessagesPrice") -> "PaidMessagePriceChanged":
|
||||
return PaidMessagePriceChanged(
|
||||
stars_amount=action.stars
|
||||
)
|
||||
|
|
@ -43,6 +43,7 @@ from .chat_reactions import ChatReactions
|
|||
from .dialog import Dialog
|
||||
from .emoji_status import EmojiStatus
|
||||
from .folder import Folder
|
||||
from .group_call_member import GroupCallMember
|
||||
from .invite_link_importer import InviteLinkImporter
|
||||
from .restriction import Restriction
|
||||
from .user import User
|
||||
|
|
@ -106,5 +107,6 @@ __all__ = [
|
|||
"ChatPrivileges",
|
||||
"ChatJoiner",
|
||||
"EmojiStatus",
|
||||
"GroupCallMember",
|
||||
"ChatReactions"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ class Chat(Object):
|
|||
is_support (``bool``):
|
||||
True, if this chat is part of the Telegram support team. Users and bots only.
|
||||
|
||||
is_forum (``bool``, *optional*):
|
||||
True, if the supergroup chat is a forum
|
||||
|
||||
is_participants_hidden (``bool``, *optional*):
|
||||
True, if the chat members are hidden.
|
||||
Returned only in :meth:`~pyrogram.Client.get_chat`.
|
||||
|
|
@ -83,6 +80,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.
|
||||
|
||||
|
|
@ -167,6 +167,10 @@ class Chat(Object):
|
|||
The linked discussion group (in case of channels) or the linked channel (in case of supergroups).
|
||||
Returned only in :meth:`~pyrogram.Client.get_chat`.
|
||||
|
||||
linked_forum (:obj:`~pyrogram.types.Chat`, *optional*):
|
||||
The linked monoforum (in case of channels) or the linked channel (in case of monoforum).
|
||||
Returned only in :meth:`~pyrogram.Client.get_chat`.
|
||||
|
||||
send_as_chat (:obj:`~pyrogram.types.Chat`, *optional*):
|
||||
The default "send_as" chat.
|
||||
Returned only in :meth:`~pyrogram.Client.get_chat`.
|
||||
|
|
@ -228,7 +232,6 @@ class Chat(Object):
|
|||
is_scam: bool = None,
|
||||
is_fake: bool = None,
|
||||
is_support: bool = None,
|
||||
is_forum: bool = None,
|
||||
is_participants_hidden: bool = None,
|
||||
is_join_request: bool = None,
|
||||
is_join_to_send: bool = None,
|
||||
|
|
@ -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,
|
||||
|
|
@ -259,6 +263,7 @@ class Chat(Object):
|
|||
permissions: "types.ChatPermissions" = None,
|
||||
distance: int = None,
|
||||
linked_chat: "types.Chat" = None,
|
||||
linked_forum: "types.Chat" = None,
|
||||
send_as_chat: "types.Chat" = None,
|
||||
available_reactions: Optional["types.ChatReactions"] = None,
|
||||
usernames: List["types.Username"] = None,
|
||||
|
|
@ -282,7 +287,6 @@ class Chat(Object):
|
|||
self.is_scam = is_scam
|
||||
self.is_fake = is_fake
|
||||
self.is_support = is_support
|
||||
self.is_forum = is_forum
|
||||
self.is_participants_hidden = is_participants_hidden
|
||||
self.is_join_request = is_join_request
|
||||
self.is_join_to_send = is_join_to_send
|
||||
|
|
@ -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
|
||||
|
|
@ -313,6 +318,7 @@ class Chat(Object):
|
|||
self.permissions = permissions
|
||||
self.distance = distance
|
||||
self.linked_chat = linked_chat
|
||||
self.linked_forum = linked_forum
|
||||
self.send_as_chat = send_as_chat
|
||||
self.available_reactions = available_reactions
|
||||
self.usernames = usernames
|
||||
|
|
@ -389,6 +395,16 @@ class Chat(Object):
|
|||
restriction_reason = getattr(channel, "restriction_reason", [])
|
||||
user_name = getattr(channel, "username", None)
|
||||
active_usernames = getattr(channel, "usernames", [])
|
||||
if getattr(channel, "monoforum", None):
|
||||
chat_type = enums.ChatType.MONOFORUM
|
||||
elif getattr(channel, "forum", None):
|
||||
chat_type = enums.ChatType.FORUM
|
||||
elif getattr(channel, "megagroup", None):
|
||||
chat_type = enums.ChatType.SUPERGROUP
|
||||
elif getattr(channel, "broadcast", None):
|
||||
chat_type = enums.ChatType.CHANNEL
|
||||
else:
|
||||
chat_type = enums.ChatType.GROUP
|
||||
usernames = None
|
||||
if len(active_usernames) >= 1:
|
||||
usernames = []
|
||||
|
|
@ -405,13 +421,12 @@ class Chat(Object):
|
|||
|
||||
return Chat(
|
||||
id=peer_id,
|
||||
type=enums.ChatType.SUPERGROUP if getattr(channel, "megagroup", None) else enums.ChatType.CHANNEL,
|
||||
type=chat_type,
|
||||
is_verified=getattr(channel, "verified", None),
|
||||
is_restricted=getattr(channel, "restricted", None),
|
||||
is_creator=getattr(channel, "creator", None),
|
||||
is_scam=getattr(channel, "scam", None),
|
||||
is_fake=getattr(channel, "fake", None),
|
||||
is_forum=getattr(channel, "forum", None),
|
||||
is_join_request=getattr(channel, "join_request", None),
|
||||
is_join_to_send=getattr(channel, "join_to_send", None),
|
||||
is_slowmode_enabled=getattr(channel, "slowmode_enabled", None),
|
||||
|
|
@ -535,14 +550,20 @@ 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)
|
||||
|
||||
linked_chat_raw = chats.get(full_chat.linked_chat_id, None)
|
||||
|
||||
linked_forum_raw = chats.get(getattr(chat_raw, "linked_monoforum_id"), None)
|
||||
|
||||
if linked_chat_raw:
|
||||
parsed_chat.linked_chat = Chat._parse_channel_chat(client, linked_chat_raw)
|
||||
|
||||
if linked_forum_raw:
|
||||
parsed_chat.linked_forum = Chat._parse_channel_chat(client, linked_forum_raw)
|
||||
|
||||
default_send_as = full_chat.default_send_as
|
||||
|
||||
if default_send_as:
|
||||
|
|
|
|||
149
pyrogram/types/user_and_chats/group_call_member.py
Normal file
149
pyrogram/types/user_and_chats/group_call_member.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
import pyrogram
|
||||
from pyrogram import raw, types, utils
|
||||
from ..object import Object
|
||||
|
||||
|
||||
class GroupCallMember(Object):
|
||||
"""Contains information about one member of a group call.
|
||||
|
||||
Parameters:
|
||||
chat (:obj:`~pyrogram.types.Chat`, *optional*):
|
||||
Information about the user or chat.
|
||||
|
||||
date (:py:obj:`~datetime.datetime`, *optional*):
|
||||
Date when this participant join this group call.
|
||||
|
||||
active_date (:py:obj:`~datetime.datetime`, *optional*):
|
||||
Date when this participant last active in this group call.
|
||||
|
||||
volume (``int``, *optional*):
|
||||
Volume, if not set the volume is set to 100%.
|
||||
|
||||
can_self_unmute (``bool``, *optional*):
|
||||
Whether the participant can unmute themselves.
|
||||
|
||||
is_muted (``bool``, *optional*):
|
||||
Whether the participant is muted.
|
||||
|
||||
is_left (``bool``, *optional*):
|
||||
Whether the participant has left.
|
||||
|
||||
is_just_joined (``bool``, *optional*):
|
||||
Whether the participant has just joined.
|
||||
|
||||
is_muted_by_you (``bool``, *optional*):
|
||||
Whether this participant was muted by the current user.
|
||||
|
||||
is_volume_by_admin (``bool``, *optional*):
|
||||
Whether our volume can only changed by an admin.
|
||||
|
||||
is_self (``bool``, *optional*):
|
||||
Whether this participant is the current user.
|
||||
|
||||
is_video_joined (``bool``, *optional*):
|
||||
Whether this participant is currently broadcasting video.
|
||||
|
||||
is_hand_raised (``bool``, *optional*):
|
||||
Whether this participant is raised hand.
|
||||
|
||||
is_video_enabled (``bool``, *optional*):
|
||||
Whether this participant is currently broadcasting video.
|
||||
|
||||
is_screen_sharing_enabled (``bool``, *optional*):
|
||||
Whether this participant is currently shared screen.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
client: "pyrogram.Client" = None,
|
||||
chat: "types.Chat" = None,
|
||||
date: datetime = None,
|
||||
active_date: datetime = None,
|
||||
volume: int = None,
|
||||
can_self_unmute: bool = None,
|
||||
is_muted: bool = None,
|
||||
is_left: bool = None,
|
||||
is_just_joined: bool = None,
|
||||
is_muted_by_you: bool = None,
|
||||
is_volume_by_admin: bool = None,
|
||||
is_self: bool = None,
|
||||
is_video_joined: bool = None,
|
||||
is_hand_raised: bool = None,
|
||||
is_video_enabled: bool = None,
|
||||
is_screen_sharing_enabled: bool = None
|
||||
):
|
||||
super().__init__(client)
|
||||
|
||||
self.chat = chat
|
||||
self.date = date
|
||||
self.active_date = active_date
|
||||
self.volume = volume
|
||||
self.can_self_unmute = can_self_unmute
|
||||
self.is_muted = is_muted
|
||||
self.is_left = is_left
|
||||
self.is_just_joined = is_just_joined
|
||||
self.is_muted_by_you = is_muted_by_you
|
||||
self.is_volume_by_admin = is_volume_by_admin
|
||||
self.is_self = is_self
|
||||
self.is_video_joined = is_video_joined
|
||||
self.is_hand_raised = is_hand_raised
|
||||
self.is_video_enabled = is_video_enabled
|
||||
self.is_screen_sharing_enabled = is_screen_sharing_enabled
|
||||
|
||||
@staticmethod
|
||||
def _parse(
|
||||
client: "pyrogram.Client",
|
||||
member: "raw.types.GroupCallParticipant",
|
||||
users: Dict[int, "raw.base.User"],
|
||||
chats: Dict[int, "raw.base.Chat"]
|
||||
) -> "GroupCallMember":
|
||||
peer = member.peer
|
||||
peer_id = utils.get_raw_peer_id(peer)
|
||||
|
||||
parsed_chat = types.Chat._parse_chat(
|
||||
client,
|
||||
users[peer_id] if isinstance(peer, raw.types.PeerUser) else chats[peer_id],
|
||||
)
|
||||
|
||||
parsed_chat.bio = getattr(member, "about", None)
|
||||
|
||||
return GroupCallMember(
|
||||
chat=parsed_chat,
|
||||
date=utils.timestamp_to_datetime(member.date),
|
||||
active_date=utils.timestamp_to_datetime(member.active_date),
|
||||
volume=getattr(member, "volume", None),
|
||||
can_self_unmute=member.can_self_unmute,
|
||||
is_muted=member.muted,
|
||||
is_left=member.left,
|
||||
is_just_joined=member.just_joined,
|
||||
is_muted_by_you=member.muted_by_you,
|
||||
is_volume_by_admin=member.volume_by_admin,
|
||||
is_self=member.is_self,
|
||||
is_video_joined=member.video_joined,
|
||||
is_hand_raised=bool(getattr(member, "raise_hand_rating", None)),
|
||||
is_video_enabled=bool(getattr(member, "video", None)),
|
||||
is_screen_sharing_enabled=bool(getattr(member, "presentation", None)),
|
||||
client=client
|
||||
)
|
||||
|
|
@ -79,6 +79,9 @@ class User(Object, Update):
|
|||
is_deleted(``bool``, *optional*):
|
||||
True, if this user is deleted.
|
||||
|
||||
is_frozen(``bool``, *optional*):
|
||||
True, if this user is frozen.
|
||||
|
||||
is_bot (``bool``, *optional*):
|
||||
True, if this user is a bot.
|
||||
|
||||
|
|
@ -168,6 +171,10 @@ class User(Object, Update):
|
|||
|
||||
active_users (``int``, *optional*):
|
||||
Bot's active users count.
|
||||
|
||||
frozen_icon (``int``, *optional*):
|
||||
Frozen account icon.
|
||||
This field is available only in case *is_frozen* is True.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
|
@ -179,6 +186,7 @@ class User(Object, Update):
|
|||
is_contact: bool = None,
|
||||
is_mutual_contact: bool = None,
|
||||
is_deleted: bool = None,
|
||||
is_frozen: bool = None,
|
||||
is_bot: bool = None,
|
||||
is_verified: bool = None,
|
||||
is_restricted: bool = None,
|
||||
|
|
@ -203,7 +211,8 @@ class User(Object, Update):
|
|||
restrictions: List["types.Restriction"] = None,
|
||||
reply_color: "types.ChatColor" = None,
|
||||
profile_color: "types.ChatColor" = None,
|
||||
active_users: int = None
|
||||
active_users: int = None,
|
||||
frozen_icon: int = None
|
||||
):
|
||||
super().__init__(client)
|
||||
|
||||
|
|
@ -212,6 +221,7 @@ class User(Object, Update):
|
|||
self.is_contact = is_contact
|
||||
self.is_mutual_contact = is_mutual_contact
|
||||
self.is_deleted = is_deleted
|
||||
self.is_frozen = is_frozen
|
||||
self.is_bot = is_bot
|
||||
self.is_verified = is_verified
|
||||
self.is_restricted = is_restricted
|
||||
|
|
@ -237,6 +247,7 @@ class User(Object, Update):
|
|||
self.reply_color = reply_color
|
||||
self.profile_color = profile_color
|
||||
self.active_users = active_users
|
||||
self.frozen_icon = frozen_icon
|
||||
|
||||
@property
|
||||
def full_name(self) -> str:
|
||||
|
|
@ -269,12 +280,15 @@ class User(Object, Update):
|
|||
user_name = usernames[0].username
|
||||
usernames.pop(0)
|
||||
|
||||
frozen_icon = getattr(user, "bot_verification_icon", None)
|
||||
|
||||
return User(
|
||||
id=user.id,
|
||||
is_self=user.is_self,
|
||||
is_contact=user.contact,
|
||||
is_mutual_contact=user.mutual_contact,
|
||||
is_deleted=user.deleted,
|
||||
is_frozen=True if frozen_icon else False,
|
||||
is_bot=user.bot,
|
||||
is_verified=user.verified,
|
||||
is_restricted=user.restricted,
|
||||
|
|
@ -298,6 +312,7 @@ class User(Object, Update):
|
|||
reply_color=types.ChatColor._parse(getattr(user, "color", None)),
|
||||
profile_color=types.ChatColor._parse_profile_color(getattr(user, "profile_color", None)),
|
||||
active_users=active_users,
|
||||
frozen_icon=frozen_icon,
|
||||
client=client
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ async def parse_messages(
|
|||
client,
|
||||
messages: "raw.types.messages.Messages",
|
||||
replies: int = 1,
|
||||
business_connection_id: str = None
|
||||
business_connection_id: str = None,
|
||||
is_scheduled: bool = False
|
||||
) -> List["types.Message"]:
|
||||
users = {i.id: i for i in messages.users}
|
||||
chats = {i.id: i for i in messages.chats}
|
||||
|
|
@ -120,64 +121,76 @@ async def parse_messages(
|
|||
parsed_messages.append(await types.Message._parse(client, message, users, chats, topics, replies=0, business_connection_id=business_connection_id))
|
||||
|
||||
if replies:
|
||||
messages_with_replies = {
|
||||
i.id: i.reply_to.reply_to_msg_id
|
||||
for i in messages.messages
|
||||
if (
|
||||
not isinstance(i, raw.types.MessageEmpty)
|
||||
and i.reply_to
|
||||
and isinstance(i.reply_to, raw.types.MessageReplyHeader)
|
||||
and i.reply_to.reply_to_msg_id is not None
|
||||
)
|
||||
}
|
||||
if not is_scheduled:
|
||||
messages_with_replies = {
|
||||
i.id: i.reply_to.reply_to_msg_id
|
||||
for i in messages.messages
|
||||
if (
|
||||
not isinstance(i, raw.types.MessageEmpty)
|
||||
and i.reply_to
|
||||
and isinstance(i.reply_to, raw.types.MessageReplyHeader)
|
||||
and i.reply_to.reply_to_msg_id is not None
|
||||
)
|
||||
}
|
||||
|
||||
message_reply_to_story = {
|
||||
i.id: {'user_id': i.reply_to.user_id, 'story_id': i.reply_to.story_id}
|
||||
for i in messages.messages
|
||||
if not isinstance(i, raw.types.MessageEmpty) and i.reply_to and isinstance(i.reply_to, raw.types.MessageReplyStoryHeader)
|
||||
}
|
||||
message_reply_to_story = {
|
||||
i.id: {'user_id': i.reply_to.user_id, 'story_id': i.reply_to.story_id}
|
||||
for i in messages.messages
|
||||
if not isinstance(i, raw.types.MessageEmpty) and i.reply_to and isinstance(i.reply_to, raw.types.MessageReplyStoryHeader)
|
||||
}
|
||||
|
||||
if messages_with_replies:
|
||||
# We need a chat id, but some messages might be empty (no chat attribute available)
|
||||
# Scan until we find a message with a chat available (there must be one, because we are fetching replies)
|
||||
for m in parsed_messages:
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
if messages_with_replies:
|
||||
# We need a chat id, but some messages might be empty (no chat attribute available)
|
||||
# Scan until we find a message with a chat available (there must be one, because we are fetching replies)
|
||||
for m in parsed_messages:
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
|
||||
reply_messages = await client.get_messages(
|
||||
chat_id,
|
||||
reply_to_message_ids=messages_with_replies.keys(),
|
||||
replies=replies - 1
|
||||
)
|
||||
|
||||
for message in parsed_messages:
|
||||
reply_id = messages_with_replies.get(message.id, None)
|
||||
|
||||
for reply in reply_messages:
|
||||
if reply.id == reply_id:
|
||||
if not reply.forum_topic_created:
|
||||
message.reply_to_message = reply
|
||||
if message_reply_to_story:
|
||||
for m in parsed_messages:
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
|
||||
reply_messages = {}
|
||||
for msg_id in message_reply_to_story.keys():
|
||||
reply_messages[msg_id] = await client.get_stories(
|
||||
message_reply_to_story[msg_id]['user_id'],
|
||||
message_reply_to_story[msg_id]['story_id']
|
||||
reply_messages = await client.get_messages(
|
||||
chat_id,
|
||||
reply_to_message_ids=messages_with_replies.keys(),
|
||||
replies=replies - 1
|
||||
)
|
||||
|
||||
for message in parsed_messages:
|
||||
reply_id = messages_with_replies.get(message.id, None)
|
||||
|
||||
for reply in reply_messages:
|
||||
if reply.id == reply_id:
|
||||
if not reply.forum_topic_created:
|
||||
message.reply_to_message = reply
|
||||
if message_reply_to_story:
|
||||
for m in parsed_messages:
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
|
||||
reply_messages = {}
|
||||
for msg_id in message_reply_to_story.keys():
|
||||
reply_messages[msg_id] = await client.get_stories(
|
||||
message_reply_to_story[msg_id]['user_id'],
|
||||
message_reply_to_story[msg_id]['story_id']
|
||||
)
|
||||
|
||||
for message in parsed_messages:
|
||||
if message.id in reply_messages:
|
||||
message.reply_to_story = reply_messages[message.id]
|
||||
else:
|
||||
for message in parsed_messages:
|
||||
if message.id in reply_messages:
|
||||
message.reply_to_story = reply_messages[message.id]
|
||||
if (
|
||||
message.reply_to_message_id
|
||||
and not message.external_reply
|
||||
):
|
||||
message.reply_to_message = await client.get_messages(
|
||||
message.chat.id,
|
||||
message_ids=message.reply_to_message_id,
|
||||
replies=replies - 1
|
||||
)
|
||||
|
||||
return types.List(parsed_messages)
|
||||
|
||||
|
|
@ -474,6 +487,7 @@ async def get_reply_to(
|
|||
reply_to_message_id: int = None,
|
||||
reply_to_story_id: int = None,
|
||||
message_thread_id: int = None,
|
||||
reply_to_monoforum_id: Union[int,str] = None,
|
||||
reply_to_chat_id: Union[int,str] = None,
|
||||
quote_text: str = None,
|
||||
quote_entities: List["types.MessageEntity"] = None,
|
||||
|
|
@ -482,7 +496,12 @@ async def get_reply_to(
|
|||
):
|
||||
reply_to = None
|
||||
reply_to_chat = None
|
||||
if reply_to_message_id or message_thread_id:
|
||||
if reply_to_monoforum_id:
|
||||
peer = await client.resolve_peer(reply_to_monoforum_id)
|
||||
reply_to = types.InputReplyToMonoforum(
|
||||
monoforum_peer=peer
|
||||
)
|
||||
elif reply_to_message_id or message_thread_id:
|
||||
text, entities = (await parse_text_entities(client, quote_text, parse_mode, quote_entities)).values()
|
||||
if reply_to_chat_id is not None:
|
||||
reply_to_chat = await client.resolve_peer(reply_to_chat_id)
|
||||
|
|
@ -494,7 +513,7 @@ async def get_reply_to(
|
|||
quote_entities=entities,
|
||||
quote_offset=quote_offset,
|
||||
)
|
||||
if reply_to_story_id:
|
||||
elif reply_to_story_id:
|
||||
peer = await client.resolve_peer(chat_id)
|
||||
reply_to = types.InputReplyToStory(
|
||||
peer=peer,
|
||||
|
|
|
|||
Loading…
Reference in a new issue