Merge branch 'Mayuri-Chan:main' into main

This commit is contained in:
naya1503 2024-07-04 16:56:57 +07:00 committed by GitHub
commit d26c2b855f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 1458 additions and 31 deletions

View file

@ -53,6 +53,7 @@ inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> s
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
inputMediaStory#89fdd778 peer:InputPeer id:int = InputMedia;
inputMediaWebPage#c21b8849 flags:# force_large_media:flags.0?true force_small_media:flags.1?true optional:flags.2?true url:string = InputMedia;
inputMediaPaidMedia#aa661fc3 stars_amount:long extended_media:Vector<InputMedia> = InputMedia;
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
inputChatUploadedPhoto#bdcdaec0 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.3?VideoSize = InputChatPhoto;
@ -110,7 +111,7 @@ channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5
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;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -142,6 +143,7 @@ messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;
messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia;
messageMediaGiveaway#daad85b0 flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.2?true channels:Vector<long> countries_iso2:flags.1?Vector<string> prize_description:flags.3?string quantity:int months:int until_date:int = MessageMedia;
messageMediaGiveawayResults#c6991068 flags:# only_new_subscribers:flags.0?true refunded:flags.2?true channel_id:long additional_peers_count:flags.3?int launch_msg_id:int winners_count:int unclaimed_count:int winners:Vector<long> months:int prize_description:flags.1?string until_date:int = MessageMedia;
messageMediaPaidMedia#a8852491 stars_amount:long extended_media:Vector<MessageExtendedMedia> = MessageMedia;
messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
@ -393,7 +395,7 @@ updateUserEmojiStatus#28373599 user_id:long emoji_status:EmojiStatus = Update;
updateRecentEmojiStatuses#30f443db = Update;
updateRecentReactions#6f7863f4 = Update;
updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?true stickerset:long = Update;
updateMessageExtendedMedia#5a73a98c peer:Peer msg_id:int extended_media:MessageExtendedMedia = Update;
updateMessageExtendedMedia#d5a41724 peer:Peer msg_id:int extended_media:Vector<MessageExtendedMedia> = Update;
updateChannelPinnedTopic#192efbe3 flags:# pinned:flags.0?true channel_id:long topic_id:int = Update;
updateChannelPinnedTopics#fe198602 flags:# channel_id:long order:flags.0?Vector<int> = Update;
updateUser#20529438 user_id:long = Update;
@ -770,7 +772,7 @@ auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeTyp
auth.sentCodeTypeEmailCode#f450f59b flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int reset_available_period:flags.3?int reset_pending_date:flags.4?int = auth.SentCodeType;
auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType;
auth.sentCodeTypeFragmentSms#d9565c39 url:string length:int = auth.SentCodeType;
auth.sentCodeTypeFirebaseSms#13c90f17 flags:# nonce:flags.0?bytes play_integrity_nonce:flags.2?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType;
auth.sentCodeTypeFirebaseSms#9fd736 flags:# nonce:flags.0?bytes play_integrity_project_id:flags.2?long play_integrity_nonce:flags.2?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType;
auth.sentCodeTypeSmsWord#a416ac81 flags:# beginning:flags.0?string = auth.SentCodeType;
auth.sentCodeTypeSmsPhrase#b37794af flags:# beginning:flags.0?string = auth.SentCodeType;
@ -1431,9 +1433,7 @@ attachMenuBots#3c4301c0 hash:long bots:Vector<AttachMenuBot> users:Vector<User>
attachMenuBotsBot#93bf667f bot:AttachMenuBot users:Vector<User> = AttachMenuBotsBot;
webViewResultUrl#c14557c query_id:long url:string = WebViewResult;
simpleWebViewResultUrl#882f76bb url:string = SimpleWebViewResult;
webViewResultUrl#4d22ff98 flags:# fullsize:flags.1?true query_id:flags.0?long url:string = WebViewResult;
webViewMessageSent#c94511c flags:# msg_id:flags.0?InputBotInlineMessageID = WebViewMessageSent;
@ -1563,8 +1563,6 @@ botApp#95fcd1d6 flags:# id:long access_hash:long short_name:string title:string
messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true has_settings:flags.2?true app:BotApp = messages.BotApp;
appWebViewResultUrl#3c1b4f0d url:string = AppWebViewResult;
inlineBotWebView#b57295d5 text:string url:string = InlineBotWebView;
readParticipantDate#4a4ff172 user_id:long date:int = ReadParticipantDate;
@ -1812,10 +1810,11 @@ starsTransactionPeerPlayMarket#7b560a0b = StarsTransactionPeer;
starsTransactionPeerPremiumBot#250dbaf8 = StarsTransactionPeer;
starsTransactionPeerFragment#e92fd902 = StarsTransactionPeer;
starsTransactionPeer#d80da15d peer:Peer = StarsTransactionPeer;
starsTransactionPeerAds#60682812 = StarsTransactionPeer;
starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption;
starsTransaction#aa00c898 flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true id:string stars:long 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 = StarsTransaction;
starsTransaction#2db5418f flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true id:string stars:long 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> = StarsTransaction;
payments.starsStatus#8cf4ee60 flags:# balance:long history:Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
@ -1831,6 +1830,10 @@ payments.starsRevenueStats#c92bb73b revenue_graph:StatsGraph status:StarsRevenue
payments.starsRevenueWithdrawalUrl#1dab80b7 url:string = payments.StarsRevenueWithdrawalUrl;
payments.starsRevenueAdsAccountUrl#394e7f21 url:string = payments.StarsRevenueAdsAccountUrl;
inputStarsTransaction#206ae6d1 flags:# refund:flags.0?true id:string = InputStarsTransaction;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2174,9 +2177,9 @@ messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = mes
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool;
messages.requestWebView#269dc2c1 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = WebViewResult;
messages.requestWebView#269dc2c1 flags:# from_bot_menu:flags.4?true silent:flags.5?true compact:flags.7?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = WebViewResult;
messages.prolongWebView#b0d81a83 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = Bool;
messages.requestSimpleWebView#1a46500a flags:# from_switch_webview:flags.1?true from_side_menu:flags.2?true bot:InputUser url:flags.3?string start_param:flags.4?string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
messages.requestSimpleWebView#413a3e73 flags:# from_switch_webview:flags.1?true from_side_menu:flags.2?true compact:flags.7?true bot:InputUser url:flags.3?string start_param:flags.4?string theme_params:flags.0?DataJSON platform:string = WebViewResult;
messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent;
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;
@ -2198,7 +2201,7 @@ messages.getEmojiProfilePhotoGroups#21a548f3 hash:int = messages.EmojiGroups;
messages.searchCustomEmoji#2c11c0d7 emoticon:string hash:long = EmojiList;
messages.togglePeerTranslations#e47cb579 flags:# disabled:flags.0?true peer:InputPeer = Bool;
messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp;
messages.requestAppWebView#8c5a3b3c flags:# write_allowed:flags.0?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = AppWebViewResult;
messages.requestAppWebView#53618bce flags:# write_allowed:flags.0?true compact:flags.7?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;
@ -2378,6 +2381,8 @@ payments.sendStarsForm#2bb731d flags:# form_id:long invoice:InputInvoice = payme
payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates;
payments.getStarsRevenueStats#d91ffad6 flags:# dark:flags.0?true peer:InputPeer = payments.StarsRevenueStats;
payments.getStarsRevenueWithdrawalUrl#13bbe8b3 peer:InputPeer stars:long password:InputCheckPasswordSRP = payments.StarsRevenueWithdrawalUrl;
payments.getStarsRevenueAdsAccountUrl#d1d7efc5 peer:InputPeer = payments.StarsRevenueAdsAccountUrl;
payments.getStarsTransactionsByID#27842d2e peer:InputPeer id:Vector<InputStarsTransaction> = payments.StarsStatus;
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;
@ -2497,4 +2502,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
// LAYER 182
// LAYER 183

View file

@ -168,6 +168,7 @@ def pyrogram_api():
forward_messages
copy_message
copy_media_group
send_paid_media
send_photo
send_audio
send_document
@ -229,6 +230,9 @@ def pyrogram_api():
set_administrator_title
set_chat_photo
delete_chat_photo
delete_folder
export_folder_link
update_folder
set_chat_title
set_chat_description
set_chat_permissions
@ -241,6 +245,7 @@ def pyrogram_api():
get_chat_members_count
get_dialogs
get_dialogs_count
get_folders
get_forum_topics
get_forum_topics_by_id
set_chat_username
@ -271,6 +276,8 @@ def pyrogram_api():
reopen_forum_topic
reopen_general_topic
unhide_general_topic
update_color
update_folder
""",
users="""
Users
@ -453,6 +460,7 @@ def pyrogram_api():
ChatJoinedByRequest
ChatJoiner
Dialog
Folder
Restriction
EmojiStatus
ForumTopic
@ -513,6 +521,8 @@ def pyrogram_api():
ReactionType
MessageReactionUpdated
MessageReactionCountUpdated
ExtendedMediaPreview
PaidMedia
""",
stories="""
Stories

View file

@ -1,5 +1,7 @@
.. raw:: html
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
<blockquote>
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
</blockquote>

View file

@ -1,5 +1,7 @@
.. raw:: html
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
<blockquote>
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
</blockquote>

View file

@ -1,5 +1,7 @@
.. raw:: html
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Bots</span>
<blockquote>
<strong>Usable by</strong>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Bots</span>
</blockquote>

View file

@ -0,0 +1,8 @@
FolderColor
===========
.. autoclass:: pyrogram.enums.FolderColor()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -19,6 +19,7 @@ to apply only a valid value among the expected ones.
ChatMemberStatus
ChatMembersFilter
ChatType
FolderColor
ListenerTypes
MessageEntityType
MessageMediaType
@ -41,6 +42,7 @@ to apply only a valid value among the expected ones.
ChatMemberStatus
ChatMembersFilter
ChatType
FolderColor
ListenerTypes
MessageEntityType
MessageMediaType

View file

@ -18,7 +18,7 @@
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
__fork_name__ = "PyroFork"
__version__ = "2.3.26"
__version__ = "2.3.29"
__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)"
__copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>"

View file

@ -24,6 +24,7 @@ from .chat_member_status import ChatMemberStatus
from .chat_members_filter import ChatMembersFilter
from .chat_type import ChatType
from .client_platform import ClientPlatform
from .folder_color import FolderColor
from .listerner_types import ListenerTypes
from .message_entity_type import MessageEntityType
from .message_media_type import MessageMediaType
@ -47,7 +48,8 @@ __all__ = [
'ChatMemberStatus',
'ChatMembersFilter',
'ChatType',
'ClientPlatform',
'ClientPlatform',
'FolderColor',
'ListenerTypes',
'MessageEntityType',
'MessageMediaType',

View file

@ -0,0 +1,47 @@
# 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 .auto_name import AutoName
class FolderColor(AutoName):
"""Folder color enumeration used in :obj:`~pyrogram.types.Folder`."""
NO_COLOR = None
"No color."
RED = 0
"Red color."
ORANGE = 1
"Orange color."
VIOLET = 2
"Violet color."
GREEN = 3
"Green color."
CYAN = 4
"Cyan color."
BLUE = 5
"Blue color."
PINK = 6
"Pink color."

View file

@ -81,3 +81,6 @@ class MessageMediaType(AutoName):
INVOICE = auto()
"Invoice media"
PAID_MEDIA = auto()
"Paid media"

View file

@ -28,11 +28,13 @@ from .close_forum_topic import CloseForumTopic
from .close_general_topic import CloseGeneralTopic
from .delete_channel import DeleteChannel
from .delete_chat_photo import DeleteChatPhoto
from .delete_folder import DeleteFolder
from .delete_forum_topic import DeleteForumTopic
from .delete_supergroup import DeleteSupergroup
from .delete_user_history import DeleteUserHistory
from .edit_forum_topic import EditForumTopic
from .edit_general_topic import EditGeneralTopic
from .export_folder_link import ExportFolderLink
from .reopen_forum_topic import ReopenForumTopic
from .reopen_general_topic import ReopenGeneralTopic
from .hide_general_topic import HideGeneralTopic
@ -45,6 +47,7 @@ from .get_chat_members_count import GetChatMembersCount
from .get_chat_online_count import GetChatOnlineCount
from .get_dialogs import GetDialogs
from .get_dialogs_count import GetDialogsCount
from .get_folders import GetFolders
from .get_forum_topics import GetForumTopics
from .get_forum_topics_by_id import GetForumTopicsByID
from .get_nearby_chats import GetNearbyChats
@ -69,6 +72,7 @@ from .unban_chat_member import UnbanChatMember
from .unpin_all_chat_messages import UnpinAllChatMessages
from .unpin_chat_message import UnpinChatMessage
from .update_color import UpdateColor
from .update_folder import UpdateFolder
class Chats(
@ -92,6 +96,7 @@ class Chats(
SetChatUsername,
SetChatPermissions,
GetDialogsCount,
GetFolders,
GetForumTopics,
GetForumTopicsByID,
ArchiveChats,
@ -104,10 +109,12 @@ class Chats(
CloseGeneralTopic,
AddChatMembers,
DeleteChannel,
DeleteFolder,
DeleteForumTopic,
DeleteSupergroup,
EditForumTopic,
EditGeneralTopic,
ExportFolderLink,
ReopenForumTopic,
ReopenGeneralTopic,
HideGeneralTopic,
@ -123,6 +130,7 @@ class Chats(
GetSendAsChats,
SetSendAsChat,
SetChatProtectedContent,
UpdateColor
UpdateColor,
UpdateFolder
):
pass

View file

@ -0,0 +1,52 @@
# 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 pyrogram
from pyrogram import raw
class DeleteFolder:
async def delete_folder(
self: "pyrogram.Client",
folder_id: int
) -> bool:
"""Delete a user's folder.
.. include:: /_includes/usable-by/users.rst
Parameters:
folder_id (``int``):
Unique identifier (int) of the target folder.
Returns:
``bool``: True, on success.
Example:
.. code-block:: python
# Delete folder
app.delete_folder(folder_id)
"""
r = await self.invoke(
raw.functions.messages.UpdateDialogFilter(
id=folder_id
)
)
return r

View file

@ -0,0 +1,70 @@
# 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 pyrogram
from pyrogram import raw
class ExportFolderLink:
async def export_folder_link(
self: "pyrogram.Client",
folder_id: int
) -> str:
"""Export link to a user's folder.
.. include:: /_includes/usable-by/users.rst
Parameters:
folder_id (``int``):
Unique identifier (int) of the target folder.
Returns:
``str``: On success, a link to the folder as string is returned.
Example:
.. code-block:: python
# Export folder link
app.export_folder_link(folder_id)
"""
folder = await self.get_folders(folder_id)
if not folder:
return
peers = []
if folder.included_chats:
peers.extend(iter(folder.included_chats))
if folder.excluded_chats:
peers.extend(iter(folder.included_chats))
if folder.pinned_chats:
peers.extend(iter(folder.included_chats))
r = await self.invoke(
raw.functions.chatlists.ExportChatlistInvite(
chatlist=raw.types.InputChatlistDialogFilter(filter_id=folder_id),
title=folder.title,
peers=[await self.resolve_peer(i.id) for i in peers],
)
)
return r.invite.url

View file

@ -0,0 +1,98 @@
# 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 Union, List, Iterable
import pyrogram
from pyrogram import types, raw, utils
class GetFolders:
async def get_folders(
self: "pyrogram.Client",
folder_ids: Union[int, Iterable[int]] = None
) -> Union["types.Folder", List["types.Folder"]]:
"""Get one or more folders by using folder identifiers.
.. include:: /_includes/usable-by/users.rst
Parameters:
folder_ids (``int`` | Iterable of ``int``, *optional*):
Pass a single folder identifier or an iterable of folder ids (as integers) to get the content of the
folders themselves.
By default all folders are returned.
Returns:
:obj:`~pyrogram.types.Folder` | List of :obj:`~pyrogram.types.Folder`: In case *folder_ids* was not
a list, a single folder is returned, otherwise a list of folders is returned.
Example:
.. code-block:: python
# Get one folder
await app.get_folders(12345)
# Get more than one folders (list of folders)
await app.get_folders([12345, 12346])
# Get all folders
await app.get_folders()
"""
is_iterable = hasattr(folder_ids, "__iter__")
ids = set(folder_ids) if is_iterable else {folder_ids}
dialog_filters = await self.invoke(raw.functions.messages.GetDialogFilters())
raw_folders = [
folder for folder in dialog_filters.filters
if not isinstance(folder, raw.types.DialogFilterDefault) and (is_iterable and folder.id in ids or not is_iterable)
]
raw_peers = {}
for folder in raw_folders:
for peer in folder.pinned_peers + folder.include_peers + getattr(folder, "exclude_peers", []):
raw_peers[utils.get_peer_id(peer)] = peer
users = {}
chats = {}
for i in range(0, len(raw_peers), 100):
chunk = list(raw_peers.values())[i:i + 100]
r = await self.invoke(
raw.functions.messages.GetPeerDialogs(
peers=[raw.types.InputDialogPeer(peer=peer) for peer in chunk]
)
)
users.update({i.id: i for i in r.users})
chats.update({i.id: i for i in r.chats})
folders = types.List(types.Folder._parse(self, folder, users, chats) for folder in raw_folders)
if not folders:
return None
if folder_ids:
if is_iterable:
return folders
else:
for folder in folders:
if folder.id == folder_ids:
return folder
return None
return folders

View file

@ -0,0 +1,149 @@
# 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, Union
import pyrogram
from pyrogram import raw
from pyrogram import enums
class UpdateFolder:
async def update_folder(
self: "pyrogram.Client",
folder_id: int,
title: str,
included_chats: Union[Union[int, str], List[Union[int, str]]] = None,
excluded_chats: Union[Union[int, str], List[Union[int, str]]] = None,
pinned_chats: Union[Union[int, str], List[Union[int, str]]] = None,
contacts: bool = None,
non_contacts: bool = None,
groups: bool = None,
channels: bool = None,
bots: bool = None,
exclude_muted: bool = None,
exclude_read: bool = None,
exclude_archived: bool = None,
color: "enums.FolderColor" = None,
emoji: str = None
) -> bool:
"""Create or update a user's folder.
.. include:: /_includes/usable-by/users.rst
Parameters:
folder_id (``int``):
Unique folder identifier.
title (``str``):
Folder title.
included_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should added in the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
excluded_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should excluded from the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
pinned_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should pinned in the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
contacts (``bool``, *optional*):
Pass True if folder should contain contacts.
non_contacts (``bool``, *optional*):
Pass True if folder should contain non contacts.
groups (``bool``, *optional*):
Pass True if folder should contain groups.
channels (``bool``, *optional*):
Pass True if folder should contain channels.
bots (``bool``, *optional*):
Pass True if folder should contain bots.
exclude_muted (``bool``, *optional*):
Pass True if folder should exclude muted users.
exclude_archived (``bool``, *optional*):
Pass True if folder should exclude archived users.
emoji (``str``, *optional*):
Folder emoji.
Pass None to leave the folder icon as default.
color (:obj:`~pyrogram.enums.FolderColor`, *optional*):
Color type.
Pass :obj:`~pyrogram.enums.FolderColor` to set folder color.
Returns:
``bool``: True, on success.
Example:
.. code-block:: python
# Create or update folder
app.update_folder(folder_id, title="New folder", included_chats="me")
"""
if not isinstance(included_chats, list):
included_chats = [included_chats] if included_chats else []
if not isinstance(excluded_chats, list):
excluded_chats = [excluded_chats] if excluded_chats else []
if not isinstance(pinned_chats, list):
pinned_chats = [pinned_chats] if pinned_chats else []
r = await self.invoke(
raw.functions.messages.UpdateDialogFilter(
id=folder_id,
filter=raw.types.DialogFilter(
id=folder_id,
title=title,
pinned_peers=[
await self.resolve_peer(user_id)
for user_id in pinned_chats
],
include_peers=[
await self.resolve_peer(user_id)
for user_id in included_chats
],
exclude_peers=[
await self.resolve_peer(user_id)
for user_id in excluded_chats
],
contacts=contacts,
non_contacts=non_contacts,
groups=groups,
broadcasts=channels,
bots=bots,
exclude_muted=exclude_muted,
exclude_read=exclude_read,
exclude_archived=exclude_archived,
emoticon=emoji,
color=color.value if color else None
)
)
)
return r

View file

@ -58,6 +58,7 @@ from .send_invoice import SendInvoice
from .send_location import SendLocation
from .send_media_group import SendMediaGroup
from .send_message import SendMessage
from .send_paid_media import SendPaidMedia
from .send_photo import SendPhoto
from .send_poll import SendPoll
from .send_reaction import SendReaction
@ -91,6 +92,7 @@ class Messages(
SendLocation,
SendMediaGroup,
SendMessage,
SendPaidMedia,
SendPhoto,
SendSticker,
SendVenue,

View file

@ -21,7 +21,7 @@ from pyrogram import raw
class SearchGlobalHashtagMessagesCount:
async def search_golbal_hashtag_messages_count(
async def search_global_hashtag_messages_count(
self: "pyrogram.Client",
hashtag: str = "",
) -> int:

View file

@ -0,0 +1,290 @@
# 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/>.
import os
import re
from datetime import datetime
from pymediainfo import MediaInfo
from typing import Union, List, Optional
import pyrogram
from pyrogram import raw, utils, enums
from pyrogram import types
from pyrogram.file_id import FileType
class SendPaidMedia:
async def send_paid_media(
self: "pyrogram.Client",
chat_id: Union[int, str],
stars_amount: int,
media: List[Union["types.InputMediaAnimation", "types.InputMediaPhoto", "types.InputMediaVideo"]],
caption: str = "",
caption_entities: List["types.MessageEntity"] = None,
parse_mode: Optional["enums.ParseMode"] = None,
disable_notification: bool = None,
schedule_date: datetime = None,
protect_content: bool = None,
invert_media: bool = None
) -> "types.Message":
"""Send paid media.
Only for channels.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier for the target chat or username of the target channel (in the format @channelusername).
stars_amount (``int``):
Amount of stars.
media (List of :obj:`~pyrogram.types.InputMediaAnimation` | :obj:`~pyrogram.types.InputMediaPhoto` | :obj:`~pyrogram.types.InputMediaVideo`):
A list of media to send.
caption (``str``, *optional*):
Media caption, 0-1024 characters.
caption_entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*):
Special entities that appear in the caption, which can be specified instead of parse_mode.
parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.
disable_notification (``bool``, *optional*):
Sends the message silently. Users will receive a notification with no sound.
schedule_date (:obj:`~datetime.datetime`, *optional*):
Date when the message will be automatically sent. Pass a :obj:`~datetime.datetime` object.
protect_content (``bool``, *optional*):
Protect content from being forwarded.
invert_media (``bool``, *optional*):
Invert the media.
Example:
.. code-block:: python
app.send_paid_media(
chat_id="pyrogram",
stars_amount=100,
media=[
types.InputMediaPhoto("/path/to/photo.jpg"),
types.InputMediaVideo("video_file_id")
],
caption="This is a paid media message."
)
"""
multi_media = []
for i in media:
if isinstance(i, types.InputMediaPhoto):
if isinstance(i.media, str):
if os.path.isfile(i.media):
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
)
)
)
media = raw.types.InputMediaPhoto(
id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
),
spoiler=i.has_spoiler
)
elif re.match("^https?://", i.media):
media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id),
media=raw.types.InputMediaPhotoExternal(
url=i.media,
spoiler=i.has_spoiler
)
)
)
media = raw.types.InputMediaPhoto(
id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
),
spoiler=i.has_spoiler
)
else:
media = utils.get_input_media_from_file_id(i.media, FileType.PHOTO)
else:
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
)
)
)
media = raw.types.InputMediaPhoto(
id=raw.types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash,
file_reference=media.photo.file_reference
),
spoiler=i.has_spoiler
)
elif (
isinstance(i, types.InputMediaVideo)
or
isinstance(i, types.InputMediaAnimation)
):
if isinstance(i.media, str):
is_animation = False
if os.path.isfile(i.media):
try:
videoInfo = MediaInfo.parse(i.media)
except OSError:
is_animation = True if isinstance(i, types.InputMediaAnimation) else False
else:
if not any([track.track_type == 'Audio' for track in videoInfo.tracks]):
is_animation = True
attributes = [
raw.types.DocumentAttributeVideo(
supports_streaming=True if is_animation else (i.supports_streaming or None),
duration=i.duration,
w=i.width,
h=i.height
),
raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
]
if is_animation:
attributes.append(raw.types.DocumentAttributeAnimated())
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),
spoiler=i.has_spoiler,
mime_type=self.guess_mime_type(i.media) or "video/mp4",
nosound_video=is_animation,
attributes=attributes
)
)
)
media = raw.types.InputMediaDocument(
id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
),
spoiler=i.has_spoiler
)
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,
spoiler=i.has_spoiler
)
)
)
media = raw.types.InputMediaDocument(
id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
),
spoiler=i.has_spoiler
)
else:
media = utils.get_input_media_from_file_id(i.media, FileType.VIDEO)
else:
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),
spoiler=i.has_spoiler,
mime_type=self.guess_mime_type(getattr(i.media, "name", "video.mp4")) or "video/mp4",
attributes=[
raw.types.DocumentAttributeVideo(
supports_streaming=i.supports_streaming or None,
duration=i.duration,
w=i.width,
h=i.height
),
raw.types.DocumentAttributeFilename(file_name=getattr(i.media, "name", "video.mp4"))
]
)
)
)
media = raw.types.InputMediaDocument(
id=raw.types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash,
file_reference=media.document.file_reference
),
spoiler=i.has_spoiler
)
else:
raise ValueError(f"{i.__class__.__name__} is not a supported type for send_paid_media")
multi_media.append(media)
rpc = raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=raw.types.InputMediaPaidMedia(
stars_amount=stars_amount,
extended_media=multi_media
),
silent=disable_notification or None,
random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content,
invert_media=invert_media,
**await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
r = await self.invoke(rpc, sleep_threshold=60)
return await utils.parse_messages(
self,
raw.types.messages.Messages(
messages=[m.message for m in filter(
lambda u: isinstance(u, (raw.types.UpdateNewMessage,
raw.types.UpdateNewChannelMessage,
raw.types.UpdateNewScheduledMessage,
raw.types.UpdateBotNewBusinessMessage)),
r.updates
)],
users=r.users,
chats=r.chats
)
)

View file

@ -172,7 +172,17 @@ class SendPoll:
Example:
.. code-block:: python
await app.send_poll(chat_id, "Is this a poll question?", ["Yes", "No", "Maybe"])
from pyrogram.types import PollOption
await app.send_poll(
chat_id,
"Is this a poll question?",
[
PollOption("Yes"),
PollOption("No"),
PollOption("Maybe")
]
)
"""
reply_to = await utils.get_reply_to(

View file

@ -57,6 +57,7 @@ OPENING_TAG = "<{}>"
CLOSING_TAG = "</{}>"
URL_MARKUP = '<a href="{}">{}</a>'
FIXED_WIDTH_DELIMS = [CODE_DELIM, PRE_DELIM]
CODE_TAG_RE = re.compile(r"<code>.*?</code>")
class Markdown:
@ -108,6 +109,12 @@ class Markdown:
delims = set()
is_fixed_width = False
placeholders = {}
for i, code_section in enumerate(CODE_TAG_RE.findall(text)):
placeholder = f"{{CODE_SECTION_{i}}}"
placeholders[placeholder] = code_section
text = text.replace(code_section, placeholder, 1)
for i, match in enumerate(re.finditer(MARKDOWN_RE, text)):
start, _ = match.span()
delim, text_url, url = match.groups()
@ -155,6 +162,9 @@ class Markdown:
text = utils.replace_once(text, delim, tag, start)
for placeholder, code_section in placeholders.items():
text = text.replace(placeholder, code_section)
return await self.html.parse(text)
@staticmethod

View file

@ -23,6 +23,7 @@ from .available_effect import AvailableEffect
from .contact import Contact
from .dice import Dice
from .document import Document
from .extended_media_preview import ExtendedMediaPreview
from .game import Game
from .gifted_premium import GiftedPremium
from .giveaway import Giveaway
@ -35,6 +36,7 @@ from .media_area_channel_post import MediaAreaChannelPost
from .media_area_coordinates import MediaAreaCoordinates
from .message import Message
from .message_entity import MessageEntity
from .paid_media import PaidMedia
from .photo import Photo
from .poll import Poll
from .poll_option import PollOption
@ -67,7 +69,7 @@ from .story_views import StoryViews
from .exported_story_link import ExportedStoryLink
__all__ = [
"Animation", "Audio", "AvailableEffect", "Contact", "Document", "Game", "GiftedPremium", "Giveaway", "GiveawayLaunched", "GiveawayResult", "LabeledPrice", "Location", "MediaArea", "MediaAreaChannelPost", "MediaAreaCoordinates", "Message", "MessageEntity", "Photo", "Thumbnail",
"Animation", "Audio", "AvailableEffect", "Contact", "Document", "ExtendedMediaPreview", "Game", "GiftedPremium", "Giveaway", "GiveawayLaunched", "GiveawayResult", "LabeledPrice", "Location", "MediaArea", "MediaAreaChannelPost", "MediaAreaCoordinates", "Message", "MessageEntity", "PaidMedia", "Photo", "Thumbnail",
"StrippedThumbnail", "Poll", "PollOption", "Sticker", "StickerSet", "Venue", "Video", "VideoNote", "Voice", "WebPage", "WebPageEmpty", "WebPagePreview", "Dice",
"Reaction", "WebAppData", "MessageInvoice", "MessageReactions", "ReactionCount", "ReactionType", "MessageReactionUpdated", "MessageReactionCountUpdated", "MessageStory", "Story", "StoryDeleted", "StorySkipped", "StoryViews", "StoryForwardHeader", "StoriesPrivacyRules", "ExportedStoryLink"
]

View file

@ -0,0 +1,66 @@
# 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 pyrogram import types
from ..object import Object
class ExtendedMediaPreview(Object):
"""A ExtendedMediaPreview.
Parameters:
width (``int``, *optional*):
Media Width.
height (``int``, *optional*):
Media Height.
thumb (:obj:`~pyrogram.types.StrippedThumbnail`, *optional*):
Media Thumbnail.
video_duration (``int``, *optional*):
Video duration.
"""
def __init__(
self,
*,
width: int = None,
height: int = None,
thumb: "types.Thumbnail" = None,
video_duration: int = None
):
super().__init__()
self.width = width
self.height = height
self.thumb = thumb
self.video_duration = video_duration
@staticmethod
def _parse(client, media: "raw.types.MessageExtendedMediaPreview") -> "ExtendedMediaPreview":
thumb = None
if media.thumb:
thumb = types.StrippedThumbnail._parse(client, media.thumb)
return ExtendedMediaPreview(
width=media.w,
height=media.h,
thumb=thumb,
video_duration=media.video_duration
)

View file

@ -208,6 +208,9 @@ class Message(Object, Update):
photo (:obj:`~pyrogram.types.Photo`, *optional*):
Message is a photo, information about the photo.
paid_media (:obj:`~pyrogram.types.PaidMedia`, *optional*):
Message is a paid media, information about the paid media.
sticker (:obj:`~pyrogram.types.Sticker`, *optional*):
Message is a sticker, information about the sticker.
@ -472,6 +475,7 @@ class Message(Object, Update):
audio: "types.Audio" = None,
document: "types.Document" = None,
photo: "types.Photo" = None,
paid_media: "types.PaidMedia" = None,
sticker: "types.Sticker" = None,
animation: "types.Animation" = None,
game: "types.Game" = None,
@ -582,6 +586,7 @@ class Message(Object, Update):
self.audio = audio
self.document = document
self.photo = photo
self.paid_media = paid_media
self.sticker = sticker
self.animation = animation
self.game = game
@ -859,7 +864,6 @@ class Message(Object, Update):
chat=types.Chat._parse(client, message, users, chats, is_chat=True),
topics=None,
from_user=from_user,
sender_chat=sender_chat,
service=service_type,
new_chat_members=new_chat_members,
chat_joined_by_request=chat_joined_by_request,
@ -895,6 +899,8 @@ class Message(Object, Update):
client=client
# TODO: supergroup_chat_created
)
if parsed_message.chat.type is not enums.ChatType.CHANNEL:
parsed_message.sender_chat = sender_chat
if isinstance(action, raw.types.MessageActionPinMessage):
try:
@ -971,6 +977,7 @@ class Message(Object, Update):
forward_sender_name = forward_header.from_name
photo = None
paid_media = None
location = None
contact = None
venue = None
@ -1077,6 +1084,9 @@ class Message(Object, Update):
elif isinstance(media, raw.types.MessageMediaInvoice):
invoice = types.MessageInvoice._parse(media)
media = enums.MessageMediaType.INVOICE
elif isinstance(media, raw.types.MessageMediaPaidMedia):
paid_media = types.PaidMedia._parse(client, media)
media_type = enums.MessageMediaType.PAID_MEDIA
else:
media = None
@ -1110,7 +1120,6 @@ class Message(Object, Update):
chat=types.Chat._parse(client, message, users, chats, is_chat=True),
topics=None,
from_user=from_user,
sender_chat=sender_chat,
sender_business_bot=sender_business_bot,
text=(
Str(message.message).init(entities) or None
@ -1151,6 +1160,7 @@ class Message(Object, Update):
media_group_id=message.grouped_id,
invert_media=message.invert_media,
photo=photo,
paid_media=paid_media,
location=location,
contact=contact,
venue=venue,
@ -1179,6 +1189,8 @@ class Message(Object, Update):
raw=message,
client=client
)
if parsed_message.chat.type is not enums.ChatType.CHANNEL:
parsed_message.sender_chat = sender_chat
if message.reply_to:
if isinstance(message.reply_to, raw.types.MessageReplyHeader):
@ -4505,7 +4517,12 @@ class Message(Object, Update):
return await self._client.send_poll(
chat_id,
question=self.poll.question,
options=[opt.text for opt in self.poll.options],
options=[
types.PollOption(
text=opt.text,
entities=opt.entities
) for opt in self.poll.options
],
disable_notification=disable_notification,
message_thread_id=message_thread_id,
schedule_date=schedule_date

View file

@ -0,0 +1,78 @@
# 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 PaidMedia(Object):
"""A PaidMedia.
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,
extended_media: List[
Union[
"types.Animation",
"types.ExtendedMediaPreview",
"types.Photo",
"types.Video"
]
] = None
):
super().__init__()
self.stars_amount = stars_amount
self.extended_media = extended_media
@staticmethod
def _parse(client, media: "raw.types.MessageMediaPaidMedia") -> "PaidMedia":
extended_media = []
for m in media.extended_media:
if isinstance(m, raw.types.MessageExtendedMediaPreview):
extended_media.append(types.ExtendedMediaPreview._parse(client, m))
elif isinstance(m.media, raw.types.MessageMediaPhoto):
extended_media.append(types.Photo._parse(client, m.media.photo, m.media.ttl_seconds))
elif isinstance(m.media, raw.types.MessageMediaDocument):
attributes = {type(i): i for i in m.media.document.attributes}
file_name = getattr(
attributes.get(
raw.types.DocumentAttributeFilename, None
), "file_name", None
)
if raw.types.DocumentAttributeAnimated in attributes:
video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None)
extended_media.append(types.Animation._parse(client, m.media.document, video_attributes, file_name))
else:
video_attributes = attributes[raw.types.DocumentAttributeVideo]
extended_media.append(types.Video._parse(client, m.media.document, video_attributes, file_name, m.media.ttl_seconds))
return PaidMedia(
stars_amount=media.stars_amount,
extended_media=extended_media
)

View file

@ -41,6 +41,7 @@ from .chat_privileges import ChatPrivileges
from .chat_reactions import ChatReactions
from .dialog import Dialog
from .emoji_status import EmojiStatus
from .folder import Folder
from .invite_link_importer import InviteLinkImporter
from .restriction import Restriction
from .user import User
@ -72,6 +73,7 @@ __all__ = [
"ChatPhoto",
"ChatPreview",
"Dialog",
"Folder",
"User",
"Username",
"Restriction",

View file

@ -0,0 +1,490 @@
# 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 List, Union
import pyrogram
from pyrogram import enums
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from ..object import Object
class Folder(Object):
"""A user's folder.
Parameters:
id (``int``):
The folder id.
title (``str``):
The folder title.
included_chats (List of :obj:`~pyrogram.types.Chat`, *optional*):
A list of included chats in folder.
excluded_chats (List of :obj:`~pyrogram.types.Chat`, *optional*):
A list of excluded chats in folder.
pinned_chats (List of :obj:`~pyrogram.types.Chat`, *optional*):
A list of pinned chats in folder.
contacts (``bool``, *optional*):
True, if the folder includes contacts.
non_contacts (``bool``, *optional*):
True, if the folder includes non contacts.
groups (``bool``, *optional*):
True, if the folder includes groups.
channels (``bool``, *optional*):
True, if the folder includes channels.
bots (``bool``, *optional*):
True, if the folder includes bots.
exclude_muted (``bool``, *optional*):
True, if the folder exclude muted.
exclude_read (``bool``, *optional*):
True, if the folder exclude read.
exclude_archived (``bool``, *optional*):
True, if the folder exclude archived.
emoji (``str``, *optional*):
Folder emoji.
color (:obj:`~pyrogram.enums.FolderColor`, *optional*)
Chat reply color.
"""
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: int,
title: str,
included_chats: List["types.Chat"] = None,
excluded_chats: List["types.Chat"] = None,
pinned_chats: List["types.Chat"] = None,
contacts: bool = None,
non_contacts: bool = None,
groups: bool = None,
channels: bool = None,
bots: bool = None,
exclude_muted: bool = None,
exclude_read: bool = None,
exclude_archived: bool = None,
emoji: str = None,
color: "enums.FolderColor" = None,
has_my_invites: bool = None
):
super().__init__(client)
self.id = id
self.title = title
self.included_chats = included_chats
self.excluded_chats = excluded_chats
self.pinned_chats = pinned_chats
self.contacts = contacts
self.non_contacts = non_contacts
self.groups = groups
self.channels = channels
self.bots = bots
self.exclude_muted = exclude_muted
self.exclude_read = exclude_read
self.exclude_archived = exclude_archived
self.emoji = emoji
self.color = color
self.has_my_invites = has_my_invites
@staticmethod
def _parse(client, folder: "raw.types.DialogFilter", users, chats) -> "Folder":
included_chats = []
excluded_chats = []
pinned_chats = []
for peer in folder.include_peers:
try:
included_chats.append(types.Chat._parse_dialog(client, peer, users, chats))
except KeyError:
pass
if getattr(folder, "exclude_peers", None):
for peer in folder.exclude_peers:
try:
excluded_chats.append(types.Chat._parse_dialog(client, peer, users, chats))
except KeyError:
pass
for peer in folder.pinned_peers:
try:
pinned_chats.append(types.Chat._parse_dialog(client, peer, users, chats))
except KeyError:
pass
return Folder(
id=folder.id,
title=folder.title,
included_chats=types.List(included_chats) or None,
excluded_chats=types.List(excluded_chats) or None,
pinned_chats=types.List(pinned_chats) or None,
contacts=getattr(folder, "contacts", None),
non_contacts=getattr(folder, "non_contacts", None),
groups=getattr(folder, "groups", None),
channels=getattr(folder, "broadcasts", None),
bots=getattr(folder, "bots", None),
exclude_muted=getattr(folder, "exclude_muted", None),
exclude_read=getattr(folder, "exclude_read", None),
exclude_archived=getattr(folder, "exclude_archived", None),
emoji=folder.emoticon or None,
color=enums.FolderColor(getattr(folder, "color", None)),
has_my_invites=getattr(folder, "has_my_invites", None),
client=client
)
async def delete(self):
"""Bound method *delete* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.delete_folder(123456789)
Example:
.. code-block:: python
await folder.delete()
Returns:
True on success.
"""
return await self._client.delete_folder(self.id)
async def update(
self,
included_chats: List[Union[int, str]] = None,
excluded_chats: List[Union[int, str]] = None,
pinned_chats: List[Union[int, str]] = None,
title: str = None,
contacts: bool = None,
non_contacts: bool = None,
groups: bool = None,
channels: bool = None,
bots: bool = None,
exclude_muted: bool = None,
exclude_read: bool = None,
exclude_archived: bool = None,
emoji: str = None,
color: "enums.FolderColor" = None
):
"""Bound method *update_peers* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id,
title="New folder",
included_chats=["me"]
)
Example:
.. code-block:: python
await folder.update(included_chats=["me"])
Parameters:
included_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should added in the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
excluded_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should excluded from the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
pinned_chats (``int`` | ``str`` | List of ``int`` or ``str``, *optional*):
Users or chats that should pinned in the folder
You can pass an ID (int), username (str) or phone number (str).
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
title (``str``, *optional*):
A folder title was changed to this value.
contacts (``bool``, *optional*):
Pass True if folder should contain contacts.
non_contacts (``bool``, *optional*):
Pass True if folder should contain non contacts.
groups (``bool``, *optional*):
Pass True if folder should contain groups.
channels (``bool``, *optional*):
Pass True if folder should contain channels.
bots (``bool``, *optional*):
Pass True if folder should contain bots.
exclude_muted (``bool``, *optional*):
Pass True if folder should exclude muted users.
exclude_archived (``bool``, *optional*):
Pass True if folder should exclude archived users.
emoji (``str``, *optional*):
Folder emoji.
Pass None to leave the folder icon as default.
color (:obj:`~pyrogram.enums.FolderColor`, *optional*):
Color type.
Pass :obj:`~pyrogram.enums.FolderColor` to set folder color.
Returns:
True on success.
"""
if not included_chats:
included_chats = [i.id for i in self.included_chats or []]
if not included_chats:
excluded_chats = [i.id for i in self.excluded_chats or []]
if not included_chats:
pinned_chats = [i.id for i in self.pinned_chats or []]
return await self._client.update_folder(
folder_id=self.id,
title=title or self.title,
included_chats=included_chats,
excluded_chats=excluded_chats,
pinned_chats=pinned_chats,
contacts=contacts or self.contacts,
non_contacts=non_contacts or self.non_contacts,
groups=groups or self.groups,
channels=channels or self.channels,
bots=bots or self.bots,
exclude_muted=exclude_muted or self.exclude_muted,
exclude_read=exclude_read or self.exclude_read,
exclude_archived=exclude_archived or self.exclude_archived,
emoji=emoji or self.emoji,
color=color or self.color
)
async def include_chat(self, chat_id: Union[int, str]):
"""Bound method *include_chat* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id=123456789,
included_chats=[chat_id],
excluded_chats=[...],
pinned_chats=[...]
)
Example:
.. code-block:: python
await folder.include_chat(chat_id)
Parameters:
chat_id (``int`` | ``str``):
Unique identifier for the target chat or username of the target user/channel/supergroup
(in the format @username).
Returns:
True on success.
"""
return await self.update(
included_chats=[i.id for i in self.included_chats or []] + [chat_id],
excluded_chats=[i.id for i in self.excluded_chats or []],
pinned_chats=[i.id for i in self.pinned_chats or []]
)
async def exclude_chat(self, chat_id: Union[int, str]):
"""Bound method *exclude_chat* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id=123456789,
included_chats=[...],
excluded_chats=[chat_id],
pinned_chats=[...]
)
Example:
.. code-block:: python
await folder.exclude_chat(chat_id)
Parameters:
chat_id (``int`` | ``str``):
Unique identifier for the target chat or username of the target user/channel/supergroup
(in the format @username).
Returns:
True on success.
"""
return await self.update(
included_chats=[i.id for i in self.included_chats or []],
excluded_chats=[i.id for i in self.excluded_chats or []] + [chat_id],
pinned_chats=[i.id for i in self.pinned_chats or []],
)
async def update_color(self, color: "enums.FolderColor"):
"""Bound method *update_color* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id=123456789,
included_chats=[chat_id],
excluded_chats=[chat_id],
pinned_chats=[...],
color=color
)
Example:
.. code-block:: python
await folder.update_color(enums.FolderColor.RED)
Parameters:
color (:obj:`~pyrogram.enums.FolderColor`, *optional*):
Color type.
Pass :obj:`~pyrogram.enums.FolderColor` to set folder color.
Returns:
True on success.
"""
return await self.update(
color=color
)
async def pin_chat(self, chat_id: Union[int, str]):
"""Bound method *pin_chat* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id=123456789,
included_chats=[chat_id],
excluded_chats=[chat_id],
pinned_chats=[...]
)
Example:
.. code-block:: python
await folder.pin_chat(chat_id)
Parameters:
chat_id (``int`` | ``str``):
Unique identifier for the target chat or username of the target user/channel/supergroup
(in the format @username).
Returns:
True on success.
"""
return await self.update(
included_chats=[i.id for i in self.included_chats or []] + [chat_id],
excluded_chats=[i.id for i in self.excluded_chats or []],
pinned_chats=[i.id for i in self.pinned_chats or []] + [chat_id]
)
async def remove_chat(self, chat_id: Union[int, str]):
"""Bound method *remove_chat* of :obj:`~pyrogram.types.Folder`.
Remove chat from included, excluded and pinned chats.
Use as a shortcut for:
.. code-block:: python
await client.update_folder(
folder_id=123456789,
included_chats=[...],
excluded_chats=[...],
pinned_chats=[...]
)
Example:
.. code-block:: python
await folder.remove_chat(chat_id)
Parameters:
chat_id (``int`` | ``str``):
Unique identifier for the target chat or username of the target user/channel/supergroup
(in the format @username).
Returns:
True on success.
"""
peer = await self._client.resolve_peer(chat_id)
peer_id = utils.get_peer_id(peer)
return await self.update(
included_chats=[i.id for i in self.included_chats or [] if peer_id != i.id],
excluded_chats=[i.id for i in self.excluded_chats or [] if peer_id != i.id],
pinned_chats=[i.id for i in self.pinned_chats or [] if peer_id != i.id]
)
async def export_link(self):
"""Bound method *export_link* of :obj:`~pyrogram.types.Folder`.
Use as a shortcut for:
.. code-block:: python
await client.export_folder_link(123456789)
Example:
.. code-block:: python
await folder.export_link()
Returns:
``str``: On success, a link to the folder as string is returned.
"""
return await self._client.export_folder_link(
folder_id=self.id
)