Merge branch 'develop' into develop
This commit is contained in:
commit
f33a192162
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,2 +1,2 @@
|
|||||||
github: delivrance
|
# github: delivrance
|
||||||
custom: https://docs.pyrogram.org/support-pyrogram
|
custom: https://docs.pyrogram.org/support-pyrogram
|
||||||
|
2
.github/ISSUE_TEMPLATE/question.md
vendored
2
.github/ISSUE_TEMPLATE/question.md
vendored
@ -10,6 +10,6 @@ labels: "question"
|
|||||||
# Important
|
# Important
|
||||||
This place is for issues about Pyrogram, it's **not a forum**.
|
This place is for issues about Pyrogram, it's **not a forum**.
|
||||||
|
|
||||||
If you'd like to post a question, please move to https://stackoverflow.com or join the Telegram community at https://t.me/pyrogram.
|
If you'd like to post a question, please move to https://stackoverflow.com or join the Telegram community at https://t.me/pyrogram. Useful information on how to ask good questions can be found here: https://stackoverflow.com/help/how-to-ask.
|
||||||
|
|
||||||
Thanks.
|
Thanks.
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,6 +11,9 @@ pyrogram/api/all.py
|
|||||||
# PyCharm stuff
|
# PyCharm stuff
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
@ -78,6 +81,7 @@ instance/
|
|||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
docs/source/_build
|
||||||
|
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
target/
|
target/
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
## Include
|
## Include
|
||||||
include README.md COPYING COPYING.lesser NOTICE requirements.txt
|
include README.md COPYING COPYING.lesser NOTICE requirements.txt
|
||||||
recursive-include compiler *.py *.tl *.tsv *.txt
|
recursive-include compiler *.py *.tl *.tsv *.txt
|
||||||
recursive-include pyrogram mime.types
|
recursive-include pyrogram mime.types schema.sql
|
||||||
|
|
||||||
## Exclude
|
## Exclude
|
||||||
prune pyrogram/api/errors/exceptions
|
prune pyrogram/errors/exceptions
|
||||||
prune pyrogram/api/functions
|
prune pyrogram/api/functions
|
||||||
prune pyrogram/api/types
|
prune pyrogram/api/types
|
||||||
exclude pyrogram/api/all.py
|
exclude pyrogram/api/all.py
|
@ -28,7 +28,7 @@ app = Client("my_account")
|
|||||||
|
|
||||||
@app.on_message(Filters.private)
|
@app.on_message(Filters.private)
|
||||||
def hello(client, message):
|
def hello(client, message):
|
||||||
message.reply("Hello {}".format(message.from_user.first_name))
|
message.reply_text("Hello {}".format(message.from_user.first_name))
|
||||||
|
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
@ -478,7 +478,6 @@ def start():
|
|||||||
|
|
||||||
f.write("\n 0xbc799737: \"pyrogram.api.core.BoolFalse\",")
|
f.write("\n 0xbc799737: \"pyrogram.api.core.BoolFalse\",")
|
||||||
f.write("\n 0x997275b5: \"pyrogram.api.core.BoolTrue\",")
|
f.write("\n 0x997275b5: \"pyrogram.api.core.BoolTrue\",")
|
||||||
f.write("\n 0x56730bcc: \"pyrogram.api.core.Null\",")
|
|
||||||
f.write("\n 0x1cb5c415: \"pyrogram.api.core.Vector\",")
|
f.write("\n 0x1cb5c415: \"pyrogram.api.core.Vector\",")
|
||||||
f.write("\n 0x73f1f8dc: \"pyrogram.api.core.MsgContainer\",")
|
f.write("\n 0x73f1f8dc: \"pyrogram.api.core.MsgContainer\",")
|
||||||
f.write("\n 0xae500895: \"pyrogram.api.core.FutureSalts\",")
|
f.write("\n 0xae500895: \"pyrogram.api.core.FutureSalts\",")
|
||||||
|
@ -101,11 +101,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
|||||||
chatEmpty#9ba2d800 id:int = Chat;
|
chatEmpty#9ba2d800 id:int = Chat;
|
||||||
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int 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;
|
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int 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#7328bdb id:int title:string = Chat;
|
chatForbidden#7328bdb id:int title:string = Chat;
|
||||||
channel#4df30834 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 id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
channel#4df30834 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 id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||||
|
|
||||||
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
|
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
|
||||||
channelFull#9882e516 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_view_stats:flags.12?true id:int 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:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int 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.13?int pts:int = ChatFull;
|
channelFull#10916653 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_view_stats:flags.12?true can_set_location:flags.16?true id:int 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:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int 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?int location:flags.15?ChannelLocation pts:int = ChatFull;
|
||||||
|
|
||||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||||
@ -189,7 +189,7 @@ inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags
|
|||||||
|
|
||||||
peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;
|
peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;
|
||||||
|
|
||||||
peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings;
|
peerSettings#818426cd flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true = PeerSettings;
|
||||||
|
|
||||||
wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
|
wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
|
||||||
|
|
||||||
@ -199,8 +199,9 @@ inputReportReasonPornography#2e59d922 = ReportReason;
|
|||||||
inputReportReasonChildAbuse#adf44ee3 = ReportReason;
|
inputReportReasonChildAbuse#adf44ee3 = ReportReason;
|
||||||
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
||||||
inputReportReasonCopyright#9b89f93a = ReportReason;
|
inputReportReasonCopyright#9b89f93a = ReportReason;
|
||||||
|
inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
|
||||||
|
|
||||||
userFull#745559cc flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int = UserFull;
|
userFull#edf17c12 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string settings:PeerSettings profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int = UserFull;
|
||||||
|
|
||||||
contact#f911c994 user_id:int mutual:Bool = Contact;
|
contact#f911c994 user_id:int mutual:Bool = Contact;
|
||||||
|
|
||||||
@ -210,8 +211,6 @@ contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
|
|||||||
|
|
||||||
contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus;
|
contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus;
|
||||||
|
|
||||||
contacts.link#3ace484c my_link:ContactLink foreign_link:ContactLink user:User = contacts.Link;
|
|
||||||
|
|
||||||
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
|
contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
|
||||||
contacts.contacts#eae87e42 contacts:Vector<Contact> saved_count:int users:Vector<User> = contacts.Contacts;
|
contacts.contacts#eae87e42 contacts:Vector<Contact> saved_count:int users:Vector<User> = contacts.Contacts;
|
||||||
|
|
||||||
@ -262,7 +261,6 @@ updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
|||||||
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
||||||
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
||||||
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
|
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
|
||||||
updateContactLink#9d2e67c5 user_id:int my_link:ContactLink foreign_link:ContactLink = Update;
|
|
||||||
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
|
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
|
||||||
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
|
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
|
||||||
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
|
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
|
||||||
@ -323,6 +321,8 @@ updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
|
|||||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = 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;
|
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||||
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||||
|
updatePeerSettings#6a7e7366 peer:Peer settings:PeerSettings = Update;
|
||||||
|
updatePeerLocated#b4afcfb0 peers:Vector<PeerLocated> = Update;
|
||||||
|
|
||||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||||
|
|
||||||
@ -468,10 +468,6 @@ messages.allStickers#edfd405f hash:int sets:Vector<StickerSet> = messages.AllSti
|
|||||||
|
|
||||||
messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;
|
messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;
|
||||||
|
|
||||||
contactLinkUnknown#5f4f9247 = ContactLink;
|
|
||||||
contactLinkNone#feedd3ad = ContactLink;
|
|
||||||
contactLinkContact#d502c2d0 = ContactLink;
|
|
||||||
|
|
||||||
webPageEmpty#eb1477e8 id:long = WebPage;
|
webPageEmpty#eb1477e8 id:long = WebPage;
|
||||||
webPagePending#c586da1c id:long date:int = WebPage;
|
webPagePending#c586da1c id:long date:int = WebPage;
|
||||||
webPage#5f07b4bc flags:# 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 = WebPage;
|
webPage#5f07b4bc flags:# 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 = WebPage;
|
||||||
@ -501,7 +497,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
|||||||
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
||||||
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
||||||
|
|
||||||
stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
|
stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
|
||||||
|
|
||||||
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
||||||
|
|
||||||
@ -542,6 +538,9 @@ messageEntityMentionName#352dca58 offset:int length:int user_id:int = MessageEnt
|
|||||||
inputMessageEntityMentionName#208e68c9 offset:int length:int user_id:InputUser = MessageEntity;
|
inputMessageEntityMentionName#208e68c9 offset:int length:int user_id:InputUser = MessageEntity;
|
||||||
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
|
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
|
||||||
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
|
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
|
||||||
|
messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
|
||||||
|
messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
|
||||||
|
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
|
||||||
|
|
||||||
inputChannelEmpty#ee8c1e86 = InputChannel;
|
inputChannelEmpty#ee8c1e86 = InputChannel;
|
||||||
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
|
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
|
||||||
@ -828,6 +827,7 @@ channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = Chann
|
|||||||
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction;
|
||||||
|
channelAdminLogEventActionChangeLocation#e6b76ae prev_value:ChannelLocation new_value:ChannelLocation = ChannelAdminLogEventAction;
|
||||||
|
|
||||||
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
||||||
|
|
||||||
@ -1034,6 +1034,11 @@ urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User
|
|||||||
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
|
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
|
||||||
urlAuthResultDefault#a9d6db1f = UrlAuthResult;
|
urlAuthResultDefault#a9d6db1f = UrlAuthResult;
|
||||||
|
|
||||||
|
channelLocationEmpty#bfb5ad8b = ChannelLocation;
|
||||||
|
channelLocation#209b82db geo_point:GeoPoint address:string = ChannelLocation;
|
||||||
|
|
||||||
|
peerLocated#ca461b5d peer:Peer expires:int distance:int = PeerLocated;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@ -1060,7 +1065,7 @@ auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentC
|
|||||||
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
|
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
|
||||||
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
|
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
|
||||||
|
|
||||||
account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
|
account.registerDevice#68976c6f flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
|
||||||
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
|
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
|
||||||
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
|
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
|
||||||
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
|
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
|
||||||
@ -1124,8 +1129,7 @@ contacts.getContactIDs#2caa4a42 hash:int = Vector<int>;
|
|||||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||||
contacts.getContacts#c023849f hash:int = contacts.Contacts;
|
contacts.getContacts#c023849f hash:int = contacts.Contacts;
|
||||||
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
|
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
|
||||||
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
|
contacts.deleteContacts#96a0e00 id:Vector<InputUser> = Updates;
|
||||||
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
|
|
||||||
contacts.deleteByPhones#1013fd9e phones:Vector<string> = Bool;
|
contacts.deleteByPhones#1013fd9e phones:Vector<string> = Bool;
|
||||||
contacts.block#332b49fc id:InputUser = Bool;
|
contacts.block#332b49fc id:InputUser = Bool;
|
||||||
contacts.unblock#e54100bd id:InputUser = Bool;
|
contacts.unblock#e54100bd id:InputUser = Bool;
|
||||||
@ -1137,6 +1141,9 @@ contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = B
|
|||||||
contacts.resetSaved#879537f1 = Bool;
|
contacts.resetSaved#879537f1 = Bool;
|
||||||
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
||||||
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
|
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
|
||||||
|
contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates;
|
||||||
|
contacts.acceptContact#f831a20f id:InputUser = Updates;
|
||||||
|
contacts.getLocated#a356056 geo_point:InputGeoPoint = Updates;
|
||||||
|
|
||||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||||
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
|
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
|
||||||
@ -1151,7 +1158,6 @@ messages.sendMessage#fa88427a flags:# no_webpage:flags.1?true silent:flags.5?tru
|
|||||||
messages.sendMedia#b8d1262b flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates;
|
messages.sendMedia#b8d1262b flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates;
|
||||||
messages.forwardMessages#708e0195 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true grouped:flags.9?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer = Updates;
|
messages.forwardMessages#708e0195 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true grouped:flags.9?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer = Updates;
|
||||||
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
||||||
messages.hideReportSpam#a8f1709b peer:InputPeer = Bool;
|
|
||||||
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
|
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
|
||||||
messages.report#bd82b658 peer:InputPeer id:Vector<int> reason:ReportReason = Bool;
|
messages.report#bd82b658 peer:InputPeer id:Vector<int> reason:ReportReason = Bool;
|
||||||
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
|
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
|
||||||
@ -1186,7 +1192,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par
|
|||||||
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
||||||
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||||
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||||
messages.searchGlobal#f79c611 q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
messages.searchGlobal#bf7225a4 flags:# folder_id:flags.0?int q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||||
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
||||||
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||||
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
||||||
@ -1251,6 +1257,7 @@ messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
|||||||
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||||
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||||
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||||
|
messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool;
|
||||||
|
|
||||||
updates.getState#edd4882a = updates.State;
|
updates.getState#edd4882a = updates.State;
|
||||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||||
@ -1299,7 +1306,7 @@ channels.getParticipants#123e05e9 channel:InputChannel filter:ChannelParticipant
|
|||||||
channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant;
|
channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant;
|
||||||
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
||||||
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
||||||
channels.createChannel#f4893d7f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string = Updates;
|
channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates;
|
||||||
channels.editAdmin#70f893ba channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights = Updates;
|
channels.editAdmin#70f893ba channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights = Updates;
|
||||||
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
|
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
|
||||||
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
|
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
|
||||||
@ -1311,7 +1318,7 @@ channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> =
|
|||||||
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
||||||
channels.exportMessageLink#ceb77163 channel:InputChannel id:int grouped:Bool = ExportedMessageLink;
|
channels.exportMessageLink#ceb77163 channel:InputChannel id:int grouped:Bool = ExportedMessageLink;
|
||||||
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
|
channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true = messages.Chats;
|
||||||
channels.editBanned#72796912 channel:InputChannel user_id:InputUser banned_rights:ChatBannedRights = Updates;
|
channels.editBanned#72796912 channel:InputChannel user_id:InputUser banned_rights:ChatBannedRights = Updates;
|
||||||
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
||||||
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||||
@ -1320,8 +1327,9 @@ channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
|||||||
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
|
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
|
||||||
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
|
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
|
||||||
channels.getBroadcastsForDiscussion#1a87f304 = messages.Chats;
|
|
||||||
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
|
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
|
||||||
|
channels.editCreator#8f38cd1f channel:InputChannel user_id:InputUser password:InputCheckPasswordSRP = Updates;
|
||||||
|
channels.editLocation#58e63f6d channel:InputChannel geo_point:InputGeoPoint address:string = Bool;
|
||||||
|
|
||||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||||
@ -1356,7 +1364,4 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
|
|||||||
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
||||||
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||||
|
|
||||||
// LAYER 100
|
// LAYER 103
|
||||||
|
|
||||||
// Ports
|
|
||||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
|
@ -53,6 +53,15 @@ ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort;
|
|||||||
accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector<IpPort> = AccessPointRule;
|
accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector<IpPort> = AccessPointRule;
|
||||||
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
|
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
|
||||||
|
|
||||||
|
// tlsClientHello blocks:vector<TlsBlock> = TlsClientHello;
|
||||||
|
//
|
||||||
|
// tlsBlockString data:string = TlsBlock;
|
||||||
|
// tlsBlockRandom length:int = TlsBlock;
|
||||||
|
// tlsBlockZero length:int = TlsBlock;
|
||||||
|
// tlsBlockDomain = TlsBlock;
|
||||||
|
// tlsBlockGrease seed:int = TlsBlock;
|
||||||
|
// tlsBlockScope entries:Vector<TlsBlock> = TlsBlock;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
|
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
|
||||||
|
@ -23,6 +23,7 @@ import shutil
|
|||||||
|
|
||||||
HOME = "compiler/docs"
|
HOME = "compiler/docs"
|
||||||
DESTINATION = "docs/source/telegram"
|
DESTINATION = "docs/source/telegram"
|
||||||
|
PYROGRAM_API_DEST = "docs/source/api"
|
||||||
|
|
||||||
FUNCTIONS_PATH = "pyrogram/api/functions"
|
FUNCTIONS_PATH = "pyrogram/api/functions"
|
||||||
TYPES_PATH = "pyrogram/api/types"
|
TYPES_PATH = "pyrogram/api/types"
|
||||||
@ -117,6 +118,362 @@ def generate(source_path, base):
|
|||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def pyrogram_api():
|
||||||
|
def get_title_list(s: str) -> list:
|
||||||
|
return [i.strip() for i in [j.strip() for j in s.split("\n") if j] if i]
|
||||||
|
|
||||||
|
# Methods
|
||||||
|
|
||||||
|
categories = dict(
|
||||||
|
utilities="""
|
||||||
|
Utilities
|
||||||
|
start
|
||||||
|
stop
|
||||||
|
restart
|
||||||
|
idle
|
||||||
|
run
|
||||||
|
add_handler
|
||||||
|
remove_handler
|
||||||
|
stop_transmission
|
||||||
|
export_session_string
|
||||||
|
set_parse_mode
|
||||||
|
""",
|
||||||
|
messages="""
|
||||||
|
Messages
|
||||||
|
send_message
|
||||||
|
forward_messages
|
||||||
|
send_photo
|
||||||
|
send_audio
|
||||||
|
send_document
|
||||||
|
send_sticker
|
||||||
|
send_video
|
||||||
|
send_animation
|
||||||
|
send_voice
|
||||||
|
send_video_note
|
||||||
|
send_media_group
|
||||||
|
send_location
|
||||||
|
send_venue
|
||||||
|
send_contact
|
||||||
|
send_cached_media
|
||||||
|
edit_message_text
|
||||||
|
edit_message_caption
|
||||||
|
edit_message_media
|
||||||
|
edit_message_reply_markup
|
||||||
|
edit_inline_text
|
||||||
|
edit_inline_caption
|
||||||
|
edit_inline_media
|
||||||
|
edit_inline_reply_markup
|
||||||
|
send_chat_action
|
||||||
|
delete_messages
|
||||||
|
get_messages
|
||||||
|
get_history
|
||||||
|
get_history_count
|
||||||
|
read_history
|
||||||
|
iter_history
|
||||||
|
send_poll
|
||||||
|
vote_poll
|
||||||
|
stop_poll
|
||||||
|
retract_vote
|
||||||
|
download_media
|
||||||
|
""",
|
||||||
|
chats="""
|
||||||
|
Chats
|
||||||
|
join_chat
|
||||||
|
leave_chat
|
||||||
|
kick_chat_member
|
||||||
|
unban_chat_member
|
||||||
|
restrict_chat_member
|
||||||
|
promote_chat_member
|
||||||
|
export_chat_invite_link
|
||||||
|
set_chat_photo
|
||||||
|
delete_chat_photo
|
||||||
|
set_chat_title
|
||||||
|
set_chat_description
|
||||||
|
set_chat_permissions
|
||||||
|
pin_chat_message
|
||||||
|
unpin_chat_message
|
||||||
|
get_chat
|
||||||
|
get_chat_member
|
||||||
|
get_chat_members
|
||||||
|
get_chat_members_count
|
||||||
|
iter_chat_members
|
||||||
|
get_dialogs
|
||||||
|
iter_dialogs
|
||||||
|
get_dialogs_count
|
||||||
|
update_chat_username
|
||||||
|
archive_chats
|
||||||
|
unarchive_chats
|
||||||
|
add_chat_members
|
||||||
|
create_channel
|
||||||
|
create_group
|
||||||
|
create_supergroup
|
||||||
|
delete_channel
|
||||||
|
delete_supergroup
|
||||||
|
""",
|
||||||
|
users="""
|
||||||
|
Users
|
||||||
|
get_me
|
||||||
|
get_users
|
||||||
|
get_profile_photos
|
||||||
|
get_profile_photos_count
|
||||||
|
iter_profile_photos
|
||||||
|
set_profile_photo
|
||||||
|
delete_profile_photos
|
||||||
|
update_username
|
||||||
|
block_user
|
||||||
|
unblock_user
|
||||||
|
""",
|
||||||
|
contacts="""
|
||||||
|
Contacts
|
||||||
|
add_contacts
|
||||||
|
get_contacts
|
||||||
|
get_contacts_count
|
||||||
|
delete_contacts
|
||||||
|
""",
|
||||||
|
password="""
|
||||||
|
Pssword
|
||||||
|
enable_cloud_password
|
||||||
|
change_cloud_password
|
||||||
|
remove_cloud_password
|
||||||
|
""",
|
||||||
|
bots="""
|
||||||
|
Bots
|
||||||
|
get_inline_bot_results
|
||||||
|
send_inline_bot_result
|
||||||
|
answer_callback_query
|
||||||
|
answer_inline_query
|
||||||
|
request_callback_answer
|
||||||
|
send_game
|
||||||
|
set_game_score
|
||||||
|
get_game_high_scores
|
||||||
|
""",
|
||||||
|
advanced="""
|
||||||
|
Advanced
|
||||||
|
send
|
||||||
|
resolve_peer
|
||||||
|
save_file
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
root = PYROGRAM_API_DEST + "/methods"
|
||||||
|
|
||||||
|
shutil.rmtree(root, ignore_errors=True)
|
||||||
|
os.mkdir(root)
|
||||||
|
|
||||||
|
with open(HOME + "/template/methods.rst") as f:
|
||||||
|
template = f.read()
|
||||||
|
|
||||||
|
with open(root + "/index.rst", "w") as f:
|
||||||
|
fmt_keys = {}
|
||||||
|
|
||||||
|
for k, v in categories.items():
|
||||||
|
name, *methods = get_title_list(v)
|
||||||
|
fmt_keys.update({k: "\n ".join("{0} <{0}>".format(m) for m in methods)})
|
||||||
|
|
||||||
|
for method in methods:
|
||||||
|
with open(root + "/{}.rst".format(method), "w") as f2:
|
||||||
|
title = "{}()".format(method)
|
||||||
|
|
||||||
|
f2.write(title + "\n" + "=" * len(title) + "\n\n")
|
||||||
|
f2.write(".. automethod:: pyrogram.Client.{}()".format(method))
|
||||||
|
|
||||||
|
f.write(template.format(**fmt_keys))
|
||||||
|
|
||||||
|
# Types
|
||||||
|
|
||||||
|
categories = dict(
|
||||||
|
users_chats="""
|
||||||
|
Users & Chats
|
||||||
|
User
|
||||||
|
Chat
|
||||||
|
ChatPreview
|
||||||
|
ChatPhoto
|
||||||
|
ChatMember
|
||||||
|
ChatPermissions
|
||||||
|
Dialog
|
||||||
|
""",
|
||||||
|
messages_media="""
|
||||||
|
Messages & Media
|
||||||
|
Message
|
||||||
|
MessageEntity
|
||||||
|
Photo
|
||||||
|
Thumbnail
|
||||||
|
Audio
|
||||||
|
Document
|
||||||
|
Animation
|
||||||
|
Video
|
||||||
|
Voice
|
||||||
|
VideoNote
|
||||||
|
Contact
|
||||||
|
Location
|
||||||
|
Venue
|
||||||
|
Sticker
|
||||||
|
Game
|
||||||
|
WebPage
|
||||||
|
Poll
|
||||||
|
PollOption
|
||||||
|
""",
|
||||||
|
bots_keyboard="""
|
||||||
|
Bots & Keyboards
|
||||||
|
ReplyKeyboardMarkup
|
||||||
|
KeyboardButton
|
||||||
|
ReplyKeyboardRemove
|
||||||
|
InlineKeyboardMarkup
|
||||||
|
InlineKeyboardButton
|
||||||
|
ForceReply
|
||||||
|
CallbackQuery
|
||||||
|
GameHighScore
|
||||||
|
CallbackGame
|
||||||
|
""",
|
||||||
|
input_media="""
|
||||||
|
Input Media
|
||||||
|
InputMedia
|
||||||
|
InputMediaPhoto
|
||||||
|
InputMediaVideo
|
||||||
|
InputMediaAudio
|
||||||
|
InputMediaAnimation
|
||||||
|
InputMediaDocument
|
||||||
|
InputPhoneContact
|
||||||
|
""",
|
||||||
|
inline_mode="""
|
||||||
|
Inline Mode
|
||||||
|
InlineQuery
|
||||||
|
InlineQueryResult
|
||||||
|
InlineQueryResultArticle
|
||||||
|
InlineQueryResultPhoto
|
||||||
|
InlineQueryResultAnimation
|
||||||
|
""",
|
||||||
|
input_message_content="""
|
||||||
|
InputMessageContent
|
||||||
|
InputMessageContent
|
||||||
|
InputTextMessageContent
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
root = PYROGRAM_API_DEST + "/types"
|
||||||
|
|
||||||
|
shutil.rmtree(root, ignore_errors=True)
|
||||||
|
os.mkdir(root)
|
||||||
|
|
||||||
|
with open(HOME + "/template/types.rst") as f:
|
||||||
|
template = f.read()
|
||||||
|
|
||||||
|
with open(root + "/index.rst", "w") as f:
|
||||||
|
fmt_keys = {}
|
||||||
|
|
||||||
|
for k, v in categories.items():
|
||||||
|
name, *types = get_title_list(v)
|
||||||
|
|
||||||
|
fmt_keys.update({k: "\n ".join(types)})
|
||||||
|
|
||||||
|
# noinspection PyShadowingBuiltins
|
||||||
|
for type in types:
|
||||||
|
with open(root + "/{}.rst".format(type), "w") as f2:
|
||||||
|
title = "{}".format(type)
|
||||||
|
|
||||||
|
f2.write(title + "\n" + "=" * len(title) + "\n\n")
|
||||||
|
f2.write(".. autoclass:: pyrogram.{}()".format(type))
|
||||||
|
|
||||||
|
f.write(template.format(**fmt_keys))
|
||||||
|
|
||||||
|
# Bound Methods
|
||||||
|
|
||||||
|
categories = dict(
|
||||||
|
message="""
|
||||||
|
Message
|
||||||
|
Message.click
|
||||||
|
Message.delete
|
||||||
|
Message.download
|
||||||
|
Message.forward
|
||||||
|
Message.pin
|
||||||
|
Message.edit_text
|
||||||
|
Message.edit_caption
|
||||||
|
Message.edit_media
|
||||||
|
Message.edit_reply_markup
|
||||||
|
Message.reply_text
|
||||||
|
Message.reply_animation
|
||||||
|
Message.reply_audio
|
||||||
|
Message.reply_cached_media
|
||||||
|
Message.reply_chat_action
|
||||||
|
Message.reply_contact
|
||||||
|
Message.reply_document
|
||||||
|
Message.reply_game
|
||||||
|
Message.reply_inline_bot_result
|
||||||
|
Message.reply_location
|
||||||
|
Message.reply_media_group
|
||||||
|
Message.reply_photo
|
||||||
|
Message.reply_poll
|
||||||
|
Message.reply_sticker
|
||||||
|
Message.reply_venue
|
||||||
|
Message.reply_video
|
||||||
|
Message.reply_video_note
|
||||||
|
Message.reply_voice
|
||||||
|
""",
|
||||||
|
chat="""
|
||||||
|
Chat
|
||||||
|
Chat.archive
|
||||||
|
Chat.unarchive
|
||||||
|
Chat.set_title
|
||||||
|
Chat.set_description
|
||||||
|
Chat.set_photo
|
||||||
|
Chat.kick_member
|
||||||
|
Chat.unban_member
|
||||||
|
Chat.restrict_member
|
||||||
|
Chat.promote_member
|
||||||
|
Chat.join
|
||||||
|
Chat.leave
|
||||||
|
""",
|
||||||
|
user="""
|
||||||
|
User
|
||||||
|
User.archive
|
||||||
|
User.unarchive
|
||||||
|
User.block
|
||||||
|
User.unblock
|
||||||
|
""",
|
||||||
|
callback_query="""
|
||||||
|
Callback Query
|
||||||
|
CallbackQuery.answer
|
||||||
|
CallbackQuery.edit_message_text
|
||||||
|
CallbackQuery.edit_message_caption
|
||||||
|
CallbackQuery.edit_message_media
|
||||||
|
CallbackQuery.edit_message_reply_markup
|
||||||
|
""",
|
||||||
|
inline_query="""
|
||||||
|
InlineQuery
|
||||||
|
InlineQuery.answer
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
root = PYROGRAM_API_DEST + "/bound-methods"
|
||||||
|
|
||||||
|
shutil.rmtree(root, ignore_errors=True)
|
||||||
|
os.mkdir(root)
|
||||||
|
|
||||||
|
with open(HOME + "/template/bound-methods.rst") as f:
|
||||||
|
template = f.read()
|
||||||
|
|
||||||
|
with open(root + "/index.rst", "w") as f:
|
||||||
|
fmt_keys = {}
|
||||||
|
|
||||||
|
for k, v in categories.items():
|
||||||
|
name, *bound_methods = get_title_list(v)
|
||||||
|
|
||||||
|
fmt_keys.update({"{}_hlist".format(k): "\n ".join("- :meth:`~{}`".format(bm) for bm in bound_methods)})
|
||||||
|
|
||||||
|
fmt_keys.update(
|
||||||
|
{"{}_toctree".format(k): "\n ".join("{} <{}>".format(bm.split(".")[1], bm) for bm in bound_methods)})
|
||||||
|
|
||||||
|
# noinspection PyShadowingBuiltins
|
||||||
|
for bm in bound_methods:
|
||||||
|
with open(root + "/{}.rst".format(bm), "w") as f2:
|
||||||
|
title = "{}()".format(bm)
|
||||||
|
|
||||||
|
f2.write(title + "\n" + "=" * len(title) + "\n\n")
|
||||||
|
f2.write(".. automethod:: pyrogram.{}()".format(bm))
|
||||||
|
|
||||||
|
f.write(template.format(**fmt_keys))
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
global page_template
|
global page_template
|
||||||
global toctree
|
global toctree
|
||||||
@ -131,6 +488,7 @@ def start():
|
|||||||
|
|
||||||
generate(TYPES_PATH, TYPES_BASE)
|
generate(TYPES_PATH, TYPES_BASE)
|
||||||
generate(FUNCTIONS_PATH, FUNCTIONS_BASE)
|
generate(FUNCTIONS_PATH, FUNCTIONS_BASE)
|
||||||
|
pyrogram_api()
|
||||||
|
|
||||||
|
|
||||||
if "__main__" == __name__:
|
if "__main__" == __name__:
|
||||||
@ -138,5 +496,6 @@ if "__main__" == __name__:
|
|||||||
TYPES_PATH = "../../pyrogram/api/types"
|
TYPES_PATH = "../../pyrogram/api/types"
|
||||||
HOME = "."
|
HOME = "."
|
||||||
DESTINATION = "../../docs/source/telegram"
|
DESTINATION = "../../docs/source/telegram"
|
||||||
|
PYROGRAM_API_DEST = "../../docs/source/api"
|
||||||
|
|
||||||
start()
|
start()
|
||||||
|
88
compiler/docs/template/bound-methods.rst
vendored
Normal file
88
compiler/docs/template/bound-methods.rst
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
Bound Methods
|
||||||
|
=============
|
||||||
|
|
||||||
|
Some Pyrogram types define what are called bound methods. Bound methods are functions attached to a class which are
|
||||||
|
accessed via an instance of that class. They make it even easier to call specific methods by automatically inferring
|
||||||
|
some of the required arguments.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_message()
|
||||||
|
def hello(client, message)
|
||||||
|
message.reply("hi")
|
||||||
|
|
||||||
|
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
|
Message
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 3
|
||||||
|
|
||||||
|
{message_hlist}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{message_toctree}
|
||||||
|
|
||||||
|
Chat
|
||||||
|
----
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 4
|
||||||
|
|
||||||
|
{chat_hlist}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{chat_toctree}
|
||||||
|
|
||||||
|
User
|
||||||
|
----
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 2
|
||||||
|
|
||||||
|
{user_hlist}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{user_toctree}
|
||||||
|
|
||||||
|
CallbackQuery
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 3
|
||||||
|
|
||||||
|
{callback_query_hlist}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{callback_query_toctree}
|
||||||
|
|
||||||
|
InlineQuery
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 2
|
||||||
|
|
||||||
|
{inline_query_hlist}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{inline_query_toctree}
|
122
compiler/docs/template/methods.rst
vendored
Normal file
122
compiler/docs/template/methods.rst
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
Available Methods
|
||||||
|
=================
|
||||||
|
|
||||||
|
This page is about Pyrogram methods. All the methods listed here are bound to a :class:`~pyrogram.Client` instance.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 6
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
with app:
|
||||||
|
app.send_message("haskell", "hi")
|
||||||
|
|
||||||
|
.. currentmodule:: pyrogram.Client
|
||||||
|
|
||||||
|
Utilities
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{utilities}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{utilities}
|
||||||
|
|
||||||
|
Messages
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{messages}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{messages}
|
||||||
|
|
||||||
|
Chats
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{chats}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{chats}
|
||||||
|
|
||||||
|
Users
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{users}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{users}
|
||||||
|
|
||||||
|
Contacts
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{contacts}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{contacts}
|
||||||
|
|
||||||
|
Password
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{password}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{password}
|
||||||
|
|
||||||
|
Bots
|
||||||
|
----
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{bots}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{bots}
|
||||||
|
|
||||||
|
Advanced
|
||||||
|
--------
|
||||||
|
|
||||||
|
Learn more about these methods at :doc:`Advanced Usage <../../topics/advanced-usage>`.
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{advanced}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{advanced}
|
95
compiler/docs/template/types.rst
vendored
Normal file
95
compiler/docs/template/types.rst
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
Available Types
|
||||||
|
===============
|
||||||
|
|
||||||
|
This page is about Pyrogram types. All types listed here are accessible through the main package directly.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 1
|
||||||
|
|
||||||
|
from pyrogram import User, Message, ...
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
**Optional** fields may not exist when irrelevant -- i.e.: they will contain the value of ``None`` and aren't shown
|
||||||
|
when, for example, using ``print()``.
|
||||||
|
|
||||||
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
|
|
||||||
|
Users & Chats
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{users_chats}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{users_chats}
|
||||||
|
|
||||||
|
Messages & Media
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{messages_media}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{messages_media}
|
||||||
|
|
||||||
|
Bots & Keyboards
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{bots_keyboard}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{bots_keyboard}
|
||||||
|
|
||||||
|
Input Media
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{input_media}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{input_media}
|
||||||
|
|
||||||
|
Inline Mode
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{inline_mode}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{inline_mode}
|
||||||
|
|
||||||
|
InputMessageContent
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
{input_message_content}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
{input_message_content}
|
@ -81,6 +81,8 @@ def start():
|
|||||||
|
|
||||||
sub_classes = []
|
sub_classes = []
|
||||||
|
|
||||||
|
f_all.write(" \"_\": \"{}\",\n".format(super_class))
|
||||||
|
|
||||||
for j, row in enumerate(reader):
|
for j, row in enumerate(reader):
|
||||||
if j == 0:
|
if j == 0:
|
||||||
continue
|
continue
|
||||||
@ -90,13 +92,13 @@ def start():
|
|||||||
if not row: # Row is empty (blank line)
|
if not row: # Row is empty (blank line)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
id, message = row
|
error_id, error_message = row
|
||||||
|
|
||||||
sub_class = caml(re.sub(r"_X", "_", id))
|
sub_class = caml(re.sub(r"_X", "_", error_id))
|
||||||
|
|
||||||
f_all.write(" \"{}\": \"{}\",\n".format(id, sub_class))
|
f_all.write(" \"{}\": \"{}\",\n".format(error_id, sub_class))
|
||||||
|
|
||||||
sub_classes.append((sub_class, id, message))
|
sub_classes.append((sub_class, error_id, error_message))
|
||||||
|
|
||||||
with open("{}/template/class.txt".format(HOME), "r", encoding="utf-8") as f_class_template:
|
with open("{}/template/class.txt".format(HOME), "r", encoding="utf-8") as f_class_template:
|
||||||
class_template = f_class_template.read()
|
class_template = f_class_template.read()
|
||||||
|
@ -12,10 +12,10 @@ PHONE_NUMBER_UNOCCUPIED The phone number is not yet being used
|
|||||||
USERS_TOO_FEW Not enough users (to create a chat, for example)
|
USERS_TOO_FEW Not enough users (to create a chat, for example)
|
||||||
USERS_TOO_MUCH The maximum number of users has been exceeded (to create a chat, for example)
|
USERS_TOO_MUCH The maximum number of users has been exceeded (to create a chat, for example)
|
||||||
TYPE_CONSTRUCTOR_INVALID The type constructor is invalid
|
TYPE_CONSTRUCTOR_INVALID The type constructor is invalid
|
||||||
FILE_PART_INVALID The file part number is invalid
|
FILE_PART_INVALID The file part number is invalid. The value is not between 0 and 2999
|
||||||
FILE_PARTS_INVALID The number of file parts is invalid
|
FILE_PARTS_INVALID Invalid number of parts. The value is not between 1 and 3000
|
||||||
FILE_PART_X_MISSING Part {x} of the file is missing from storage
|
FILE_PART_X_MISSING Part {x} of the file is missing from storage
|
||||||
MD5_CHECKSUM_INVALID The MD5 checksums do not match
|
MD5_CHECKSUM_INVALID The file's checksum did not match the md5_checksum parameter
|
||||||
PHOTO_INVALID_DIMENSIONS The photo dimensions are invalid
|
PHOTO_INVALID_DIMENSIONS The photo dimensions are invalid
|
||||||
FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid
|
FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid
|
||||||
FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing
|
FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing
|
||||||
@ -41,7 +41,7 @@ PERSISTENT_TIMESTAMP_EMPTY The pts is empty
|
|||||||
CDN_METHOD_INVALID The method can't be used on CDN DCs
|
CDN_METHOD_INVALID The method can't be used on CDN DCs
|
||||||
VOLUME_LOC_NOT_FOUND The volume location can't be found
|
VOLUME_LOC_NOT_FOUND The volume location can't be found
|
||||||
FILE_ID_INVALID The file id is invalid
|
FILE_ID_INVALID The file id is invalid
|
||||||
LOCATION_INVALID The file location is invalid
|
LOCATION_INVALID The file address is invalid
|
||||||
CHAT_ADMIN_REQUIRED The method requires chat admin privileges
|
CHAT_ADMIN_REQUIRED The method requires chat admin privileges
|
||||||
PHONE_NUMBER_BANNED The phone number is banned
|
PHONE_NUMBER_BANNED The phone number is banned
|
||||||
ABOUT_TOO_LONG The about text is too long
|
ABOUT_TOO_LONG The about text is too long
|
||||||
@ -106,4 +106,21 @@ CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel
|
|||||||
LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
|
LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
|
||||||
BROADCAST_ID_INVALID The channel is invalid
|
BROADCAST_ID_INVALID The channel is invalid
|
||||||
MEGAGROUP_ID_INVALID The supergroup is invalid
|
MEGAGROUP_ID_INVALID The supergroup is invalid
|
||||||
|
BUTTON_DATA_INVALID The button callback data contains invalid data or exceeds 64 bytes
|
||||||
|
START_PARAM_INVALID The start parameter is invalid
|
||||||
|
ARTICLE_TITLE_EMPTY The article title is empty
|
||||||
|
FILE_PART_TOO_BIG The size limit (512 KB) for the content of the file part has been exceeded
|
||||||
|
FILE_PART_EMPTY The file part sent is empty
|
||||||
|
FILE_PART_SIZE_INVALID 512 KB cannot be evenly divided by part_size
|
||||||
|
FILE_PART_SIZE_CHANGED The part size is different from the size of one of the previous parts in the same file
|
||||||
|
FILE_MIGRATE_X The file is in Data Center No. {x}
|
||||||
|
RESULT_TYPE_INVALID The result type is invalid
|
||||||
|
PHOTO_THUMB_URL_EMPTY The photo thumb URL is empty
|
||||||
|
PHOTO_THUMB_URL_INVALID The photo thumb URL is invalid
|
||||||
|
PHOTO_CONTENT_URL_EMPTY The photo content URL is empty
|
||||||
|
PHOTO_CONTENT_TYPE_INVALID The photo content type is invalid
|
||||||
|
WEBDOCUMENT_INVALID The web document is invalid
|
||||||
|
WEBDOCUMENT_URL_EMPTY The web document URL is empty
|
||||||
|
WEBDOCUMENT_URL_INVALID The web document URL is invalid
|
||||||
|
WEBDOCUMENT_MIME_INVALID The web document mime type is invalid
|
||||||
BUTTON_URL_INVALID The button url is invalid
|
BUTTON_URL_INVALID The button url is invalid
|
|
@ -1,3 +1,4 @@
|
|||||||
id message
|
id message
|
||||||
AUTH_KEY_DUPLICATED Authorization error - you must delete your session file and log in again with your phone number
|
AUTH_KEY_DUPLICATED Authorization error - you must delete your session file and log in again with your phone number
|
||||||
FILEREF_UPGRADE_NEEDED The file reference has expired - you must obtain the original media message
|
FILEREF_UPGRADE_NEEDED The file reference has expired - you must obtain the original media message
|
||||||
|
STICKERSET_INVALID The sticker set is invalid
|
|
@ -10,3 +10,4 @@ WORKER_BUSY_TOO_LONG_RETRY Telegram is having internal problems. Please try agai
|
|||||||
INTERDC_X_CALL_ERROR Telegram is having internal problems at DC{x}. Please try again later
|
INTERDC_X_CALL_ERROR Telegram is having internal problems at DC{x}. Please try again later
|
||||||
INTERDC_X_CALL_RICH_ERROR Telegram is having internal problems at DC{x}. Please try again later
|
INTERDC_X_CALL_RICH_ERROR Telegram is having internal problems at DC{x}. Please try again later
|
||||||
FOLDER_DEAC_AUTOFIX_ALL Telegram is having internal problems. Please try again later
|
FOLDER_DEAC_AUTOFIX_ALL Telegram is having internal problems. Please try again later
|
||||||
|
MSGID_DECREASE_RETRY Telegram is having internal problems. Please try again later
|
|
@ -35,8 +35,7 @@ backwards-incompatible changes made in that version.
|
|||||||
When upgrading to a new version of Pyrogram, you will need to check all the breaking changes in order to find
|
When upgrading to a new version of Pyrogram, you will need to check all the breaking changes in order to find
|
||||||
incompatible code in your application, but also to take advantage of new features and improvements.
|
incompatible code in your application, but also to take advantage of new features and improvements.
|
||||||
|
|
||||||
Releases
|
**Contents**
|
||||||
--------
|
|
||||||
|
|
||||||
""".lstrip("\n")
|
""".lstrip("\n")
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ User-agent: *
|
|||||||
|
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
Disallow: /dev/*
|
Disallow: /dev*
|
||||||
Disallow: /old/*
|
Disallow: /v0*
|
||||||
|
|
||||||
Sitemap: https://docs.pyrogram.org/sitemap.xml
|
Sitemap: https://docs.pyrogram.org/sitemap.xml
|
@ -1,142 +0,0 @@
|
|||||||
Bound Methods
|
|
||||||
=============
|
|
||||||
|
|
||||||
Some Pyrogram types define what are called bound methods. Bound methods are functions attached to a class which are
|
|
||||||
accessed via an instance of that class. They make it even easier to call specific methods by automatically inferring
|
|
||||||
some of the required arguments.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:emphasize-lines: 8
|
|
||||||
|
|
||||||
from pyrogram import Client
|
|
||||||
|
|
||||||
app = Client("my_account")
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_message()
|
|
||||||
def hello(client, message)
|
|
||||||
message.reply("hi")
|
|
||||||
|
|
||||||
|
|
||||||
app.run()
|
|
||||||
|
|
||||||
.. currentmodule:: pyrogram
|
|
||||||
|
|
||||||
Index
|
|
||||||
-----
|
|
||||||
|
|
||||||
Message
|
|
||||||
^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Message.click`
|
|
||||||
- :meth:`~Message.delete`
|
|
||||||
- :meth:`~Message.download`
|
|
||||||
- :meth:`~Message.edit`
|
|
||||||
- :meth:`~Message.edit_caption`
|
|
||||||
- :meth:`~Message.edit_media`
|
|
||||||
- :meth:`~Message.edit_reply_markup`
|
|
||||||
- :meth:`~Message.forward`
|
|
||||||
- :meth:`~Message.pin`
|
|
||||||
- :meth:`~Message.reply`
|
|
||||||
- :meth:`~Message.reply_animation`
|
|
||||||
- :meth:`~Message.reply_audio`
|
|
||||||
- :meth:`~Message.reply_cached_media`
|
|
||||||
- :meth:`~Message.reply_chat_action`
|
|
||||||
- :meth:`~Message.reply_contact`
|
|
||||||
- :meth:`~Message.reply_document`
|
|
||||||
- :meth:`~Message.reply_game`
|
|
||||||
- :meth:`~Message.reply_inline_bot_result`
|
|
||||||
- :meth:`~Message.reply_location`
|
|
||||||
- :meth:`~Message.reply_media_group`
|
|
||||||
- :meth:`~Message.reply_photo`
|
|
||||||
- :meth:`~Message.reply_poll`
|
|
||||||
- :meth:`~Message.reply_sticker`
|
|
||||||
- :meth:`~Message.reply_venue`
|
|
||||||
- :meth:`~Message.reply_video`
|
|
||||||
- :meth:`~Message.reply_video_note`
|
|
||||||
- :meth:`~Message.reply_voice`
|
|
||||||
|
|
||||||
Chat
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 2
|
|
||||||
|
|
||||||
- :meth:`~Chat.archive`
|
|
||||||
- :meth:`~Chat.unarchive`
|
|
||||||
|
|
||||||
User
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 2
|
|
||||||
|
|
||||||
- :meth:`~User.archive`
|
|
||||||
- :meth:`~User.unarchive`
|
|
||||||
|
|
||||||
CallbackQuery
|
|
||||||
^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 2
|
|
||||||
|
|
||||||
- :meth:`~CallbackQuery.answer`
|
|
||||||
|
|
||||||
InlineQuery
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 2
|
|
||||||
|
|
||||||
- :meth:`~InlineQuery.answer`
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Details
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. Message
|
|
||||||
.. automethod:: Message.click()
|
|
||||||
.. automethod:: Message.delete()
|
|
||||||
.. automethod:: Message.download()
|
|
||||||
.. automethod:: Message.edit()
|
|
||||||
.. automethod:: Message.edit_caption()
|
|
||||||
.. automethod:: Message.edit_media()
|
|
||||||
.. automethod:: Message.edit_reply_markup()
|
|
||||||
.. automethod:: Message.forward()
|
|
||||||
.. automethod:: Message.pin()
|
|
||||||
.. automethod:: Message.reply()
|
|
||||||
.. automethod:: Message.reply_animation()
|
|
||||||
.. automethod:: Message.reply_audio()
|
|
||||||
.. automethod:: Message.reply_cached_media()
|
|
||||||
.. automethod:: Message.reply_chat_action()
|
|
||||||
.. automethod:: Message.reply_contact()
|
|
||||||
.. automethod:: Message.reply_document()
|
|
||||||
.. automethod:: Message.reply_game()
|
|
||||||
.. automethod:: Message.reply_inline_bot_result()
|
|
||||||
.. automethod:: Message.reply_location()
|
|
||||||
.. automethod:: Message.reply_media_group()
|
|
||||||
.. automethod:: Message.reply_photo()
|
|
||||||
.. automethod:: Message.reply_poll()
|
|
||||||
.. automethod:: Message.reply_sticker()
|
|
||||||
.. automethod:: Message.reply_venue()
|
|
||||||
.. automethod:: Message.reply_video()
|
|
||||||
.. automethod:: Message.reply_video_note()
|
|
||||||
.. automethod:: Message.reply_voice()
|
|
||||||
|
|
||||||
.. Chat
|
|
||||||
.. automethod:: Chat.archive()
|
|
||||||
.. automethod:: Chat.unarchive()
|
|
||||||
|
|
||||||
.. User
|
|
||||||
.. automethod:: User.archive()
|
|
||||||
.. automethod:: User.unarchive()
|
|
||||||
|
|
||||||
.. CallbackQuery
|
|
||||||
.. automethod:: CallbackQuery.answer()
|
|
||||||
|
|
||||||
.. InlineQuery
|
|
||||||
.. automethod:: InlineQuery.answer()
|
|
@ -1,7 +1,11 @@
|
|||||||
Pyrogram Client
|
Pyrogram Client
|
||||||
===============
|
===============
|
||||||
|
|
||||||
This is the Client class. It exposes high-level methods for an easy access to the API.
|
You have entered the API Reference section where you can find detailed information about Pyrogram's API. The main Client
|
||||||
|
class, all available methods and types, filters, handlers, decorators and bound-methods detailed descriptions can be
|
||||||
|
found starting from this page.
|
||||||
|
|
||||||
|
This page is about the Client class, which exposes high-level methods for an easy access to the API.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:emphasize-lines: 1-3
|
:emphasize-lines: 1-3
|
||||||
|
@ -6,7 +6,7 @@ deserve a dedicated page.
|
|||||||
|
|
||||||
Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to
|
Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to
|
||||||
:doc:`Handlers <handlers>`; they do so by instantiating the correct handler and calling
|
:doc:`Handlers <handlers>`; they do so by instantiating the correct handler and calling
|
||||||
:meth:`~pyrogram.Client.add_handler`, automatically. All you need to do is adding the decorators on top of your
|
:meth:`~pyrogram.Client.add_handler` automatically. All you need to do is adding the decorators on top of your
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -2,10 +2,7 @@ Update Handlers
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions.
|
Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions.
|
||||||
|
|
||||||
For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
|
For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
|
||||||
In case you decided to manually create a handler, use :class:`~pyrogram.Client.add_handler` to register
|
|
||||||
it.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:emphasize-lines: 1, 10
|
:emphasize-lines: 1, 10
|
||||||
|
@ -1,282 +0,0 @@
|
|||||||
Available Methods
|
|
||||||
=================
|
|
||||||
|
|
||||||
All Pyrogram methods listed here are bound to a :class:`~pyrogram.Client` instance.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:emphasize-lines: 6
|
|
||||||
|
|
||||||
from pyrogram import Client
|
|
||||||
|
|
||||||
app = Client("my_account")
|
|
||||||
|
|
||||||
with app:
|
|
||||||
app.send_message("haskell", "hi")
|
|
||||||
|
|
||||||
.. currentmodule:: pyrogram
|
|
||||||
|
|
||||||
Index
|
|
||||||
-----
|
|
||||||
|
|
||||||
Utilities
|
|
||||||
^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 4
|
|
||||||
|
|
||||||
- :meth:`~Client.start`
|
|
||||||
- :meth:`~Client.stop`
|
|
||||||
- :meth:`~Client.restart`
|
|
||||||
- :meth:`~Client.idle`
|
|
||||||
- :meth:`~Client.run`
|
|
||||||
- :meth:`~Client.add_handler`
|
|
||||||
- :meth:`~Client.remove_handler`
|
|
||||||
- :meth:`~Client.stop_transmission`
|
|
||||||
|
|
||||||
Messages
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.send_message`
|
|
||||||
- :meth:`~Client.forward_messages`
|
|
||||||
- :meth:`~Client.send_photo`
|
|
||||||
- :meth:`~Client.send_audio`
|
|
||||||
- :meth:`~Client.send_document`
|
|
||||||
- :meth:`~Client.send_sticker`
|
|
||||||
- :meth:`~Client.send_animated_sticker`
|
|
||||||
- :meth:`~Client.send_video`
|
|
||||||
- :meth:`~Client.send_animation`
|
|
||||||
- :meth:`~Client.send_voice`
|
|
||||||
- :meth:`~Client.send_video_note`
|
|
||||||
- :meth:`~Client.send_media_group`
|
|
||||||
- :meth:`~Client.send_location`
|
|
||||||
- :meth:`~Client.send_venue`
|
|
||||||
- :meth:`~Client.send_contact`
|
|
||||||
- :meth:`~Client.send_cached_media`
|
|
||||||
- :meth:`~Client.send_chat_action`
|
|
||||||
- :meth:`~Client.edit_message_text`
|
|
||||||
- :meth:`~Client.edit_message_caption`
|
|
||||||
- :meth:`~Client.edit_message_reply_markup`
|
|
||||||
- :meth:`~Client.edit_message_media`
|
|
||||||
- :meth:`~Client.delete_messages`
|
|
||||||
- :meth:`~Client.get_messages`
|
|
||||||
- :meth:`~Client.get_history`
|
|
||||||
- :meth:`~Client.get_history_count`
|
|
||||||
- :meth:`~Client.read_history`
|
|
||||||
- :meth:`~Client.iter_history`
|
|
||||||
- :meth:`~Client.send_poll`
|
|
||||||
- :meth:`~Client.vote_poll`
|
|
||||||
- :meth:`~Client.stop_poll`
|
|
||||||
- :meth:`~Client.retract_vote`
|
|
||||||
- :meth:`~Client.download_media`
|
|
||||||
|
|
||||||
Chats
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.join_chat`
|
|
||||||
- :meth:`~Client.leave_chat`
|
|
||||||
- :meth:`~Client.kick_chat_member`
|
|
||||||
- :meth:`~Client.unban_chat_member`
|
|
||||||
- :meth:`~Client.restrict_chat_member`
|
|
||||||
- :meth:`~Client.promote_chat_member`
|
|
||||||
- :meth:`~Client.export_chat_invite_link`
|
|
||||||
- :meth:`~Client.set_chat_photo`
|
|
||||||
- :meth:`~Client.delete_chat_photo`
|
|
||||||
- :meth:`~Client.set_chat_title`
|
|
||||||
- :meth:`~Client.set_chat_description`
|
|
||||||
- :meth:`~Client.pin_chat_message`
|
|
||||||
- :meth:`~Client.unpin_chat_message`
|
|
||||||
- :meth:`~Client.get_chat`
|
|
||||||
- :meth:`~Client.get_chat_member`
|
|
||||||
- :meth:`~Client.get_chat_members`
|
|
||||||
- :meth:`~Client.get_chat_members_count`
|
|
||||||
- :meth:`~Client.iter_chat_members`
|
|
||||||
- :meth:`~Client.get_dialogs`
|
|
||||||
- :meth:`~Client.iter_dialogs`
|
|
||||||
- :meth:`~Client.get_dialogs_count`
|
|
||||||
- :meth:`~Client.restrict_chat`
|
|
||||||
- :meth:`~Client.update_chat_username`
|
|
||||||
- :meth:`~Client.archive_chats`
|
|
||||||
- :meth:`~Client.unarchive_chats`
|
|
||||||
|
|
||||||
Users
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.get_me`
|
|
||||||
- :meth:`~Client.get_users`
|
|
||||||
- :meth:`~Client.get_profile_photos`
|
|
||||||
- :meth:`~Client.get_profile_photos_count`
|
|
||||||
- :meth:`~Client.iter_profile_photos`
|
|
||||||
- :meth:`~Client.set_profile_photo`
|
|
||||||
- :meth:`~Client.delete_profile_photos`
|
|
||||||
- :meth:`~Client.update_username`
|
|
||||||
- :meth:`~Client.get_user_dc`
|
|
||||||
|
|
||||||
Contacts
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.add_contacts`
|
|
||||||
- :meth:`~Client.get_contacts`
|
|
||||||
- :meth:`~Client.get_contacts_count`
|
|
||||||
- :meth:`~Client.delete_contacts`
|
|
||||||
|
|
||||||
Password
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.enable_cloud_password`
|
|
||||||
- :meth:`~Client.change_cloud_password`
|
|
||||||
- :meth:`~Client.remove_cloud_password`
|
|
||||||
|
|
||||||
Bots
|
|
||||||
^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :meth:`~Client.get_inline_bot_results`
|
|
||||||
- :meth:`~Client.send_inline_bot_result`
|
|
||||||
- :meth:`~Client.answer_callback_query`
|
|
||||||
- :meth:`~Client.answer_inline_query`
|
|
||||||
- :meth:`~Client.request_callback_answer`
|
|
||||||
- :meth:`~Client.send_game`
|
|
||||||
- :meth:`~Client.set_game_score`
|
|
||||||
- :meth:`~Client.get_game_high_scores`
|
|
||||||
|
|
||||||
Advanced Usage (Raw API)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Learn more about these methods at :doc:`Advanced Usage <../topics/advanced-usage>`.
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 4
|
|
||||||
|
|
||||||
- :meth:`~Client.send`
|
|
||||||
- :meth:`~Client.resolve_peer`
|
|
||||||
- :meth:`~Client.save_file`
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Details
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. Utilities
|
|
||||||
.. automethod:: Client.start()
|
|
||||||
.. automethod:: Client.stop()
|
|
||||||
.. automethod:: Client.restart()
|
|
||||||
.. automethod:: Client.idle()
|
|
||||||
.. automethod:: Client.run()
|
|
||||||
.. automethod:: Client.add_handler()
|
|
||||||
.. automethod:: Client.remove_handler()
|
|
||||||
.. automethod:: Client.stop_transmission()
|
|
||||||
|
|
||||||
.. Messages
|
|
||||||
.. automethod:: Client.send_message()
|
|
||||||
.. automethod:: Client.forward_messages()
|
|
||||||
.. automethod:: Client.send_photo()
|
|
||||||
.. automethod:: Client.send_audio()
|
|
||||||
.. automethod:: Client.send_document()
|
|
||||||
.. automethod:: Client.send_sticker()
|
|
||||||
.. automethod:: Client.send_animated_sticker()
|
|
||||||
.. automethod:: Client.send_video()
|
|
||||||
.. automethod:: Client.send_animation()
|
|
||||||
.. automethod:: Client.send_voice()
|
|
||||||
.. automethod:: Client.send_video_note()
|
|
||||||
.. automethod:: Client.send_media_group()
|
|
||||||
.. automethod:: Client.send_location()
|
|
||||||
.. automethod:: Client.send_venue()
|
|
||||||
.. automethod:: Client.send_contact()
|
|
||||||
.. automethod:: Client.send_cached_media()
|
|
||||||
.. automethod:: Client.send_chat_action()
|
|
||||||
.. automethod:: Client.edit_message_text()
|
|
||||||
.. automethod:: Client.edit_message_caption()
|
|
||||||
.. automethod:: Client.edit_message_reply_markup()
|
|
||||||
.. automethod:: Client.edit_message_media()
|
|
||||||
.. automethod:: Client.delete_messages()
|
|
||||||
.. automethod:: Client.get_messages()
|
|
||||||
.. automethod:: Client.get_history()
|
|
||||||
.. automethod:: Client.get_history_count()
|
|
||||||
.. automethod:: Client.read_history()
|
|
||||||
.. automethod:: Client.iter_history()
|
|
||||||
.. automethod:: Client.send_poll()
|
|
||||||
.. automethod:: Client.vote_poll()
|
|
||||||
.. automethod:: Client.stop_poll()
|
|
||||||
.. automethod:: Client.retract_vote()
|
|
||||||
.. automethod:: Client.download_media()
|
|
||||||
|
|
||||||
.. Chats
|
|
||||||
.. automethod:: Client.join_chat()
|
|
||||||
.. automethod:: Client.leave_chat()
|
|
||||||
.. automethod:: Client.kick_chat_member()
|
|
||||||
.. automethod:: Client.unban_chat_member()
|
|
||||||
.. automethod:: Client.restrict_chat_member()
|
|
||||||
.. automethod:: Client.promote_chat_member()
|
|
||||||
.. automethod:: Client.export_chat_invite_link()
|
|
||||||
.. automethod:: Client.set_chat_photo()
|
|
||||||
.. automethod:: Client.delete_chat_photo()
|
|
||||||
.. automethod:: Client.set_chat_title()
|
|
||||||
.. automethod:: Client.set_chat_description()
|
|
||||||
.. automethod:: Client.pin_chat_message()
|
|
||||||
.. automethod:: Client.unpin_chat_message()
|
|
||||||
.. automethod:: Client.get_chat()
|
|
||||||
.. automethod:: Client.get_chat_member()
|
|
||||||
.. automethod:: Client.get_chat_members()
|
|
||||||
.. automethod:: Client.get_chat_members_count()
|
|
||||||
.. automethod:: Client.iter_chat_members()
|
|
||||||
.. automethod:: Client.get_dialogs()
|
|
||||||
.. automethod:: Client.iter_dialogs()
|
|
||||||
.. automethod:: Client.get_dialogs_count()
|
|
||||||
.. automethod:: Client.restrict_chat()
|
|
||||||
.. automethod:: Client.update_chat_username()
|
|
||||||
.. automethod:: Client.archive_chats()
|
|
||||||
.. automethod:: Client.unarchive_chats()
|
|
||||||
|
|
||||||
.. Users
|
|
||||||
.. automethod:: Client.get_me()
|
|
||||||
.. automethod:: Client.get_users()
|
|
||||||
.. automethod:: Client.get_profile_photos()
|
|
||||||
.. automethod:: Client.get_profile_photos_count()
|
|
||||||
.. automethod:: Client.iter_profile_photos()
|
|
||||||
.. automethod:: Client.set_profile_photo()
|
|
||||||
.. automethod:: Client.delete_profile_photos()
|
|
||||||
.. automethod:: Client.update_username()
|
|
||||||
.. automethod:: Client.get_user_dc()
|
|
||||||
|
|
||||||
.. Contacts
|
|
||||||
.. automethod:: Client.add_contacts()
|
|
||||||
.. automethod:: Client.get_contacts()
|
|
||||||
.. automethod:: Client.get_contacts_count()
|
|
||||||
.. automethod:: Client.delete_contacts()
|
|
||||||
|
|
||||||
.. Password
|
|
||||||
.. automethod:: Client.enable_cloud_password()
|
|
||||||
.. automethod:: Client.change_cloud_password()
|
|
||||||
.. automethod:: Client.remove_cloud_password()
|
|
||||||
|
|
||||||
.. Bots
|
|
||||||
.. automethod:: Client.get_inline_bot_results()
|
|
||||||
.. automethod:: Client.send_inline_bot_result()
|
|
||||||
.. automethod:: Client.answer_callback_query()
|
|
||||||
.. automethod:: Client.answer_inline_query()
|
|
||||||
.. automethod:: Client.request_callback_answer()
|
|
||||||
.. automethod:: Client.send_game()
|
|
||||||
.. automethod:: Client.set_game_score()
|
|
||||||
.. automethod:: Client.get_game_high_scores()
|
|
||||||
|
|
||||||
.. Advanced Usage
|
|
||||||
.. automethod:: Client.send()
|
|
||||||
.. automethod:: Client.resolve_peer()
|
|
||||||
.. automethod:: Client.save_file()
|
|
@ -1,170 +0,0 @@
|
|||||||
Available Types
|
|
||||||
===============
|
|
||||||
|
|
||||||
All Pyrogram types listed here are accessible through the main package directly.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:emphasize-lines: 1
|
|
||||||
|
|
||||||
from pyrogram import User, Message, ...
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
**Optional** fields may not exist when irrelevant -- i.e.: they will contain the value of ``None`` and aren't shown
|
|
||||||
when, for example, using ``print()``.
|
|
||||||
|
|
||||||
.. currentmodule:: pyrogram
|
|
||||||
|
|
||||||
Index
|
|
||||||
-----
|
|
||||||
|
|
||||||
Users & Chats
|
|
||||||
^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 5
|
|
||||||
|
|
||||||
- :class:`User`
|
|
||||||
- :class:`UserStatus`
|
|
||||||
- :class:`Chat`
|
|
||||||
- :class:`ChatPreview`
|
|
||||||
- :class:`ChatPhoto`
|
|
||||||
- :class:`ChatMember`
|
|
||||||
- :class:`ChatPermissions`
|
|
||||||
- :class:`Dialog`
|
|
||||||
|
|
||||||
Messages & Media
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 5
|
|
||||||
|
|
||||||
- :class:`Message`
|
|
||||||
- :class:`MessageEntity`
|
|
||||||
- :class:`Photo`
|
|
||||||
- :class:`Thumbnail`
|
|
||||||
- :class:`Audio`
|
|
||||||
- :class:`Document`
|
|
||||||
- :class:`Animation`
|
|
||||||
- :class:`Video`
|
|
||||||
- :class:`Voice`
|
|
||||||
- :class:`VideoNote`
|
|
||||||
- :class:`Contact`
|
|
||||||
- :class:`Location`
|
|
||||||
- :class:`Venue`
|
|
||||||
- :class:`Sticker`
|
|
||||||
- :class:`Game`
|
|
||||||
- :class:`Poll`
|
|
||||||
- :class:`PollOption`
|
|
||||||
|
|
||||||
Bots & Keyboards
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 4
|
|
||||||
|
|
||||||
- :class:`ReplyKeyboardMarkup`
|
|
||||||
- :class:`KeyboardButton`
|
|
||||||
- :class:`ReplyKeyboardRemove`
|
|
||||||
- :class:`InlineKeyboardMarkup`
|
|
||||||
- :class:`InlineKeyboardButton`
|
|
||||||
- :class:`ForceReply`
|
|
||||||
- :class:`CallbackQuery`
|
|
||||||
- :class:`GameHighScore`
|
|
||||||
- :class:`CallbackGame`
|
|
||||||
|
|
||||||
Input Media
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 4
|
|
||||||
|
|
||||||
- :class:`InputMedia`
|
|
||||||
- :class:`InputMediaPhoto`
|
|
||||||
- :class:`InputMediaVideo`
|
|
||||||
- :class:`InputMediaAudio`
|
|
||||||
- :class:`InputMediaAnimation`
|
|
||||||
- :class:`InputMediaDocument`
|
|
||||||
- :class:`InputPhoneContact`
|
|
||||||
|
|
||||||
Inline Mode
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :class:`InlineQuery`
|
|
||||||
- :class:`InlineQueryResult`
|
|
||||||
- :class:`InlineQueryResultArticle`
|
|
||||||
|
|
||||||
InputMessageContent
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. hlist::
|
|
||||||
:columns: 3
|
|
||||||
|
|
||||||
- :class:`InputMessageContent`
|
|
||||||
- :class:`InputTextMessageContent`
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Details
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. User & Chats
|
|
||||||
.. autoclass:: User()
|
|
||||||
.. autoclass:: UserStatus()
|
|
||||||
.. autoclass:: Chat()
|
|
||||||
.. autoclass:: ChatPreview()
|
|
||||||
.. autoclass:: ChatPhoto()
|
|
||||||
.. autoclass:: ChatMember()
|
|
||||||
.. autoclass:: ChatPermissions()
|
|
||||||
.. autoclass:: Dialog()
|
|
||||||
|
|
||||||
.. Messages & Media
|
|
||||||
.. autoclass:: Message()
|
|
||||||
.. autoclass:: MessageEntity()
|
|
||||||
.. autoclass:: Photo()
|
|
||||||
.. autoclass:: Thumbnail()
|
|
||||||
.. autoclass:: Audio()
|
|
||||||
.. autoclass:: Document()
|
|
||||||
.. autoclass:: Animation()
|
|
||||||
.. autoclass:: Video()
|
|
||||||
.. autoclass:: Voice()
|
|
||||||
.. autoclass:: VideoNote()
|
|
||||||
.. autoclass:: Contact()
|
|
||||||
.. autoclass:: Location()
|
|
||||||
.. autoclass:: Venue()
|
|
||||||
.. autoclass:: Sticker()
|
|
||||||
.. autoclass:: Game()
|
|
||||||
.. autoclass:: Poll()
|
|
||||||
.. autoclass:: PollOption()
|
|
||||||
|
|
||||||
.. Bots & Keyboards
|
|
||||||
.. autoclass:: ReplyKeyboardMarkup()
|
|
||||||
.. autoclass:: KeyboardButton()
|
|
||||||
.. autoclass:: ReplyKeyboardRemove()
|
|
||||||
.. autoclass:: InlineKeyboardMarkup()
|
|
||||||
.. autoclass:: InlineKeyboardButton()
|
|
||||||
.. autoclass:: ForceReply()
|
|
||||||
.. autoclass:: CallbackQuery()
|
|
||||||
.. autoclass:: GameHighScore()
|
|
||||||
.. autoclass:: CallbackGame()
|
|
||||||
|
|
||||||
.. Input Media
|
|
||||||
.. autoclass:: InputMedia()
|
|
||||||
.. autoclass:: InputMediaPhoto()
|
|
||||||
.. autoclass:: InputMediaVideo()
|
|
||||||
.. autoclass:: InputMediaAudio()
|
|
||||||
.. autoclass:: InputMediaAnimation()
|
|
||||||
.. autoclass:: InputMediaDocument()
|
|
||||||
.. autoclass:: InputPhoneContact()
|
|
||||||
|
|
||||||
.. Inline Mode
|
|
||||||
.. autoclass:: InlineQuery()
|
|
||||||
.. autoclass:: InlineQueryResult()
|
|
||||||
.. autoclass:: InlineQueryResultArticle()
|
|
||||||
|
|
||||||
.. InputMessageContent
|
|
||||||
.. autoclass:: InputMessageContent()
|
|
||||||
.. autoclass:: InputTextMessageContent()
|
|
@ -66,3 +66,15 @@ html_theme_options = {
|
|||||||
|
|
||||||
html_logo = "_images/pyrogram.png"
|
html_logo = "_images/pyrogram.png"
|
||||||
html_favicon = "_images/favicon.ico"
|
html_favicon = "_images/favicon.ico"
|
||||||
|
|
||||||
|
latex_engine = "xelatex"
|
||||||
|
latex_logo = "_images/pyrogram.png"
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
"pointsize": "12pt",
|
||||||
|
"fontpkg": r"""
|
||||||
|
\setmainfont{Noto Sans}
|
||||||
|
\setsansfont{Roboto Slab}
|
||||||
|
\setmonofont{Ubuntu Mono}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
Pyrogram FAQ
|
Pyrogram FAQ
|
||||||
============
|
============
|
||||||
|
|
||||||
|
.. role:: strike
|
||||||
|
:class: strike
|
||||||
|
|
||||||
This FAQ page provides answers to common questions about Pyrogram and, to some extent, Telegram in general.
|
This FAQ page provides answers to common questions about Pyrogram and, to some extent, Telegram in general.
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
@ -65,7 +68,7 @@ To challenge the framework, the creator is constantly keeping a public
|
|||||||
`welcome bot <https://github.com/pyrogram/pyrogram/blob/develop/examples/welcomebot.py>`_ online 24/7 on his own,
|
`welcome bot <https://github.com/pyrogram/pyrogram/blob/develop/examples/welcomebot.py>`_ online 24/7 on his own,
|
||||||
relatively-busy account for well over a year now.
|
relatively-busy account for well over a year now.
|
||||||
|
|
||||||
In addition to that, about six months ago, one of the most popular Telegram bot has been rewritten
|
In addition to that, about six months ago, one of the most popular Telegram bot has been rewritten from scratch
|
||||||
:doc:`using Pyrogram <powered-by>` and is serving more than 200,000 Monthly Active Users since
|
:doc:`using Pyrogram <powered-by>` and is serving more than 200,000 Monthly Active Users since
|
||||||
then, uninterruptedly and without any need for restarting it.
|
then, uninterruptedly and without any need for restarting it.
|
||||||
|
|
||||||
@ -102,9 +105,11 @@ one: ``CAADBAADyg4AAvLQYAEYD4F7vcZ43AI``.
|
|||||||
Can I use Bot API's file_ids in Pyrogram?
|
Can I use Bot API's file_ids in Pyrogram?
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
Definitely! All file ids you might have taken from the Bot API are 100% compatible and re-usable in Pyrogram...
|
:strike:`Definitely! All file ids you might have taken from the Bot API are 100% compatible and re-usable in Pyrogram.`
|
||||||
|
|
||||||
...at least for now.
|
Starting from :doc:`Pyrogram v0.14.1 (Layer 100) <releases/v0.14.1>`, the file_id format of all photo-like objects has
|
||||||
|
changed. Types affected are: :obj:`~pyrogram.Thumbnail`, :obj:`~pyrogram.ChatPhoto` and :obj:`~pyrogram.Photo`. Any
|
||||||
|
other file id remains compatible with the Bot API.
|
||||||
|
|
||||||
Telegram is slowly changing some server's internals and it's doing it in such a way that file ids are going to break
|
Telegram is slowly changing some server's internals and it's doing it in such a way that file ids are going to break
|
||||||
inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus
|
inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus
|
||||||
@ -129,8 +134,8 @@ If you -- even accidentally -- fail to do so, all the previous session copies wi
|
|||||||
and eventually the server will start throwing the error ``[406 AUTH_KEY_DUPLICATED]``, inviting you to login again.
|
and eventually the server will start throwing the error ``[406 AUTH_KEY_DUPLICATED]``, inviting you to login again.
|
||||||
|
|
||||||
Why is that so? Because the server has recognized two identical sessions are running in two different locations, and
|
Why is that so? Because the server has recognized two identical sessions are running in two different locations, and
|
||||||
concludes it could possibly be due to a cloned/stolen device. Having the session ended in such occasions will protect
|
concludes it could possibly be due to a cloned/stolen device. Having the session terminated in such occasions will
|
||||||
the user's privacy.
|
protect the user's privacy.
|
||||||
|
|
||||||
So, the only correct way to run multiple clients on the same account is authorizing your account (either user or bot)
|
So, the only correct way to run multiple clients on the same account is authorizing your account (either user or bot)
|
||||||
from the beginning every time, and use one separate session for each parallel client you are going to use.
|
from the beginning every time, and use one separate session for each parallel client you are going to use.
|
||||||
@ -139,7 +144,8 @@ I started a client and nothing happens!
|
|||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
||||||
partially or totally blocked in those countries.
|
partially or totally blocked in those countries. More information about this block can be found at
|
||||||
|
`Wikipedia <https://en.wikipedia.org/wiki/Blocking_Telegram_in_Russia>`_.
|
||||||
|
|
||||||
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
||||||
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
||||||
@ -156,20 +162,20 @@ fails or not.
|
|||||||
What are the IP addresses of Telegram Data Centers?
|
What are the IP addresses of Telegram Data Centers?
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
The Telegram cloud is currently composed by a decentralized, multi-DC infrastructure (each of which can work
|
The Telegram cloud is currently composed by a decentralized, multi-DC infrastructure (currently 5 DCs, each of which can
|
||||||
independently) spread in 5 different locations. However, some of the less busy DCs have been lately dismissed and their
|
work independently) spread in different locations worldwide. However, some of the less busy DCs have been lately
|
||||||
IP addresses are now kept as aliases.
|
dismissed and their IP addresses are now kept as aliases to the nearest one.
|
||||||
|
|
||||||
.. csv-table:: Production Environment
|
.. csv-table:: Production Environment
|
||||||
:header: ID, Location, IPv4, IPv6
|
:header: ID, Location, IPv4, IPv6
|
||||||
:widths: auto
|
:widths: auto
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
DC1, "MIA, Miami FL, USA", ``149.154.175.50``, ``2001:b28:f23d:f001::a``
|
DC1, "MIA, Miami FL, USA", ``149.154.175.53``, ``2001:b28:f23d:f001::a``
|
||||||
DC2, "AMS, Amsterdam, NL", ``149.154.167.51``, ``2001:67c:4e8:f002::a``
|
DC2, "AMS, Amsterdam, NL", ``149.154.167.51``, ``2001:67c:4e8:f002::a``
|
||||||
DC3*, "MIA, Miami FL, USA", ``149.154.175.100``, ``2001:b28:f23d:f003::a``
|
DC3*, "MIA, Miami FL, USA", ``149.154.175.100``, ``2001:b28:f23d:f003::a``
|
||||||
DC4, "AMS, Amsterdam, NL", ``149.154.167.91``, ``2001:67c:4e8:f004::a``
|
DC4, "AMS, Amsterdam, NL", ``149.154.167.91``, ``2001:67c:4e8:f004::a``
|
||||||
DC5, "SIN, Singapore, SG", ``91.108.56.149``, ``2001:b28:f23f:f005::a``
|
DC5, "SIN, Singapore, SG", ``91.108.56.130``, ``2001:b28:f23f:f005::a``
|
||||||
|
|
||||||
.. csv-table:: Test Environment
|
.. csv-table:: Test Environment
|
||||||
:header: ID, Location, IPv4, IPv6
|
:header: ID, Location, IPv4, IPv6
|
||||||
@ -180,9 +186,11 @@ IP addresses are now kept as aliases.
|
|||||||
DC2, "AMS, Amsterdam, NL", ``149.154.167.40``, ``2001:67c:4e8:f002::e``
|
DC2, "AMS, Amsterdam, NL", ``149.154.167.40``, ``2001:67c:4e8:f002::e``
|
||||||
DC3*, "MIA, Miami FL, USA", ``149.154.175.117``, ``2001:b28:f23d:f003::e``
|
DC3*, "MIA, Miami FL, USA", ``149.154.175.117``, ``2001:b28:f23d:f003::e``
|
||||||
|
|
||||||
|
.. centered:: More info about the Test Environment can be found :doc:`here <topics/test-servers>`.
|
||||||
|
|
||||||
***** Alias DC
|
***** Alias DC
|
||||||
|
|
||||||
More info about the Test Environment can be found :doc:`here <topics/test-servers>`.
|
Thanks to `@FrayxRulez <https://t.me/tgbetachat/104921>`_ for telling about alias DCs.
|
||||||
|
|
||||||
I want to migrate my account from DCX to DCY.
|
I want to migrate my account from DCX to DCY.
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
@ -200,6 +208,36 @@ mechanism is also `confirmed <https://twitter.com/telegram/status/42713144665519
|
|||||||
it's currently not possible to have your account migrated, in any way, simply because the feature was once planned but
|
it's currently not possible to have your account migrated, in any way, simply because the feature was once planned but
|
||||||
not yet implemented.
|
not yet implemented.
|
||||||
|
|
||||||
|
Thanks to `@gabriel <https://t.me/AnotherGroup/217699>`_ for confirming the feature was not implemented yet.
|
||||||
|
|
||||||
|
Why is my client reacting slowly in supergroups?
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
This issue affects only some supergroups or only some members within the same supergroup. Mostly, it affects supergroups
|
||||||
|
whose creator's account (and thus the supergroup itself) lives inside a **different DC**, far away from yours, but could
|
||||||
|
also depend on where a member is connecting from.
|
||||||
|
|
||||||
|
Because of how Telegram works internally, every single message you receive from and send to other members must pass
|
||||||
|
through the creator's DC, and in the worst case where you, the creator and another member all belong to three different
|
||||||
|
DCs, the other member messages have to go through from its DC to the creator's DC and finally to your DC. This process
|
||||||
|
will inevitably take its time.
|
||||||
|
|
||||||
|
To confirm this theory and see it by yourself, you can test in a supergroup where you are sure all parties live
|
||||||
|
inside the same DC. In this case the responses will be faster.
|
||||||
|
|
||||||
|
Another reason that makes responses come slowly is that messages are **dispatched by priority**. Depending on the kind
|
||||||
|
of member, some users receive messages faster than others and for big and busy supergroups the delay might become
|
||||||
|
noticeable, especially if you are among the lower end of the priority list:
|
||||||
|
|
||||||
|
1. Creator.
|
||||||
|
2. Administrators.
|
||||||
|
3. Bots.
|
||||||
|
4. Mentioned users.
|
||||||
|
5. Recent online users.
|
||||||
|
6. Everyone else.
|
||||||
|
|
||||||
|
Thanks to `@Manuel15 <https://t.me/PyrogramChat/76990>`_ for the priority list.
|
||||||
|
|
||||||
I keep getting PEER_ID_INVALID error!
|
I keep getting PEER_ID_INVALID error!
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
@ -207,9 +245,13 @@ The error in question is ``[400 PEER_ID_INVALID]``, and could mean several thing
|
|||||||
|
|
||||||
- The chat id you tried to use is simply wrong, double check it.
|
- The chat id you tried to use is simply wrong, double check it.
|
||||||
- The chat id refers to a group or channel you are not a member of.
|
- The chat id refers to a group or channel you are not a member of.
|
||||||
- The chat id refers to a user you have't seen yet (from contacts, groups in common, forwarded messages or private
|
|
||||||
chats).
|
|
||||||
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
||||||
|
- The chat id refers to a user your current session haven't met yet.
|
||||||
|
|
||||||
|
About the last point: in order for you to meet a user and thus communicate with them, you should ask yourself how to
|
||||||
|
contact people using official apps. The answer is the same for Pyrogram too and involves normal usages such as searching
|
||||||
|
for usernames, meeting them in a common group, have their phone contacts saved or getting a message mentioning them,
|
||||||
|
either a forward or a mention in the message text.
|
||||||
|
|
||||||
UnicodeEncodeError: '<encoding>' codec can't encode …
|
UnicodeEncodeError: '<encoding>' codec can't encode …
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
@ -217,7 +259,15 @@ UnicodeEncodeError: '<encoding>' codec can't encode …
|
|||||||
Where ``<encoding>`` might be *ascii*, *cp932*, *charmap* or anything else other than **utf-8**. This error usually
|
Where ``<encoding>`` might be *ascii*, *cp932*, *charmap* or anything else other than **utf-8**. This error usually
|
||||||
shows up when you try to print something and has very little to do with Pyrogram itself as it is strictly related to
|
shows up when you try to print something and has very little to do with Pyrogram itself as it is strictly related to
|
||||||
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
|
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
|
||||||
better one.
|
better terminal altogether.
|
||||||
|
|
||||||
|
Uploading with URLs gives error WEBPAGE_CURL_FAILED
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
When uploading media files using an URL, the server automatically tries to download the media and uploads it to the
|
||||||
|
Telegram cloud. This error usually happens in case the provided URL is not publicly accessible by Telegram itself or the
|
||||||
|
media exceeds 20 MB in size. In such cases, your only option is to download the media yourself and upload from your
|
||||||
|
local machine.
|
||||||
|
|
||||||
My verification code expires immediately!
|
My verification code expires immediately!
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
@ -243,7 +293,7 @@ Having said that, here's a list of what Telegram definitely doesn't like:
|
|||||||
- Spam, sending unsolicited messages or adding people to unwanted groups and channels.
|
- Spam, sending unsolicited messages or adding people to unwanted groups and channels.
|
||||||
- Virtual/VoIP and cheap real numbers, because they are relatively easy to get and likely used for spam/flood.
|
- Virtual/VoIP and cheap real numbers, because they are relatively easy to get and likely used for spam/flood.
|
||||||
|
|
||||||
And here's a good explanation of how, probably, the system works:
|
And thanks to `@koteeq <https://t.me/koteeq>`_, here's a good explanation of how, probably, the system works:
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
@ -252,8 +302,7 @@ And here's a good explanation of how, probably, the system works:
|
|||||||
data-telegram-post="PyrogramChat/69424"
|
data-telegram-post="PyrogramChat/69424"
|
||||||
data-width="100%">
|
data-width="100%">
|
||||||
</script>
|
</script>
|
||||||
|
<br><br>
|
||||||
.. centered:: Join the discussion at `@Pyrogram <https://t.me/pyrogram>`_
|
|
||||||
|
|
||||||
However, you might be right, and your account was deactivated/limited without any good reason. This could happen because
|
However, you might be right, and your account was deactivated/limited without any good reason. This could happen because
|
||||||
of mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
|
of mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
|
||||||
|
@ -29,7 +29,7 @@ Terms
|
|||||||
achieve high quality and availability for services.
|
achieve high quality and availability for services.
|
||||||
|
|
||||||
RPC
|
RPC
|
||||||
Acronym for Remote Procedure call, that is, a function which gets executed at some remote place (i.e. Telegram
|
Acronym for Remote Procedure Call, that is, a function which gets executed at some remote place (i.e. Telegram
|
||||||
server) and not in your local machine.
|
server) and not in your local machine.
|
||||||
|
|
||||||
RPCError
|
RPCError
|
||||||
@ -58,7 +58,7 @@ Terms
|
|||||||
Pyrogram --- to automate some behaviours, like sending messages or reacting to text commands or any other event.
|
Pyrogram --- to automate some behaviours, like sending messages or reacting to text commands or any other event.
|
||||||
|
|
||||||
Session
|
Session
|
||||||
Also known as *login session*, is a strictly personal piece of information created and held by both parties
|
Also known as *login session*, is a strictly personal piece of data created and held by both parties
|
||||||
(client and server) which is used to grant permission into a single account without having to start a new
|
(client and server) which is used to grant permission into a single account without having to start a new
|
||||||
authorization process from scratch.
|
authorization process from scratch.
|
||||||
|
|
||||||
|
@ -1,6 +1,78 @@
|
|||||||
Welcome to Pyrogram
|
Welcome to Pyrogram
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: Introduction
|
||||||
|
|
||||||
|
intro/quickstart
|
||||||
|
intro/install
|
||||||
|
intro/setup
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: Getting Started
|
||||||
|
|
||||||
|
start/auth
|
||||||
|
start/invoking
|
||||||
|
start/updates
|
||||||
|
start/errors
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: API Reference
|
||||||
|
|
||||||
|
api/client
|
||||||
|
api/methods/index
|
||||||
|
api/types/index
|
||||||
|
api/bound-methods/index
|
||||||
|
api/handlers
|
||||||
|
api/decorators
|
||||||
|
api/errors
|
||||||
|
api/filters
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: Topic Guides
|
||||||
|
|
||||||
|
topics/use-filters
|
||||||
|
topics/create-filters
|
||||||
|
topics/more-on-updates
|
||||||
|
topics/config-file
|
||||||
|
topics/smart-plugins
|
||||||
|
topics/auto-auth
|
||||||
|
topics/session-settings
|
||||||
|
topics/tgcrypto
|
||||||
|
topics/storage-engines
|
||||||
|
topics/text-formatting
|
||||||
|
topics/serializing
|
||||||
|
topics/proxy
|
||||||
|
topics/scheduling
|
||||||
|
topics/bots-interaction
|
||||||
|
topics/mtproto-vs-botapi
|
||||||
|
topics/debugging
|
||||||
|
topics/test-servers
|
||||||
|
topics/advanced-usage
|
||||||
|
topics/voice-calls
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: Meta
|
||||||
|
|
||||||
|
faq
|
||||||
|
glossary
|
||||||
|
powered-by
|
||||||
|
support-pyrogram
|
||||||
|
license
|
||||||
|
releases/index
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
:caption: Telegram API
|
||||||
|
|
||||||
|
telegram/functions/index
|
||||||
|
telegram/types/index
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
@ -35,7 +107,7 @@ Welcome to Pyrogram
|
|||||||
|
|
||||||
@app.on_message(Filters.private)
|
@app.on_message(Filters.private)
|
||||||
def hello(client, message):
|
def hello(client, message):
|
||||||
message.reply("Hello {}".format(message.from_user.first_name))
|
message.reply_text("Hello {}".format(message.from_user.first_name))
|
||||||
|
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
@ -54,7 +126,7 @@ order using the :guilabel:`Next` button at the end of each page. Here below you
|
|||||||
relevant pages for a quick access.
|
relevant pages for a quick access.
|
||||||
|
|
||||||
First Steps
|
First Steps
|
||||||
-----------
|
^^^^^^^^^^^
|
||||||
|
|
||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
@ -65,18 +137,18 @@ First Steps
|
|||||||
- :doc:`Error Handling <start/errors>`: How to handle API errors correctly.
|
- :doc:`Error Handling <start/errors>`: How to handle API errors correctly.
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
|
|
||||||
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
|
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
|
||||||
- :doc:`Available Methods <api/methods>`: List of available high-level methods.
|
- :doc:`Available Methods <api/methods/index>`: List of available high-level methods.
|
||||||
- :doc:`Available Types <api/types>`: List of available high-level types.
|
- :doc:`Available Types <api/types/index>`: List of available high-level types.
|
||||||
- :doc:`Bound Methods <api/bound-methods>`: List of convenient bound methods.
|
- :doc:`Bound Methods <api/bound-methods/index>`: List of convenient bound methods.
|
||||||
|
|
||||||
Meta
|
Meta
|
||||||
----
|
^^^^
|
||||||
|
|
||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
@ -88,74 +160,4 @@ Meta
|
|||||||
- :doc:`About the License <license>`: Information about the Project license.
|
- :doc:`About the License <license>`: Information about the Project license.
|
||||||
- :doc:`Release Notes <releases/index>`: Release notes for Pyrogram releases.
|
- :doc:`Release Notes <releases/index>`: Release notes for Pyrogram releases.
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: Introduction
|
|
||||||
|
|
||||||
intro/quickstart
|
|
||||||
intro/install
|
|
||||||
intro/setup
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: Getting Started
|
|
||||||
|
|
||||||
start/auth
|
|
||||||
start/invoking
|
|
||||||
start/updates
|
|
||||||
start/errors
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: API Reference
|
|
||||||
|
|
||||||
api/client
|
|
||||||
api/methods
|
|
||||||
api/types
|
|
||||||
api/bound-methods
|
|
||||||
api/handlers
|
|
||||||
api/decorators
|
|
||||||
api/filters
|
|
||||||
api/errors
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: Topic Guides
|
|
||||||
|
|
||||||
topics/use-filters
|
|
||||||
topics/create-filters
|
|
||||||
topics/more-on-updates
|
|
||||||
topics/config-file
|
|
||||||
topics/smart-plugins
|
|
||||||
topics/auto-auth
|
|
||||||
topics/session-settings
|
|
||||||
topics/tgcrypto
|
|
||||||
topics/text-formatting
|
|
||||||
topics/serialize
|
|
||||||
topics/proxy
|
|
||||||
topics/bots-interaction
|
|
||||||
topics/mtproto-vs-botapi
|
|
||||||
topics/debugging
|
|
||||||
topics/test-servers
|
|
||||||
topics/advanced-usage
|
|
||||||
topics/voice-calls
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: Meta
|
|
||||||
|
|
||||||
faq
|
|
||||||
glossary
|
|
||||||
powered-by
|
|
||||||
support-pyrogram
|
|
||||||
license
|
|
||||||
releases/index
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
:caption: Telegram API
|
|
||||||
|
|
||||||
telegram/functions/index
|
|
||||||
telegram/types/index
|
|
||||||
|
|
||||||
Last updated on |today|
|
Last updated on |today|
|
@ -47,7 +47,7 @@ Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging
|
|||||||
where asyncio shines the most by providing extra performance and efficiency while running on a single OS-level thread
|
where asyncio shines the most by providing extra performance and efficiency while running on a single OS-level thread
|
||||||
only.
|
only.
|
||||||
|
|
||||||
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3+ required).
|
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3 or higher is required).
|
||||||
Use this command to install (note "asyncio.zip" in the link):
|
Use this command to install (note "asyncio.zip" in the link):
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
@ -46,4 +46,4 @@ In the next few pages of the introduction, we'll take a much more in-depth look
|
|||||||
Feeling eager to continue? You can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back later to
|
Feeling eager to continue? You can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back later to
|
||||||
learn some more details.
|
learn some more details.
|
||||||
|
|
||||||
.. _community: //t.me/Pyrogram
|
.. _community: https://t.me/Pyrogram
|
||||||
|
@ -29,9 +29,9 @@ Configuration
|
|||||||
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project.
|
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project.
|
||||||
There are two ways to do so, and you can choose what fits better for you:
|
There are two ways to do so, and you can choose what fits better for you:
|
||||||
|
|
||||||
- First option (recommended): create a new ``config.ini`` file at the root of your working directory, copy-paste the
|
- First option (recommended): create a new ``config.ini`` file next to your main script, copy-paste the following and
|
||||||
following and replace the **api_id** and **api_hash** values with your own. This is the preferred method because
|
replace the **api_id** and **api_hash** values with your own. This is the preferred method because allows you to
|
||||||
allows you to keep your credentials out of your code without having to deal with how to load them:
|
keep your credentials out of your code without having to deal with how to load them:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ About the License
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
|
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
|
||||||
:align: right
|
:align: left
|
||||||
|
|
||||||
Pyrogram is free software and is currently licensed under the terms of the
|
Pyrogram is free software and is currently licensed under the terms of the
|
||||||
`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it
|
`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it
|
||||||
|
@ -28,7 +28,7 @@ Error Categories
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
The ``RPCError`` packs together all the possible errors Telegram could raise, but to make things tidier, Pyrogram
|
The ``RPCError`` packs together all the possible errors Telegram could raise, but to make things tidier, Pyrogram
|
||||||
provides categories of errors, which are named after the common HTTP errors and subclass-ed from the RPCError:
|
provides categories of errors, which are named after the common HTTP errors and are subclass-ed from the RPCError:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -71,14 +71,22 @@ RPCError, thus building a class of error hierarchy such as this:
|
|||||||
Unknown Errors
|
Unknown Errors
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
In case Pyrogram does not know anything yet about a specific error, it raises a special ``520 - UnknownError`` exception
|
In case Pyrogram does not know anything about a specific error yet, it raises a generic error from its known category,
|
||||||
and logs it in the ``unknown_errors.txt`` file. Users are invited to report these unknown errors.
|
for example, an unknown error with error code ``400``, will be raised as a ``BadRequest``. This way you can catch the
|
||||||
|
whole category of errors and be sure to also handle these unknown errors.
|
||||||
|
|
||||||
|
In case a whole class of errors is unknown (that is, an error code that is unknown), Pyrogram will raise a special
|
||||||
|
``520 UnknownError`` exception.
|
||||||
|
|
||||||
|
In both cases, Pyrogram will log them in the ``unknown_errors.txt`` file. Users are invited to report
|
||||||
|
these unknown errors in the `discussion group <https://t.me/pyrogram>`_.
|
||||||
|
|
||||||
Errors with Values
|
Errors with Values
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Exception objects may also contain some informative values. For example, ``FloodWait`` holds the amount of seconds you
|
Exception objects may also contain some informative values. For example, ``FloodWait`` holds the amount of seconds you
|
||||||
have to wait before you can try again. The value is always stored in the ``x`` field of the returned exception object:
|
have to wait before you can try again, some other errors contain the DC number on which the request must be repeated on.
|
||||||
|
The value is stored in the ``x`` attribute of the exception object:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -88,4 +96,4 @@ have to wait before you can try again. The value is always stored in the ``x`` f
|
|||||||
try:
|
try:
|
||||||
...
|
...
|
||||||
except FloodWait as e:
|
except FloodWait as e:
|
||||||
time.sleep(e.x) # Wait before trying again
|
time.sleep(e.x) # Wait "x" seconds before continuing
|
||||||
|
@ -45,7 +45,9 @@ arrives:
|
|||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
#. Let's examine these four new pieces. First one: a callback function we defined which accepts two arguments -
|
Let's examine these four new pieces.
|
||||||
|
|
||||||
|
#. A callback function we defined which accepts two arguments -
|
||||||
*(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
|
*(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
|
||||||
call that function by passing the client instance and the new message instance as argument.
|
call that function by passing the client instance and the new message instance as argument.
|
||||||
|
|
||||||
@ -54,14 +56,14 @@ arrives:
|
|||||||
def my_function(client, message):
|
def my_function(client, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
#. Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must
|
#. The :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only handle
|
||||||
only handle updates that are in form of a :class:`~pyrogram.Message`:
|
updates that are in form of a :class:`~pyrogram.Message`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
my_handler = MessageHandler(my_function)
|
my_handler = MessageHandler(my_function)
|
||||||
|
|
||||||
#. Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
|
#. The method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
|
||||||
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase
|
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase
|
||||||
begins.
|
begins.
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ arrives:
|
|||||||
|
|
||||||
app.add_handler(my_handler)
|
app.add_handler(my_handler)
|
||||||
|
|
||||||
#. Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and
|
#. The :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and
|
||||||
a special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the
|
a special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the
|
||||||
client will be automatically stopped after that.
|
client will be automatically stopped after that.
|
||||||
|
|
||||||
@ -96,14 +98,3 @@ to do so is by decorating your callback function with the :meth:`~pyrogram.Clien
|
|||||||
|
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of
|
|
||||||
``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example
|
|
||||||
above).
|
|
||||||
|
|
||||||
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
|
|
||||||
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
|
|
||||||
tuple, accessed by bracket notation *[0]*.
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
Advanced Usage
|
Advanced Usage
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods>` and facade
|
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods/index>` and facade
|
||||||
:doc:`types <../api/types>`, exists to provide a much easier interface to the undocumented and often confusing Telegram
|
:doc:`types <../api/types/index>`, exists to provide a much easier interface to the undocumented and often confusing
|
||||||
API.
|
Telegram API.
|
||||||
|
|
||||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
||||||
Telegram API with its functions and types.
|
Telegram API with its functions and types.
|
||||||
@ -23,21 +23,21 @@ some pitfalls to take into consideration when working with the raw API.
|
|||||||
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
||||||
|
|
||||||
Nothing stops you from using the raw functions only, but they are rather complex and
|
Nothing stops you from using the raw functions only, but they are rather complex and
|
||||||
:doc:`plenty of them <../api/methods>` are already re-implemented by providing a much simpler and cleaner interface
|
:doc:`plenty of them <../api/methods/index>` are already re-implemented by providing a much simpler and cleaner
|
||||||
which is very similar to the Bot API (yet much more powerful).
|
interface which is very similar to the Bot API (yet much more powerful).
|
||||||
|
|
||||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||||
|
|
||||||
Invoking Functions
|
Invoking Functions
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Unlike the :doc:`methods <../api/methods>` found in Pyrogram's API, which can be called in the usual simple way,
|
Unlike the :doc:`methods <../api/methods/index>` found in Pyrogram's API, which can be called in the usual simple way,
|
||||||
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
|
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
|
||||||
|
|
||||||
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>` live in their
|
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>`
|
||||||
respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python
|
live in their respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist
|
||||||
classes, meaning you need to create an instance of each every time you need them and fill them in with the correct
|
as Python classes, meaning you need to create an instance of each every time you need them and fill them in with the
|
||||||
values using named arguments.
|
correct values using named arguments.
|
||||||
|
|
||||||
Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the
|
Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the
|
||||||
Client class and pass the function object you created.
|
Client class and pass the function object you created.
|
||||||
|
@ -24,7 +24,7 @@ button:
|
|||||||
|
|
||||||
app.send_message(
|
app.send_message(
|
||||||
"username", # Change this to your username or id
|
"username", # Change this to your username or id
|
||||||
"Pyrogram's custom filter test",
|
"Pyrogram custom filter test",
|
||||||
reply_markup=InlineKeyboardMarkup(
|
reply_markup=InlineKeyboardMarkup(
|
||||||
[[InlineKeyboardButton("Press me", "pyrogram")]]
|
[[InlineKeyboardButton("Press me", "pyrogram")]]
|
||||||
)
|
)
|
||||||
@ -33,61 +33,54 @@ button:
|
|||||||
Basic Filters
|
Basic Filters
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`.
|
For this basic filter we will be using only the first parameter of :meth:`~pyrogram.Filters.create`.
|
||||||
|
|
||||||
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
||||||
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
containing "pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
||||||
equals to ``"Pyrogram"``.
|
equals to ``"pyrogram"``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
static_data = Filters.create(
|
static_data_filter = Filters.create(lambda _, query: query.data == "pyrogram")
|
||||||
name="StaticdData",
|
|
||||||
func=lambda flt, query: query.data == "Pyrogram"
|
|
||||||
)
|
|
||||||
|
|
||||||
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
|
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
|
||||||
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
|
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter scope:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def func(flt, query):
|
def func(_, query):
|
||||||
return query.data == "Pyrogram"
|
return query.data == "pyrogram"
|
||||||
|
|
||||||
static_data = Filters.create(
|
static_data_filter = Filters.create(func)
|
||||||
name="StaticData",
|
|
||||||
func=func
|
|
||||||
)
|
|
||||||
|
|
||||||
The filter usage remains the same:
|
The filter usage remains the same:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@app.on_callback_query(static_data)
|
@app.on_callback_query(static_data_filter)
|
||||||
def pyrogram_data(_, query):
|
def pyrogram_data(_, query):
|
||||||
query.answer("it works!")
|
query.answer("it works!")
|
||||||
|
|
||||||
Filters with Arguments
|
Filters with Arguments
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
|
A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time.
|
||||||
A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`.
|
A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.Filters.create` method.
|
||||||
|
|
||||||
This is how a dynamic custom filter looks like:
|
This is how a dynamic custom filter looks like:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def dynamic_data(data):
|
def dynamic_data_filter(data):
|
||||||
return Filters.create(
|
return Filters.create(
|
||||||
name="DynamicData",
|
lambda flt, query: flt.data == query.data,
|
||||||
func=lambda flt, query: flt.data == query.data,
|
data=data # "data" kwarg is accessed with "flt.data" above
|
||||||
data=data # "data" kwarg is accessed with "flt.data"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
And its usage:
|
And its usage:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@app.on_callback_query(dynamic_data("Pyrogram"))
|
@app.on_callback_query(dynamic_data_filter("pyrogram"))
|
||||||
def pyrogram_data(_, query):
|
def pyrogram_data(_, query):
|
||||||
query.answer("it works!")
|
query.answer("it works!")
|
||||||
|
87
docs/source/topics/scheduling.rst
Normal file
87
docs/source/topics/scheduling.rst
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
Scheduling Tasks
|
||||||
|
================
|
||||||
|
|
||||||
|
Scheduling tasks means executing one or more functions periodically at pre-defined intervals or after a delay. This is
|
||||||
|
useful, for example, to send recurring messages to specific chats or users.
|
||||||
|
|
||||||
|
Since there's no built-in task scheduler in Pyrogram, this page will only show examples on how to integrate Pyrogram
|
||||||
|
with the main Python schedule libraries such as ``schedule`` and ``apscheduler``. For more detailed information, you can
|
||||||
|
visit and learn from each library documentation.
|
||||||
|
|
||||||
|
Using ``schedule``
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Install with ``pip3 install schedule``
|
||||||
|
- Documentation: https://schedule.readthedocs.io
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
import schedule
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
def job():
|
||||||
|
app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
schedule.every(3).seconds.do(job)
|
||||||
|
|
||||||
|
with app:
|
||||||
|
while True:
|
||||||
|
schedule.run_pending()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Using ``apscheduler``
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Install with ``pip3 install apscheduler``
|
||||||
|
- Documentation: https://apscheduler.readthedocs.io
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
def job():
|
||||||
|
app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
scheduler = BackgroundScheduler()
|
||||||
|
scheduler.add_job(job, "interval", seconds=3)
|
||||||
|
|
||||||
|
scheduler.start()
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
``apscheduler`` does also support async code, here's an example with
|
||||||
|
`Pyrogram Asyncio <https://docs.pyrogram.org/intro/install.html#asynchronous>`_:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
async def job():
|
||||||
|
await app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
scheduler = AsyncIOScheduler()
|
||||||
|
scheduler.add_job(job, "interval", seconds=3)
|
||||||
|
|
||||||
|
scheduler.start()
|
||||||
|
app.run()
|
||||||
|
|
@ -9,7 +9,7 @@ For Humans - str(obj)
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from
|
If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from
|
||||||
:doc:`Pyrogram types <../api/types>`, :doc:`raw functions <../telegram/functions/index>` and
|
:doc:`Pyrogram types <../api/types/index>`, :doc:`raw functions <../telegram/functions/index>` and
|
||||||
:doc:`raw types <../telegram/types/index>` -- you can use use ``str(obj)``.
|
:doc:`raw types <../telegram/types/index>` -- you can use use ``str(obj)``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
@ -316,9 +316,9 @@ attribute. Here's an example:
|
|||||||
Unloading
|
Unloading
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
In order to unload a plugin, all you need to do is obtain a reference to it by importing the relevant module and call
|
||||||
relevant module and call :meth:`~pyrogram.Client.remove_handler` Client's method with your function
|
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* special attribute preceded by the
|
||||||
name preceded by the star ``*`` operator as argument. Example:
|
star ``*`` operator as argument. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
|
|
||||||
@ -328,14 +328,14 @@ name preceded by the star ``*`` operator as argument. Example:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
app.remove_handler(*echo)
|
app.remove_handler(*echo.handler)
|
||||||
|
|
||||||
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
||||||
exactly what is needed. The same could have been achieved with:
|
exactly what is needed. The same could have been achieved with:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
handler, group = echo
|
handler, group = echo.handler
|
||||||
app.remove_handler(handler, group)
|
app.remove_handler(handler, group)
|
||||||
|
|
||||||
Loading
|
Loading
|
||||||
@ -352,4 +352,4 @@ using :meth:`~pyrogram.Client.add_handler` instead. Example:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
app.add_handler(*echo)
|
app.add_handler(*echo.handler)
|
99
docs/source/topics/storage-engines.rst
Normal file
99
docs/source/topics/storage-engines.rst
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
Storage Engines
|
||||||
|
===============
|
||||||
|
|
||||||
|
Every time you login to Telegram, some personal piece of data are created and held by both parties (the client, Pyrogram
|
||||||
|
and the server, Telegram). This session data is uniquely bound to your own account, indefinitely (until you logout or
|
||||||
|
decide to manually terminate it) and is used to authorize a client to execute API calls on behalf of your identity.
|
||||||
|
|
||||||
|
Persisting Sessions
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
In order to make a client reconnect successfully between restarts, that is, without having to start a new
|
||||||
|
authorization process from scratch each time, Pyrogram needs to store the generated session data somewhere.
|
||||||
|
|
||||||
|
Other useful data being stored is peers' cache. In short, peers are all those entities you can chat with, such as users
|
||||||
|
or bots, basic groups, but also channels and supergroups. Because of how Telegram works, a unique pair of **id** and
|
||||||
|
**access_hash** is needed to contact a peer. This, plus other useful info such as the peer type, is what is stored
|
||||||
|
inside a session storage.
|
||||||
|
|
||||||
|
So, if you ever wondered how is Pyrogram able to contact peers just by asking for their ids, it's because of this very
|
||||||
|
reason: the peer *id* is looked up in the internal database and the available *access_hash* is retrieved, which is then
|
||||||
|
used to correctly invoke API methods.
|
||||||
|
|
||||||
|
Different Storage Engines
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Let's now talk about how Pyrogram actually stores all the relevant data. Pyrogram offers two different types of storage
|
||||||
|
engines: a **File Storage** and a **Memory Storage**. These engines are well integrated in the library and require a
|
||||||
|
minimal effort to set up. Here's how they work:
|
||||||
|
|
||||||
|
File Storage
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This is the most common storage engine. It is implemented by using **SQLite**, which will store the session and peers
|
||||||
|
details. The database will be saved to disk as a single portable file and is designed to efficiently store and retrieve
|
||||||
|
peers whenever they are needed.
|
||||||
|
|
||||||
|
To use this type of engine, simply pass any name of your choice to the ``session_name`` parameter of the
|
||||||
|
:obj:`~pyrogram.Client` constructor, as usual:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
with Client("my_account") as app:
|
||||||
|
print(app.get_me())
|
||||||
|
|
||||||
|
Once you successfully log in (either with a user or a bot identity), a session file will be created and saved to disk as
|
||||||
|
``my_account.session``. Any subsequent client restart will make Pyrogram search for a file named that way and the
|
||||||
|
session database will be automatically loaded.
|
||||||
|
|
||||||
|
Memory Storage
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
In case you don't want to have any session file saved to disk, you can use an in-memory storage by passing the special
|
||||||
|
session name "**:memory:**" to the ``session_name`` parameter of the :obj:`~pyrogram.Client` constructor:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
with Client(":memory:") as app:
|
||||||
|
print(app.get_me())
|
||||||
|
|
||||||
|
This storage engine is still backed by SQLite, but the database exists purely in memory. This means that, once you stop a
|
||||||
|
client, the entire database is discarded and the session details used for logging in again will be lost forever.
|
||||||
|
|
||||||
|
Session Strings
|
||||||
|
---------------
|
||||||
|
|
||||||
|
In case you want to use an in-memory storage, but also want to keep access to the session you created, call
|
||||||
|
:meth:`~pyrogram.Client.export_session_string` anytime before stopping the client...
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
with Client(":memory:") as app:
|
||||||
|
print(app.export_session_string())
|
||||||
|
|
||||||
|
...and save the resulting (quite long) string somewhere. You can use this string as session name the next time you want
|
||||||
|
to login using the same session; the storage used will still be completely in-memory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
session_string = "...ZnUIFD8jsjXTb8g_vpxx48k1zkov9sapD-tzjz-S4WZv70M..."
|
||||||
|
|
||||||
|
with Client(session_string) as app:
|
||||||
|
print(app.get_me())
|
||||||
|
|
||||||
|
Session strings are useful when you want to run authorized Pyrogram clients on platforms like
|
||||||
|
`Heroku <https://www.heroku.com/>`_, where their ephemeral filesystems makes it much harder for a file-based storage
|
||||||
|
engine to properly work as intended.
|
||||||
|
|
||||||
|
But, why is the session string so long? Can't it be shorter? No, it can't. The session string already packs the bare
|
||||||
|
minimum data Pyrogram needs to successfully reconnect to an authorized session, and the 2048-bits auth key is the major
|
||||||
|
contributor to the overall length. Needless to say that this string, as well as any other session storage, represent
|
||||||
|
strictly personal data. Keep them safe.
|
@ -1,40 +1,99 @@
|
|||||||
Text Formatting
|
Text Formatting
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Pyrogram, just like the `Telegram Bot API`_, natively supports basic Markdown and HTML formatting styles for text
|
.. role:: strike
|
||||||
messages and media captions.
|
:class: strike
|
||||||
|
|
||||||
Markdown style uses the same syntax as Telegram Desktop's and is enabled by default.
|
.. role:: underline
|
||||||
|
:class: underline
|
||||||
|
|
||||||
Beside bold, italic, and pre-formatted code, **Pyrogram does also support inline URLs and inline mentions of users**.
|
.. role:: bold-underline
|
||||||
|
:class: bold-underline
|
||||||
|
|
||||||
|
.. role:: strike-italic
|
||||||
|
:class: strike-italic
|
||||||
|
|
||||||
|
Pyrogram uses a custom Markdown dialect for text formatting which adds some unique features that make writing styled
|
||||||
|
texts easier in both Markdown and HTML. You can send sophisticated text messages and media captions using a great
|
||||||
|
variety of decorations that can also be nested in order to combine multiple styles together.
|
||||||
|
|
||||||
|
Basic Styles
|
||||||
|
------------
|
||||||
|
|
||||||
|
When formatting your messages, you can choose between Markdown-style, HTML-style or both (default). The following is a
|
||||||
|
list of the basic styles currently supported by Pyrogram.
|
||||||
|
|
||||||
|
- **bold**
|
||||||
|
- *italic*
|
||||||
|
- :strike:`strike`
|
||||||
|
- :underline:`underline`
|
||||||
|
- `text URL <https://pyrogram.org>`_
|
||||||
|
- `user text mention <https://t.me/haskell>`_
|
||||||
|
- ``inline fixed-width code``
|
||||||
|
- .. code-block:: text
|
||||||
|
|
||||||
|
pre-formatted
|
||||||
|
fixed-width
|
||||||
|
code block
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
User text mentions are only guaranteed to work if you have already met the user (in groups or private chats).
|
||||||
|
|
||||||
Markdown Style
|
Markdown Style
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
To use this mode, pass "markdown" in the *parse_mode* field when using
|
To strictly use this mode, pass "markdown" to the *parse_mode* parameter when using
|
||||||
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
|
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
**bold text**
|
**bold**
|
||||||
|
|
||||||
__italic text__
|
__italic__
|
||||||
|
|
||||||
[inline URL](https://docs.pyrogram.org/)
|
--underline--
|
||||||
|
|
||||||
[inline mention of a user](tg://user?id=23122162)
|
~~strike~~
|
||||||
|
|
||||||
|
[text URL](https://docs.pyrogram.org/)
|
||||||
|
|
||||||
|
[text user mention](tg://user?id=23122162)
|
||||||
|
|
||||||
`inline fixed-width code`
|
`inline fixed-width code`
|
||||||
|
|
||||||
```block_language
|
```
|
||||||
pre-formatted fixed-width code block
|
pre-formatted
|
||||||
|
fixed-width
|
||||||
|
code block
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_message(
|
||||||
|
"haskell",
|
||||||
|
(
|
||||||
|
"**bold**, "
|
||||||
|
"__italic__, "
|
||||||
|
"--underline--, "
|
||||||
|
"~~strike~~, "
|
||||||
|
"[mention](tg://user?id=23122162), "
|
||||||
|
"[URL](https://pyrogram.org), "
|
||||||
|
"`code`, "
|
||||||
|
"```"
|
||||||
|
"for i in range(10):\n"
|
||||||
|
" print(i)"
|
||||||
|
"```"
|
||||||
|
),
|
||||||
|
parse_mode="markdown"
|
||||||
|
)
|
||||||
|
|
||||||
HTML Style
|
HTML Style
|
||||||
----------
|
----------
|
||||||
|
|
||||||
To use this mode, pass "html" in the *parse_mode* field when using :meth:`~pyrogram.Client.send_message`.
|
To strictly use this mode, pass "html" to the *parse_mode* parameter when using :meth:`~pyrogram.Client.send_message`.
|
||||||
The following tags are currently supported:
|
The following tags are currently supported:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
@ -43,49 +102,36 @@ The following tags are currently supported:
|
|||||||
|
|
||||||
<i>italic</i>, <em>italic</em>
|
<i>italic</i>, <em>italic</em>
|
||||||
|
|
||||||
<a href="http://docs.pyrogram.org/">inline URL</a>
|
<u>underline</u>
|
||||||
|
|
||||||
<a href="tg://user?id=23122162">inline mention of a user</a>
|
<s>strike</s>, <del>strike</del>, <strike>strike</strike>
|
||||||
|
|
||||||
|
<a href="http://docs.pyrogram.org/">text URL</a>
|
||||||
|
|
||||||
|
<a href="tg://user?id=23122162">inline mention</a>
|
||||||
|
|
||||||
<code>inline fixed-width code</code>
|
<code>inline fixed-width code</code>
|
||||||
|
|
||||||
<pre>pre-formatted fixed-width code block</pre>
|
<pre>
|
||||||
|
pre-formatted
|
||||||
|
fixed-width
|
||||||
|
code block
|
||||||
|
</pre>
|
||||||
|
|
||||||
.. note:: Mentions are only guaranteed to work if you have already met the user (in groups or private chats).
|
**Example**:
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Markdown:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
app.send_message(
|
app.send_message(
|
||||||
chat_id="haskell",
|
"haskell",
|
||||||
text=(
|
(
|
||||||
"**bold**, "
|
|
||||||
"__italic__, "
|
|
||||||
"[mention](tg://user?id=23122162), "
|
|
||||||
"[URL](https://docs.pyrogram.org), "
|
|
||||||
"`code`, "
|
|
||||||
"```"
|
|
||||||
"for i in range(10):\n"
|
|
||||||
" print(i)```"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
- HTML:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app.send_message(
|
|
||||||
chat_id="haskell",
|
|
||||||
text=(
|
|
||||||
"<b>bold</b>, "
|
"<b>bold</b>, "
|
||||||
"<i>italic</i>, "
|
"<i>italic</i>, "
|
||||||
|
"<u>underline</u>, "
|
||||||
|
"<s>strike</s>, "
|
||||||
"<a href=\"tg://user?id=23122162\">mention</a>, "
|
"<a href=\"tg://user?id=23122162\">mention</a>, "
|
||||||
"<a href=\"https://pyrogram.org/\">URL</a>, "
|
"<a href=\"https://pyrogram.org/\">URL</a>, "
|
||||||
"<code>code</code>, "
|
"<code>code</code>\n\n"
|
||||||
"<pre>"
|
"<pre>"
|
||||||
"for i in range(10):\n"
|
"for i in range(10):\n"
|
||||||
" print(i)"
|
" print(i)"
|
||||||
@ -94,4 +140,86 @@ Examples
|
|||||||
parse_mode="html"
|
parse_mode="html"
|
||||||
)
|
)
|
||||||
|
|
||||||
.. _Telegram Bot API: https://core.telegram.org/bots/api#formatting-options
|
.. note::
|
||||||
|
|
||||||
|
All ``<``, ``>`` and ``&`` symbols that are not a part of a tag or an HTML entity must be replaced with the
|
||||||
|
corresponding HTML entities (``<`` with ``<``, ``>`` with ``>`` and ``&`` with ``&``). You can use this
|
||||||
|
snippet to quickly escape those characters:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import html
|
||||||
|
|
||||||
|
text = "<my text>"
|
||||||
|
text = html.escape(text)
|
||||||
|
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
<my text>
|
||||||
|
|
||||||
|
Different Styles
|
||||||
|
----------------
|
||||||
|
|
||||||
|
By default, when ignoring the *parse_mode* parameter, both Markdown and HTML styles are enabled together.
|
||||||
|
This means you can combine together both syntaxes in the same text:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_message("haskell", "**bold**, <i>italic</i>")
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
**bold**, *italic*
|
||||||
|
|
||||||
|
If you don't like this behaviour you can always choose to only enable either Markdown or HTML in strict mode by passing
|
||||||
|
"markdown" or "html" as argument to the *parse_mode* parameter.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="markdown")
|
||||||
|
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="html")
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
**bold**, <i>italic</i>
|
||||||
|
|
||||||
|
\*\*bold**, *italic*
|
||||||
|
|
||||||
|
In case you want to completely turn off the style parser, simply pass ``None`` to *parse_mode*. The text will be sent
|
||||||
|
as-is.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode=None)
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
\*\*bold**, <i>italic</i>
|
||||||
|
|
||||||
|
Nested and Overlapping Entities
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
You can also style texts with more than one decoration at once by nesting entities together. For example, you can send
|
||||||
|
a text message with both :bold-underline:`bold and underline` styles, or a text that has both :strike-italic:`italic and
|
||||||
|
strike` styles, and you can still combine both Markdown and HTML together.
|
||||||
|
|
||||||
|
Here there are some example texts you can try sending:
|
||||||
|
|
||||||
|
**Markdown**:
|
||||||
|
|
||||||
|
- ``**bold, --underline--**``
|
||||||
|
- ``**bold __italic --underline ~~strike~~--__**``
|
||||||
|
- ``**bold __and** italic__``
|
||||||
|
|
||||||
|
**HTML**:
|
||||||
|
|
||||||
|
- ``<b>bold, <u>underline</u></b>``
|
||||||
|
- ``<b>bold <i>italic <u>underline <s>strike</s></u></i></b>``
|
||||||
|
- ``<b>bold <i>and</b> italic</i>``
|
||||||
|
|
||||||
|
**Combined**:
|
||||||
|
|
||||||
|
- ``--you can combine <i>HTML</i> with **Markdown**--``
|
||||||
|
- ``**and also <i>overlap** --entities</i> this way--``
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
Using Filters
|
Using Filters
|
||||||
=============
|
=============
|
||||||
|
|
||||||
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
So far we've seen :doc:`how to register a callback function <../start/updates>` that executes every time a specific update
|
||||||
but there's much more than that to come.
|
comes from the server, but there's much more than that to come.
|
||||||
|
|
||||||
Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
|
Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
|
||||||
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
||||||
|
@ -24,7 +24,7 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
|
|||||||
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
||||||
sys.modules["typing"] = typing
|
sys.modules["typing"] = typing
|
||||||
|
|
||||||
__version__ = "0.15.0-develop"
|
__version__ = "0.16.0.dev"
|
||||||
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
||||||
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
|
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
from .all import objects
|
from .all import objects
|
||||||
from .core.tl_object import TLObject
|
|
||||||
|
|
||||||
for k, v in objects.items():
|
for k, v in objects.items():
|
||||||
path, name = v.rsplit(".", 1)
|
path, name = v.rsplit(".", 1)
|
||||||
TLObject.all[k] = getattr(import_module(path), name)
|
objects[k] = getattr(import_module(path), name)
|
||||||
|
@ -22,8 +22,5 @@ from .gzip_packed import GzipPacked
|
|||||||
from .list import List
|
from .list import List
|
||||||
from .message import Message
|
from .message import Message
|
||||||
from .msg_container import MsgContainer
|
from .msg_container import MsgContainer
|
||||||
from .primitives import (
|
from .primitives import *
|
||||||
Bool, BoolTrue, BoolFalse, Bytes, Double,
|
|
||||||
Int, Long, Int128, Int256, Null, String, Vector
|
|
||||||
)
|
|
||||||
from .tl_object import TLObject
|
from .tl_object import TLObject
|
||||||
|
@ -16,10 +16,11 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .bool import Bool, BoolTrue, BoolFalse
|
from .bool import Bool, BoolFalse, BoolTrue
|
||||||
from .bytes import Bytes
|
from .bytes import Bytes
|
||||||
from .double import Double
|
from .double import Double
|
||||||
from .int import Int, Long, Int128, Int256
|
from .int import Int, Long, Int128, Int256
|
||||||
from .null import Null
|
|
||||||
from .string import String
|
from .string import String
|
||||||
from .vector import Vector
|
from .vector import Vector
|
||||||
|
|
||||||
|
__all__ = ["Bool", "BoolFalse", "BoolTrue", "Bytes", "Double", "Int", "Long", "Int128", "Int256", "String", "Vector"]
|
||||||
|
@ -20,17 +20,17 @@ from collections import OrderedDict
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
|
from ..all import objects
|
||||||
|
|
||||||
|
|
||||||
class TLObject:
|
class TLObject:
|
||||||
all = {}
|
|
||||||
|
|
||||||
__slots__ = []
|
__slots__ = []
|
||||||
|
|
||||||
QUALNAME = "Base"
|
QUALNAME = "Base"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, *args): # TODO: Rename b -> data
|
def read(b: BytesIO, *args): # TODO: Rename b -> data
|
||||||
return TLObject.all[int.from_bytes(b.read(4), "little")].read(b, *args)
|
return objects[int.from_bytes(b.read(4), "little")].read(b, *args)
|
||||||
|
|
||||||
def write(self, *args) -> bytes:
|
def write(self, *args) -> bytes:
|
||||||
pass
|
pass
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,11 +19,13 @@
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from pyrogram import __version__
|
from pyrogram import __version__
|
||||||
from ..style import Markdown, HTML
|
from ..parser import Parser
|
||||||
from ...session.internals import MsgId
|
from ...session.internals import MsgId
|
||||||
|
|
||||||
|
|
||||||
@ -45,6 +47,8 @@ class BaseClient:
|
|||||||
|
|
||||||
LANG_CODE = "en"
|
LANG_CODE = "en"
|
||||||
|
|
||||||
|
PARENT_DIR = Path(sys.argv[0]).parent
|
||||||
|
|
||||||
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/joinchat/)([\w-]+)$")
|
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/joinchat/)([\w-]+)$")
|
||||||
BOT_TOKEN_RE = re.compile(r"^\d+:[\w-]+$")
|
BOT_TOKEN_RE = re.compile(r"^\d+:[\w-]+$")
|
||||||
DIALOGS_AT_ONCE = 100
|
DIALOGS_AT_ONCE = 100
|
||||||
@ -52,8 +56,10 @@ class BaseClient:
|
|||||||
DOWNLOAD_WORKERS = 1
|
DOWNLOAD_WORKERS = 1
|
||||||
OFFLINE_SLEEP = 900
|
OFFLINE_SLEEP = 900
|
||||||
WORKERS = 4
|
WORKERS = 4
|
||||||
WORKDIR = "."
|
WORKDIR = PARENT_DIR
|
||||||
CONFIG_FILE = "./config.ini"
|
CONFIG_FILE = PARENT_DIR / "config.ini"
|
||||||
|
|
||||||
|
PARSE_MODES = ["combined", "markdown", "md", "html", None]
|
||||||
|
|
||||||
MEDIA_TYPE_ID = {
|
MEDIA_TYPE_ID = {
|
||||||
0: "photo_thumbnail",
|
0: "photo_thumbnail",
|
||||||
@ -83,28 +89,21 @@ class BaseClient:
|
|||||||
|
|
||||||
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
||||||
|
|
||||||
|
is_idling = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.is_bot = None
|
self.storage = None
|
||||||
self.dc_id = None
|
|
||||||
self.auth_key = None
|
|
||||||
self.user_id = None
|
|
||||||
self.date = None
|
|
||||||
|
|
||||||
self.rnd_id = MsgId
|
self.rnd_id = MsgId
|
||||||
|
|
||||||
self.peers_by_id = {}
|
self.parser = Parser(self)
|
||||||
self.peers_by_username = {}
|
self.parse_mode = "combined"
|
||||||
self.peers_by_phone = {}
|
|
||||||
|
|
||||||
self.markdown = Markdown(self)
|
|
||||||
self.html = HTML(self)
|
|
||||||
|
|
||||||
self.session = None
|
self.session = None
|
||||||
self.media_sessions = {}
|
self.media_sessions = {}
|
||||||
self.media_sessions_lock = Lock()
|
self.media_sessions_lock = Lock()
|
||||||
|
|
||||||
self.is_started = None
|
self.is_started = None
|
||||||
self.is_idle = None
|
|
||||||
|
|
||||||
self.takeout_id = None
|
self.takeout_id = None
|
||||||
|
|
||||||
@ -159,3 +158,18 @@ class BaseClient:
|
|||||||
|
|
||||||
def edit_message_text(self, *args, **kwargs):
|
def edit_message_text(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def edit_inline_text(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def edit_message_media(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def edit_inline_media(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def edit_message_reply_markup(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def edit_inline_reply_markup(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
@ -20,7 +20,7 @@ import logging
|
|||||||
import threading
|
import threading
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from threading import Thread
|
from threading import Thread, Lock
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import types
|
from pyrogram.api import types
|
||||||
@ -61,6 +61,8 @@ class Dispatcher:
|
|||||||
self.workers = workers
|
self.workers = workers
|
||||||
|
|
||||||
self.workers_list = []
|
self.workers_list = []
|
||||||
|
self.locks_list = []
|
||||||
|
|
||||||
self.updates_queue = Queue()
|
self.updates_queue = Queue()
|
||||||
self.groups = OrderedDict()
|
self.groups = OrderedDict()
|
||||||
|
|
||||||
@ -75,9 +77,7 @@ class Dispatcher:
|
|||||||
lambda upd, usr, cht: (pyrogram.CallbackQuery._parse(self.client, upd, usr), CallbackQueryHandler),
|
lambda upd, usr, cht: (pyrogram.CallbackQuery._parse(self.client, upd, usr), CallbackQueryHandler),
|
||||||
|
|
||||||
(types.UpdateUserStatus,):
|
(types.UpdateUserStatus,):
|
||||||
lambda upd, usr, cht: (
|
lambda upd, usr, cht: (pyrogram.User._parse_user_status(self.client, upd), UserStatusHandler),
|
||||||
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
|
|
||||||
),
|
|
||||||
|
|
||||||
(types.UpdateBotInlineQuery,):
|
(types.UpdateBotInlineQuery,):
|
||||||
lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler),
|
lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler),
|
||||||
@ -90,10 +90,13 @@ class Dispatcher:
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
for i in range(self.workers):
|
for i in range(self.workers):
|
||||||
|
self.locks_list.append(Lock())
|
||||||
|
|
||||||
self.workers_list.append(
|
self.workers_list.append(
|
||||||
Thread(
|
Thread(
|
||||||
target=self.update_worker,
|
target=self.update_worker,
|
||||||
name="UpdateWorker#{}".format(i + 1)
|
name="UpdateWorker#{}".format(i + 1),
|
||||||
|
args=(self.locks_list[-1],)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -107,22 +110,37 @@ class Dispatcher:
|
|||||||
worker.join()
|
worker.join()
|
||||||
|
|
||||||
self.workers_list.clear()
|
self.workers_list.clear()
|
||||||
|
self.locks_list.clear()
|
||||||
self.groups.clear()
|
self.groups.clear()
|
||||||
|
|
||||||
def add_handler(self, handler, group: int):
|
def add_handler(self, handler, group: int):
|
||||||
|
for lock in self.locks_list:
|
||||||
|
lock.acquire()
|
||||||
|
|
||||||
|
try:
|
||||||
if group not in self.groups:
|
if group not in self.groups:
|
||||||
self.groups[group] = []
|
self.groups[group] = []
|
||||||
self.groups = OrderedDict(sorted(self.groups.items()))
|
self.groups = OrderedDict(sorted(self.groups.items()))
|
||||||
|
|
||||||
self.groups[group].append(handler)
|
self.groups[group].append(handler)
|
||||||
|
finally:
|
||||||
|
for lock in self.locks_list:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
def remove_handler(self, handler, group: int):
|
def remove_handler(self, handler, group: int):
|
||||||
|
for lock in self.locks_list:
|
||||||
|
lock.acquire()
|
||||||
|
|
||||||
|
try:
|
||||||
if group not in self.groups:
|
if group not in self.groups:
|
||||||
raise ValueError("Group {} does not exist. Handler was not removed.".format(group))
|
raise ValueError("Group {} does not exist. Handler was not removed.".format(group))
|
||||||
|
|
||||||
self.groups[group].remove(handler)
|
self.groups[group].remove(handler)
|
||||||
|
finally:
|
||||||
|
for lock in self.locks_list:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
def update_worker(self):
|
def update_worker(self, lock):
|
||||||
name = threading.current_thread().name
|
name = threading.current_thread().name
|
||||||
log.debug("{} started".format(name))
|
log.debug("{} started".format(name))
|
||||||
|
|
||||||
@ -142,13 +160,19 @@ class Dispatcher:
|
|||||||
else (None, type(None))
|
else (None, type(None))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with lock:
|
||||||
for group in self.groups.values():
|
for group in self.groups.values():
|
||||||
for handler in group:
|
for handler in group:
|
||||||
args = None
|
args = None
|
||||||
|
|
||||||
if isinstance(handler, handler_type):
|
if isinstance(handler, handler_type):
|
||||||
|
try:
|
||||||
if handler.check(parsed_update):
|
if handler.check(parsed_update):
|
||||||
args = (parsed_update,)
|
args = (parsed_update,)
|
||||||
|
except Exception as e:
|
||||||
|
log.error(e, exc_info=True)
|
||||||
|
continue
|
||||||
|
|
||||||
elif isinstance(handler, RawUpdateHandler):
|
elif isinstance(handler, RawUpdateHandler):
|
||||||
args = (update, users, chats)
|
args = (update, users, chats)
|
||||||
|
|
||||||
|
@ -16,16 +16,10 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import base64
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import time
|
import time
|
||||||
from threading import Thread, Event, Lock
|
from threading import Thread, Event, Lock
|
||||||
|
|
||||||
from . import utils
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -81,48 +75,13 @@ class Syncer:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def sync(cls, client):
|
def sync(cls, client):
|
||||||
temporary = os.path.join(client.workdir, "{}.sync".format(client.session_name))
|
|
||||||
persistent = os.path.join(client.workdir, "{}.session".format(client.session_name))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
auth_key = base64.b64encode(client.auth_key).decode()
|
start = time.time()
|
||||||
auth_key = [auth_key[i: i + 43] for i in range(0, len(auth_key), 43)]
|
client.storage.save()
|
||||||
|
|
||||||
data = dict(
|
|
||||||
dc_id=client.dc_id,
|
|
||||||
test_mode=client.test_mode,
|
|
||||||
auth_key=auth_key,
|
|
||||||
user_id=client.user_id,
|
|
||||||
date=int(time.time()),
|
|
||||||
is_bot=bool(client.is_bot),
|
|
||||||
peers_by_id={
|
|
||||||
k: getattr(v, "access_hash", None)
|
|
||||||
for k, v in client.peers_by_id.copy().items()
|
|
||||||
},
|
|
||||||
peers_by_username={
|
|
||||||
k: utils.get_peer_id(v)
|
|
||||||
for k, v in client.peers_by_username.copy().items()
|
|
||||||
},
|
|
||||||
peers_by_phone={
|
|
||||||
k: utils.get_peer_id(v)
|
|
||||||
for k, v in client.peers_by_phone.copy().items()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
os.makedirs(client.workdir, exist_ok=True)
|
|
||||||
|
|
||||||
with open(temporary, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(data, f, indent=4)
|
|
||||||
|
|
||||||
f.flush()
|
|
||||||
os.fsync(f.fileno())
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.critical(e, exc_info=True)
|
log.critical(e, exc_info=True)
|
||||||
else:
|
else:
|
||||||
shutil.move(temporary, persistent)
|
log.info('Synced "{}" in {:.6} ms'.format(
|
||||||
log.info("Synced {}".format(client.session_name))
|
client.storage.name,
|
||||||
finally:
|
(time.time() - start) * 1000
|
||||||
try:
|
))
|
||||||
os.remove(temporary)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
@ -18,22 +18,30 @@
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import struct
|
import struct
|
||||||
from base64 import b64decode, b64encode
|
from typing import List
|
||||||
from typing import Union, List
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.api.types import PeerUser, PeerChat, PeerChannel
|
||||||
from . import BaseClient
|
from . import BaseClient
|
||||||
from ...api import types
|
from ...api import types
|
||||||
|
|
||||||
|
|
||||||
def decode(s: str) -> bytes:
|
def decode(s: str) -> bytes:
|
||||||
s = b64decode(s + "=" * (-len(s) % 4), "-_")
|
s = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
|
||||||
r = b""
|
r = b""
|
||||||
|
|
||||||
|
try:
|
||||||
assert s[-1] == 2
|
assert s[-1] == 2
|
||||||
|
skip = 1
|
||||||
|
except AssertionError:
|
||||||
|
assert s[-2] == 22
|
||||||
|
assert s[-1] == 4
|
||||||
|
skip = 2
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(s) - 1:
|
|
||||||
|
while i < len(s) - skip:
|
||||||
if s[i] != 0:
|
if s[i] != 0:
|
||||||
r += bytes([s[i]])
|
r += bytes([s[i]])
|
||||||
else:
|
else:
|
||||||
@ -49,7 +57,7 @@ def encode(s: bytes) -> str:
|
|||||||
r = b""
|
r = b""
|
||||||
n = 0
|
n = 0
|
||||||
|
|
||||||
for i in s + bytes([2]):
|
for i in s + bytes([22]) + bytes([4]):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
n += 1
|
n += 1
|
||||||
else:
|
else:
|
||||||
@ -59,24 +67,7 @@ def encode(s: bytes) -> str:
|
|||||||
|
|
||||||
r += bytes([i])
|
r += bytes([i])
|
||||||
|
|
||||||
return b64encode(r, b"-_").decode().rstrip("=")
|
return base64.urlsafe_b64encode(r).decode().rstrip("=")
|
||||||
|
|
||||||
|
|
||||||
def get_peer_id(input_peer) -> int:
|
|
||||||
return (
|
|
||||||
input_peer.user_id if isinstance(input_peer, types.InputPeerUser)
|
|
||||||
else -input_peer.chat_id if isinstance(input_peer, types.InputPeerChat)
|
|
||||||
else int("-100" + str(input_peer.channel_id))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_input_peer(peer_id: int, access_hash: int):
|
|
||||||
return (
|
|
||||||
types.InputPeerUser(user_id=peer_id, access_hash=access_hash) if peer_id > 0
|
|
||||||
else types.InputPeerChannel(channel_id=int(str(peer_id)[4:]), access_hash=access_hash)
|
|
||||||
if (str(peer_id).startswith("-100") and access_hash)
|
|
||||||
else types.InputPeerChat(chat_id=-peer_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_offset_date(dialogs):
|
def get_offset_date(dialogs):
|
||||||
@ -183,7 +174,7 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
|
|||||||
pyrogram.Message(
|
pyrogram.Message(
|
||||||
message_id=message,
|
message_id=message,
|
||||||
chat=pyrogram.Chat(
|
chat=pyrogram.Chat(
|
||||||
id=int("-100" + str(channel_id)),
|
id=get_channel_id(channel_id),
|
||||||
type="channel",
|
type="channel",
|
||||||
client=client
|
client=client
|
||||||
) if channel_id is not None else None,
|
) if channel_id is not None else None,
|
||||||
@ -203,3 +194,39 @@ def unpack_inline_message_id(inline_message_id: str) -> types.InputBotInlineMess
|
|||||||
id=r[1],
|
id=r[1],
|
||||||
access_hash=r[2]
|
access_hash=r[2]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MIN_CHANNEL_ID = -1002147483647
|
||||||
|
MAX_CHANNEL_ID = -1000000000000
|
||||||
|
MIN_CHAT_ID = -2147483647
|
||||||
|
MAX_USER_ID = 2147483647
|
||||||
|
|
||||||
|
|
||||||
|
def get_peer_id(peer: Union[PeerUser, PeerChat, PeerChannel]) -> int:
|
||||||
|
if isinstance(peer, PeerUser):
|
||||||
|
return peer.user_id
|
||||||
|
|
||||||
|
if isinstance(peer, PeerChat):
|
||||||
|
return -peer.chat_id
|
||||||
|
|
||||||
|
if isinstance(peer, PeerChannel):
|
||||||
|
return MAX_CHANNEL_ID - peer.channel_id
|
||||||
|
|
||||||
|
raise ValueError("Peer type invalid: {}".format(peer))
|
||||||
|
|
||||||
|
|
||||||
|
def get_type(peer_id: int) -> str:
|
||||||
|
if peer_id < 0:
|
||||||
|
if MIN_CHAT_ID <= peer_id:
|
||||||
|
return "chat"
|
||||||
|
|
||||||
|
if MIN_CHANNEL_ID <= peer_id < MAX_CHANNEL_ID:
|
||||||
|
return "channel"
|
||||||
|
elif 0 < peer_id <= MAX_USER_ID:
|
||||||
|
return "user"
|
||||||
|
|
||||||
|
raise ValueError("Peer id invalid: {}".format(peer_id))
|
||||||
|
|
||||||
|
|
||||||
|
def get_channel_id(peer_id: int) -> int:
|
||||||
|
return MAX_CHANNEL_ID - peer_id
|
||||||
|
@ -17,180 +17,183 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from .filter import Filter
|
from .filter import Filter
|
||||||
from ..types.bots_and_keyboards import InlineKeyboardMarkup, ReplyKeyboardMarkup
|
from ..types.bots_and_keyboards import InlineKeyboardMarkup, ReplyKeyboardMarkup
|
||||||
|
|
||||||
|
CUSTOM_FILTER_NAME = "CustomFilter"
|
||||||
|
|
||||||
def create(name: str, func: callable, **kwargs) -> type:
|
|
||||||
"""Create a Filter.
|
def create(func: Callable, name: str = None, **kwargs) -> Filter:
|
||||||
|
"""Easily create a custom filter.
|
||||||
|
|
||||||
Custom filters give you extra control over which updates are allowed or not to be processed by your handlers.
|
Custom filters give you extra control over which updates are allowed or not to be processed by your handlers.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
name (``str``):
|
|
||||||
Your filter's name. Can be anything you like.
|
|
||||||
|
|
||||||
func (``callable``):
|
func (``callable``):
|
||||||
A function that accepts two arguments *(filter, update)* and returns a Boolean: True if the update should be
|
A function that accepts two positional arguments *(filter, update)* and returns a boolean: True if the
|
||||||
handled, False otherwise.
|
update should be handled, False otherwise. The *filter* argument refers to the filter itself and can be used
|
||||||
The "update" argument type will vary depending on which `Handler <Handlers.html>`_ is coming from.
|
to access keyword arguments (read below). The *update* argument type will vary depending on which
|
||||||
For example, in a :obj:`MessageHandler` the update type will be
|
`Handler <handlers>`_ is coming from. For example, in a :obj:`MessageHandler` the *update* argument will be
|
||||||
a :obj:`Message`; in a :obj:`CallbackQueryHandler` the
|
a :obj:`Message`; in a :obj:`CallbackQueryHandler` the *update* will be a :obj:`CallbackQuery`. Your
|
||||||
update type will be a :obj:`CallbackQuery`. Your function body can then access the
|
function body can then access the incoming update attributes and decide whether to allow it or not.
|
||||||
incoming update and decide whether to allow it or not.
|
|
||||||
|
name (``str``, *optional*):
|
||||||
|
Your filter's name. Can be anything you like.
|
||||||
|
Defaults to "CustomFilter".
|
||||||
|
|
||||||
**kwargs (``any``, *optional*):
|
**kwargs (``any``, *optional*):
|
||||||
Any keyword argument you would like to pass. Useful for custom filters that accept parameters (e.g.:
|
Any keyword argument you would like to pass. Useful when creating parameterized custom filters, such as
|
||||||
:meth:`~Filters.command`, :meth:`~Filters.regex`).
|
:meth:`~Filters.command` or :meth:`~Filters.regex`.
|
||||||
"""
|
"""
|
||||||
# TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only
|
# TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only
|
||||||
d = {"__call__": func}
|
d = {"__call__": func}
|
||||||
d.update(kwargs)
|
d.update(kwargs)
|
||||||
|
|
||||||
return type(name, (Filter,), d)()
|
return type(name or CUSTOM_FILTER_NAME, (Filter,), d)()
|
||||||
|
|
||||||
|
|
||||||
class Filters:
|
class Filters:
|
||||||
"""This class provides access to all library-defined Filters available in Pyrogram.
|
"""This class provides access to all library-defined Filters available in Pyrogram.
|
||||||
|
|
||||||
The Filters listed here are intended to be used with the :obj:`MessageHandler` only.
|
The Filters listed here are currently intended to be used with the :obj:`MessageHandler` only.
|
||||||
At the moment, if you want to filter updates coming from different `Handlers <Handlers.html>`_ you have to create
|
At the moment, if you want to filter updates coming from different `Handlers <Handlers.html>`_ you have to create
|
||||||
your own filters with :meth:`~Filters.create` and use them in the same way.
|
your own filters with :meth:`~Filters.create` and use them in the same way.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
create = create
|
create = create
|
||||||
|
|
||||||
me = create("Me", lambda _, m: bool(m.from_user and m.from_user.is_self))
|
me = create(lambda _, m: bool(m.from_user and m.from_user.is_self), "MeFilter")
|
||||||
"""Filter messages generated by you yourself."""
|
"""Filter messages generated by you yourself."""
|
||||||
|
|
||||||
bot = create("Bot", lambda _, m: bool(m.from_user and m.from_user.is_bot))
|
bot = create(lambda _, m: bool(m.from_user and m.from_user.is_bot), "BotFilter")
|
||||||
"""Filter messages coming from bots."""
|
"""Filter messages coming from bots."""
|
||||||
|
|
||||||
incoming = create("Incoming", lambda _, m: not m.outgoing)
|
incoming = create(lambda _, m: not m.outgoing, "IncomingFilter")
|
||||||
"""Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
|
"""Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
|
||||||
|
|
||||||
outgoing = create("Outgoing", lambda _, m: m.outgoing)
|
outgoing = create(lambda _, m: m.outgoing, "OutgoingFilter")
|
||||||
"""Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
|
"""Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
|
||||||
|
|
||||||
text = create("Text", lambda _, m: bool(m.text))
|
text = create(lambda _, m: bool(m.text), "TextFilter")
|
||||||
"""Filter text messages."""
|
"""Filter text messages."""
|
||||||
|
|
||||||
reply = create("Reply", lambda _, m: bool(m.reply_to_message))
|
reply = create(lambda _, m: bool(m.reply_to_message), "ReplyFilter")
|
||||||
"""Filter messages that are replies to other messages."""
|
"""Filter messages that are replies to other messages."""
|
||||||
|
|
||||||
forwarded = create("Forwarded", lambda _, m: bool(m.forward_date))
|
forwarded = create(lambda _, m: bool(m.forward_date), "ForwardedFilter")
|
||||||
"""Filter messages that are forwarded."""
|
"""Filter messages that are forwarded."""
|
||||||
|
|
||||||
caption = create("Caption", lambda _, m: bool(m.caption))
|
caption = create(lambda _, m: bool(m.caption), "CaptionFilter")
|
||||||
"""Filter media messages that contain captions."""
|
"""Filter media messages that contain captions."""
|
||||||
|
|
||||||
edited = create("Edited", lambda _, m: bool(m.edit_date))
|
edited = create(lambda _, m: bool(m.edit_date), "EditedFilter")
|
||||||
"""Filter edited messages."""
|
"""Filter edited messages."""
|
||||||
|
|
||||||
audio = create("Audio", lambda _, m: bool(m.audio))
|
audio = create(lambda _, m: bool(m.audio), "AudioFilter")
|
||||||
"""Filter messages that contain :obj:`Audio` objects."""
|
"""Filter messages that contain :obj:`Audio` objects."""
|
||||||
|
|
||||||
document = create("Document", lambda _, m: bool(m.document))
|
document = create(lambda _, m: bool(m.document), "DocumentFilter")
|
||||||
"""Filter messages that contain :obj:`Document` objects."""
|
"""Filter messages that contain :obj:`Document` objects."""
|
||||||
|
|
||||||
photo = create("Photo", lambda _, m: bool(m.photo))
|
photo = create(lambda _, m: bool(m.photo), "PhotoFilter")
|
||||||
"""Filter messages that contain :obj:`Photo` objects."""
|
"""Filter messages that contain :obj:`Photo` objects."""
|
||||||
|
|
||||||
sticker = create("Sticker", lambda _, m: bool(m.sticker))
|
sticker = create(lambda _, m: bool(m.sticker), "StickerFilter")
|
||||||
"""Filter messages that contain :obj:`Sticker` objects."""
|
"""Filter messages that contain :obj:`Sticker` objects."""
|
||||||
|
|
||||||
animation = create("Animation", lambda _, m: bool(m.animation))
|
animation = create(lambda _, m: bool(m.animation), "AnimationFilter")
|
||||||
"""Filter messages that contain :obj:`Animation` objects."""
|
"""Filter messages that contain :obj:`Animation` objects."""
|
||||||
|
|
||||||
game = create("Game", lambda _, m: bool(m.game))
|
game = create(lambda _, m: bool(m.game), "GameFilter")
|
||||||
"""Filter messages that contain :obj:`Game` objects."""
|
"""Filter messages that contain :obj:`Game` objects."""
|
||||||
|
|
||||||
video = create("Video", lambda _, m: bool(m.video))
|
video = create(lambda _, m: bool(m.video), "VideoFilter")
|
||||||
"""Filter messages that contain :obj:`Video` objects."""
|
"""Filter messages that contain :obj:`Video` objects."""
|
||||||
|
|
||||||
media_group = create("MediaGroup", lambda _, m: bool(m.media_group_id))
|
media_group = create(lambda _, m: bool(m.media_group_id), "MediaGroupFilter")
|
||||||
"""Filter messages containing photos or videos being part of an album."""
|
"""Filter messages containing photos or videos being part of an album."""
|
||||||
|
|
||||||
voice = create("Voice", lambda _, m: bool(m.voice))
|
voice = create(lambda _, m: bool(m.voice), "VoiceFilter")
|
||||||
"""Filter messages that contain :obj:`Voice` note objects."""
|
"""Filter messages that contain :obj:`Voice` note objects."""
|
||||||
|
|
||||||
video_note = create("VideoNote", lambda _, m: bool(m.video_note))
|
video_note = create(lambda _, m: bool(m.video_note), "VideoNoteFilter")
|
||||||
"""Filter messages that contain :obj:`VideoNote` objects."""
|
"""Filter messages that contain :obj:`VideoNote` objects."""
|
||||||
|
|
||||||
contact = create("Contact", lambda _, m: bool(m.contact))
|
contact = create(lambda _, m: bool(m.contact), "ContactFilter")
|
||||||
"""Filter messages that contain :obj:`Contact` objects."""
|
"""Filter messages that contain :obj:`Contact` objects."""
|
||||||
|
|
||||||
location = create("Location", lambda _, m: bool(m.location))
|
location = create(lambda _, m: bool(m.location), "LocationFilter")
|
||||||
"""Filter messages that contain :obj:`Location` objects."""
|
"""Filter messages that contain :obj:`Location` objects."""
|
||||||
|
|
||||||
venue = create("Venue", lambda _, m: bool(m.venue))
|
venue = create(lambda _, m: bool(m.venue), "VenueFilter")
|
||||||
"""Filter messages that contain :obj:`Venue` objects."""
|
"""Filter messages that contain :obj:`Venue` objects."""
|
||||||
|
|
||||||
web_page = create("WebPage", lambda _, m: m.web_page)
|
web_page = create(lambda _, m: m.web_page, "WebPageFilter")
|
||||||
"""Filter messages sent with a webpage preview."""
|
"""Filter messages sent with a webpage preview."""
|
||||||
|
|
||||||
poll = create("Poll", lambda _, m: m.poll)
|
poll = create(lambda _, m: m.poll, "PollFilter")
|
||||||
"""Filter messages that contain :obj:`Poll` objects."""
|
"""Filter messages that contain :obj:`Poll` objects."""
|
||||||
|
|
||||||
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
|
private = create(lambda _, m: bool(m.chat and m.chat.type in {"private", "bot"}), "PrivateFilter")
|
||||||
"""Filter messages sent in private chats."""
|
"""Filter messages sent in private chats."""
|
||||||
|
|
||||||
group = create("Group", lambda _, m: bool(m.chat and m.chat.type in {"group", "supergroup"}))
|
group = create(lambda _, m: bool(m.chat and m.chat.type in {"group", "supergroup"}), "GroupFilter")
|
||||||
"""Filter messages sent in group or supergroup chats."""
|
"""Filter messages sent in group or supergroup chats."""
|
||||||
|
|
||||||
channel = create("Channel", lambda _, m: bool(m.chat and m.chat.type == "channel"))
|
channel = create(lambda _, m: bool(m.chat and m.chat.type == "channel"), "ChannelFilter")
|
||||||
"""Filter messages sent in channels."""
|
"""Filter messages sent in channels."""
|
||||||
|
|
||||||
new_chat_members = create("NewChatMembers", lambda _, m: bool(m.new_chat_members))
|
new_chat_members = create(lambda _, m: bool(m.new_chat_members), "NewChatMembersFilter")
|
||||||
"""Filter service messages for new chat members."""
|
"""Filter service messages for new chat members."""
|
||||||
|
|
||||||
left_chat_member = create("LeftChatMember", lambda _, m: bool(m.left_chat_member))
|
left_chat_member = create(lambda _, m: bool(m.left_chat_member), "LeftChatMemberFilter")
|
||||||
"""Filter service messages for members that left the chat."""
|
"""Filter service messages for members that left the chat."""
|
||||||
|
|
||||||
new_chat_title = create("NewChatTitle", lambda _, m: bool(m.new_chat_title))
|
new_chat_title = create(lambda _, m: bool(m.new_chat_title), "NewChatTitleFilter")
|
||||||
"""Filter service messages for new chat titles."""
|
"""Filter service messages for new chat titles."""
|
||||||
|
|
||||||
new_chat_photo = create("NewChatPhoto", lambda _, m: bool(m.new_chat_photo))
|
new_chat_photo = create(lambda _, m: bool(m.new_chat_photo), "NewChatPhotoFilter")
|
||||||
"""Filter service messages for new chat photos."""
|
"""Filter service messages for new chat photos."""
|
||||||
|
|
||||||
delete_chat_photo = create("DeleteChatPhoto", lambda _, m: bool(m.delete_chat_photo))
|
delete_chat_photo = create(lambda _, m: bool(m.delete_chat_photo), "DeleteChatPhotoFilter")
|
||||||
"""Filter service messages for deleted photos."""
|
"""Filter service messages for deleted photos."""
|
||||||
|
|
||||||
group_chat_created = create("GroupChatCreated", lambda _, m: bool(m.group_chat_created))
|
group_chat_created = create(lambda _, m: bool(m.group_chat_created), "GroupChatCreatedFilter")
|
||||||
"""Filter service messages for group chat creations."""
|
"""Filter service messages for group chat creations."""
|
||||||
|
|
||||||
supergroup_chat_created = create("SupergroupChatCreated", lambda _, m: bool(m.supergroup_chat_created))
|
supergroup_chat_created = create(lambda _, m: bool(m.supergroup_chat_created), "SupergroupChatCreatedFilter")
|
||||||
"""Filter service messages for supergroup chat creations."""
|
"""Filter service messages for supergroup chat creations."""
|
||||||
|
|
||||||
channel_chat_created = create("ChannelChatCreated", lambda _, m: bool(m.channel_chat_created))
|
channel_chat_created = create(lambda _, m: bool(m.channel_chat_created), "ChannelChatCreatedFilter")
|
||||||
"""Filter service messages for channel chat creations."""
|
"""Filter service messages for channel chat creations."""
|
||||||
|
|
||||||
migrate_to_chat_id = create("MigrateToChatId", lambda _, m: bool(m.migrate_to_chat_id))
|
migrate_to_chat_id = create(lambda _, m: bool(m.migrate_to_chat_id), "MigrateToChatIdFilter")
|
||||||
"""Filter service messages that contain migrate_to_chat_id."""
|
"""Filter service messages that contain migrate_to_chat_id."""
|
||||||
|
|
||||||
migrate_from_chat_id = create("MigrateFromChatId", lambda _, m: bool(m.migrate_from_chat_id))
|
migrate_from_chat_id = create(lambda _, m: bool(m.migrate_from_chat_id), "MigrateFromChatIdFilter")
|
||||||
"""Filter service messages that contain migrate_from_chat_id."""
|
"""Filter service messages that contain migrate_from_chat_id."""
|
||||||
|
|
||||||
pinned_message = create("PinnedMessage", lambda _, m: bool(m.pinned_message))
|
pinned_message = create(lambda _, m: bool(m.pinned_message), "PinnedMessageFilter")
|
||||||
"""Filter service messages for pinned messages."""
|
"""Filter service messages for pinned messages."""
|
||||||
|
|
||||||
game_high_score = create("GameHighScore", lambda _, m: bool(m.game_high_score))
|
game_high_score = create(lambda _, m: bool(m.game_high_score), "GameHighScoreFilter")
|
||||||
"""Filter service messages for game high scores."""
|
"""Filter service messages for game high scores."""
|
||||||
|
|
||||||
reply_keyboard = create("ReplyKeyboard", lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup))
|
reply_keyboard = create(lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup), "ReplyKeyboardFilter")
|
||||||
"""Filter messages containing reply keyboard markups"""
|
"""Filter messages containing reply keyboard markups"""
|
||||||
|
|
||||||
inline_keyboard = create("InlineKeyboard", lambda _, m: isinstance(m.reply_markup, InlineKeyboardMarkup))
|
inline_keyboard = create(lambda _, m: isinstance(m.reply_markup, InlineKeyboardMarkup), "InlineKeyboardFilter")
|
||||||
"""Filter messages containing inline keyboard markups"""
|
"""Filter messages containing inline keyboard markups"""
|
||||||
|
|
||||||
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
|
mentioned = create(lambda _, m: bool(m.mentioned), "MentionedFilter")
|
||||||
"""Filter messages containing mentions"""
|
"""Filter messages containing mentions"""
|
||||||
|
|
||||||
via_bot = create("ViaBot", lambda _, m: bool(m.via_bot))
|
via_bot = create(lambda _, m: bool(m.via_bot), "ViaBotFilter")
|
||||||
"""Filter messages sent via inline bots"""
|
"""Filter messages sent via inline bots"""
|
||||||
|
|
||||||
service = create("Service", lambda _, m: bool(m.service))
|
service = create(lambda _, m: bool(m.service), "ServiceFilter")
|
||||||
"""Filter service messages.
|
"""Filter service messages.
|
||||||
|
|
||||||
A service message contains any of the following fields set: *left_chat_member*,
|
A service message contains any of the following fields set: *left_chat_member*,
|
||||||
@ -198,7 +201,7 @@ class Filters:
|
|||||||
*channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*.
|
*channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
media = create("Media", lambda _, m: bool(m.media))
|
media = create(lambda _, m: bool(m.media), "MediaFilter")
|
||||||
"""Filter media messages.
|
"""Filter media messages.
|
||||||
|
|
||||||
A media message contains any of the following fields set: *audio*, *document*, *photo*, *sticker*, *video*,
|
A media message contains any of the following fields set: *audio*, *document*, *photo*, *sticker*, *video*,
|
||||||
@ -237,6 +240,7 @@ class Filters:
|
|||||||
|
|
||||||
def func(flt, message):
|
def func(flt, message):
|
||||||
text = message.text or message.caption
|
text = message.text or message.caption
|
||||||
|
message.command = None
|
||||||
|
|
||||||
if text:
|
if text:
|
||||||
for p in flt.p:
|
for p in flt.p:
|
||||||
@ -253,27 +257,31 @@ class Filters:
|
|||||||
commands = {c if case_sensitive else c.lower() for c in commands}
|
commands = {c if case_sensitive else c.lower() for c in commands}
|
||||||
prefixes = set(prefix) if prefix else {""}
|
prefixes = set(prefix) if prefix else {""}
|
||||||
|
|
||||||
return create("Command", func=func, c=commands, p=prefixes, s=separator, cs=case_sensitive)
|
return create(func, "CommandFilter", c=commands, p=prefixes, s=separator, cs=case_sensitive)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def regex(pattern, flags: int = 0):
|
def regex(pattern, flags: int = 0):
|
||||||
"""Filter messages that match a given RegEx pattern.
|
"""Filter message texts or captions that match a given regular expression pattern.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
pattern (``str``):
|
pattern (``str``):
|
||||||
The RegEx pattern as string, it will be applied to the text of a message. When a pattern matches,
|
The RegEx pattern as string, it will be applied to the text or the caption of a message. When a pattern
|
||||||
all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_
|
matches, all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_ are stored
|
||||||
are stored in the *matches* field of the :obj:`Message` itself.
|
in the *matches* field of the :obj:`Message` itself.
|
||||||
|
|
||||||
flags (``int``, *optional*):
|
flags (``int``, *optional*):
|
||||||
RegEx flags.
|
RegEx flags.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def f(_, m):
|
def func(flt, message):
|
||||||
m.matches = [i for i in _.p.finditer(m.text or m.caption or "")]
|
text = message.text or message.caption
|
||||||
return bool(m.matches)
|
|
||||||
|
|
||||||
return create("Regex", f, p=re.compile(pattern, flags))
|
if text:
|
||||||
|
message.matches = list(flt.p.finditer(text)) or None
|
||||||
|
|
||||||
|
return bool(message.matches)
|
||||||
|
|
||||||
|
return create(func, "RegexFilter", p=re.compile(pattern, flags))
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class user(Filter, set):
|
class user(Filter, set):
|
||||||
@ -348,6 +356,6 @@ class Filters:
|
|||||||
Pass the data you want to filter for.
|
Pass the data you want to filter for.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return create("CallbackData", lambda flt, cb: cb.data == flt.data, data=data)
|
return create(lambda flt, cb: cb.data == flt.data, "CallbackDataFilter", data=data)
|
||||||
|
|
||||||
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
dan = create(lambda _, m: bool(m.from_user and m.from_user.id == 23122162), "DanFilter")
|
||||||
|
@ -21,26 +21,24 @@ from .handler import Handler
|
|||||||
|
|
||||||
class UserStatusHandler(Handler):
|
class UserStatusHandler(Handler):
|
||||||
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
|
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
|
||||||
It is intended to be used with :meth:`~Client.add_handler`
|
It is intended to be used with :meth:`~Client.add_handler`.
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the :meth:`~Client.on_user_status` decorator.
|
||||||
:meth:`~Client.on_user_status` decorator.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
Pass a function that will be called when a new UserStatus update arrives. It takes *(client, user_status)*
|
Pass a function that will be called when a new user status update arrives. It takes *(client, user)*
|
||||||
as positional arguments (look at the section below for a detailed description).
|
as positional arguments (look at the section below for a detailed description).
|
||||||
|
|
||||||
filters (:obj:`Filters`):
|
filters (:obj:`Filters`):
|
||||||
Pass one or more filters to allow only a subset of messages to be passed
|
Pass one or more filters to allow only a subset of users to be passed in your callback function.
|
||||||
in your callback function.
|
|
||||||
|
|
||||||
Other parameters:
|
Other parameters:
|
||||||
client (:obj:`Client`):
|
client (:obj:`Client`):
|
||||||
The Client itself, useful when you want to call other API methods inside the user status handler.
|
The Client itself, useful when you want to call other API methods inside the user status handler.
|
||||||
|
|
||||||
user_status (:obj:`UserStatus`):
|
user (:obj:`User`):
|
||||||
The received UserStatus update.
|
The user containing the updated status.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, callback: callable, filters=None):
|
def __init__(self, callback: callable, filters=None):
|
||||||
|
@ -56,8 +56,14 @@ class AnswerCallbackQuery(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True, on success.
|
``bool``: True, on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Answer without alert
|
||||||
|
app.answer_callback_query(query_id, text=text)
|
||||||
|
|
||||||
|
# Answer with alert
|
||||||
|
app.answer_callback_query(query_id, text=text, show_alert=True)
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SetBotCallbackAnswer(
|
functions.messages.SetBotCallbackAnswer(
|
||||||
|
@ -29,28 +29,34 @@ class AnswerInlineQuery(BaseClient):
|
|||||||
inline_query_id: str,
|
inline_query_id: str,
|
||||||
results: List[InlineQueryResult],
|
results: List[InlineQueryResult],
|
||||||
cache_time: int = 300,
|
cache_time: int = 300,
|
||||||
is_personal: bool = None,
|
is_gallery: bool = False,
|
||||||
|
is_personal: bool = False,
|
||||||
next_offset: str = "",
|
next_offset: str = "",
|
||||||
switch_pm_text: str = "",
|
switch_pm_text: str = "",
|
||||||
switch_pm_parameter: str = ""
|
switch_pm_parameter: str = ""
|
||||||
):
|
):
|
||||||
"""Send answers to an inline query.
|
"""Send answers to an inline query.
|
||||||
No more than 50 results per query are allowed.
|
|
||||||
|
A maximum of 50 results per query is allowed.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inline_query_id (``str``):
|
inline_query_id (``str``):
|
||||||
Unique identifier for the answered query.
|
Unique identifier for the answered query.
|
||||||
|
|
||||||
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
results (List of :obj:`InlineQueryResult`):
|
||||||
A list of results for the inline query.
|
A list of results for the inline query.
|
||||||
|
|
||||||
cache_time (``int``, *optional*):
|
cache_time (``int``, *optional*):
|
||||||
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
||||||
Defaults to 300.
|
Defaults to 300.
|
||||||
|
|
||||||
|
is_gallery (``bool``, *optional*):
|
||||||
|
Pass True, if results should be displayed in gallery mode instead of list mode.
|
||||||
|
Defaults to False.
|
||||||
|
|
||||||
is_personal (``bool``, *optional*):
|
is_personal (``bool``, *optional*):
|
||||||
Pass True, if results may be cached on the server side only for the user that sent the query.
|
Pass True, if results may be cached on the server side only for the user that sent the query.
|
||||||
By default, results may be returned to any user who sends the same query.
|
By default (False), results may be returned to any user who sends the same query.
|
||||||
|
|
||||||
next_offset (``str``, *optional*):
|
next_offset (``str``, *optional*):
|
||||||
Pass the offset that a client should send in the next query with the same text to receive more results.
|
Pass the offset that a client should send in the next query with the same text to receive more results.
|
||||||
@ -75,15 +81,24 @@ class AnswerInlineQuery(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True, on success.
|
``bool``: True, on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InlineQueryResultArticle, InputTextMessageContent
|
||||||
|
|
||||||
|
app.answer_inline_query(
|
||||||
|
inline_query_id,
|
||||||
|
results=[
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
"Title",
|
||||||
|
InputTextMessageContent("Message content"))])
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SetInlineBotResults(
|
functions.messages.SetInlineBotResults(
|
||||||
query_id=int(inline_query_id),
|
query_id=int(inline_query_id),
|
||||||
results=[r.write() for r in results],
|
results=[r.write() for r in results],
|
||||||
cache_time=cache_time,
|
cache_time=cache_time,
|
||||||
gallery=None,
|
gallery=is_gallery or None,
|
||||||
private=is_personal or None,
|
private=is_personal or None,
|
||||||
next_offset=next_offset or None,
|
next_offset=next_offset or None,
|
||||||
switch_pm=types.InlineBotSwitchPM(
|
switch_pm=types.InlineBotSwitchPM(
|
||||||
|
@ -51,8 +51,11 @@ class GetGameHighScores(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`GameHighScore`: On success.
|
List of :obj:`GameHighScore`: On success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
scores = app.get_game_high_scores(user_id, chat_id, message_id)
|
||||||
|
print(scores)
|
||||||
"""
|
"""
|
||||||
# TODO: inline_message_id
|
# TODO: inline_message_id
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class GetInlineBotResults(BaseClient):
|
|||||||
def get_inline_bot_results(
|
def get_inline_bot_results(
|
||||||
self,
|
self,
|
||||||
bot: Union[int, str],
|
bot: Union[int, str],
|
||||||
query: str,
|
query: str = "",
|
||||||
offset: str = "",
|
offset: str = "",
|
||||||
latitude: float = None,
|
latitude: float = None,
|
||||||
longitude: float = None
|
longitude: float = None
|
||||||
@ -40,8 +40,9 @@ class GetInlineBotResults(BaseClient):
|
|||||||
Unique identifier of the inline bot you want to get results from. You can specify
|
Unique identifier of the inline bot you want to get results from. You can specify
|
||||||
a @username (str) or a bot ID (int).
|
a @username (str) or a bot ID (int).
|
||||||
|
|
||||||
query (``str``):
|
query (``str``, *optional*):
|
||||||
Text of the query (up to 512 characters).
|
Text of the query (up to 512 characters).
|
||||||
|
Defaults to "" (empty string).
|
||||||
|
|
||||||
offset (``str``, *optional*):
|
offset (``str``, *optional*):
|
||||||
Offset of the results to be returned.
|
Offset of the results to be returned.
|
||||||
@ -58,8 +59,13 @@ class GetInlineBotResults(BaseClient):
|
|||||||
:obj:`BotResults <pyrogram.api.types.messages.BotResults>`: On Success.
|
:obj:`BotResults <pyrogram.api.types.messages.BotResults>`: On Success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
TimeoutError: In case the bot fails to answer within 10 seconds.
|
TimeoutError: In case the bot fails to answer within 10 seconds.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
results = app.get_inline_bot_results("pyrogrambot")
|
||||||
|
print(results)
|
||||||
"""
|
"""
|
||||||
# TODO: Don't return the raw type
|
# TODO: Don't return the raw type
|
||||||
|
|
||||||
|
@ -53,8 +53,12 @@ class RequestCallbackAnswer(BaseClient):
|
|||||||
or as an alert.
|
or as an alert.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
TimeoutError: In case the bot fails to answer within 10 seconds.
|
TimeoutError: In case the bot fails to answer within 10 seconds.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.request_callback_answer(chat_id, message_id, "callback_data")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Telegram only wants bytes, but we are allowed to pass strings too.
|
# Telegram only wants bytes, but we are allowed to pass strings too.
|
||||||
|
@ -62,8 +62,10 @@ class SendGame(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent game message is returned.
|
:obj:`Message`: On success, the sent game message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_game(chat_id, "gamename")
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
|
@ -60,8 +60,10 @@ class SendInlineBotResult(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent inline result message is returned.
|
:obj:`Message`: On success, the sent inline result message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_inline_bot_result(chat_id, query_id, result_id)
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SendInlineBotResult(
|
functions.messages.SendInlineBotResult(
|
||||||
|
@ -66,8 +66,14 @@ class SetGameScore(BaseClient):
|
|||||||
:obj:`Message` | ``bool``: On success, if the message was sent by the bot, the edited message is returned,
|
:obj:`Message` | ``bool``: On success, if the message was sent by the bot, the edited message is returned,
|
||||||
True otherwise.
|
True otherwise.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Set new score
|
||||||
|
app.set_game_score(user_id, 1000)
|
||||||
|
|
||||||
|
# Force set new score
|
||||||
|
app.set_game_score(user_id, 25, force=True)
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SetGameScore(
|
functions.messages.SetGameScore(
|
||||||
|
@ -16,8 +16,14 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_chat_members import AddChatMembers
|
||||||
from .archive_chats import ArchiveChats
|
from .archive_chats import ArchiveChats
|
||||||
|
from .create_channel import CreateChannel
|
||||||
|
from .create_group import CreateGroup
|
||||||
|
from .create_supergroup import CreateSupergroup
|
||||||
|
from .delete_channel import DeleteChannel
|
||||||
from .delete_chat_photo import DeleteChatPhoto
|
from .delete_chat_photo import DeleteChatPhoto
|
||||||
|
from .delete_supergroup import DeleteSupergroup
|
||||||
from .export_chat_invite_link import ExportChatInviteLink
|
from .export_chat_invite_link import ExportChatInviteLink
|
||||||
from .get_chat import GetChat
|
from .get_chat import GetChat
|
||||||
from .get_chat_member import GetChatMember
|
from .get_chat_member import GetChatMember
|
||||||
@ -32,9 +38,9 @@ from .kick_chat_member import KickChatMember
|
|||||||
from .leave_chat import LeaveChat
|
from .leave_chat import LeaveChat
|
||||||
from .pin_chat_message import PinChatMessage
|
from .pin_chat_message import PinChatMessage
|
||||||
from .promote_chat_member import PromoteChatMember
|
from .promote_chat_member import PromoteChatMember
|
||||||
from .restrict_chat import RestrictChat
|
|
||||||
from .restrict_chat_member import RestrictChatMember
|
from .restrict_chat_member import RestrictChatMember
|
||||||
from .set_chat_description import SetChatDescription
|
from .set_chat_description import SetChatDescription
|
||||||
|
from .set_chat_permissions import SetChatPermissions
|
||||||
from .set_chat_photo import SetChatPhoto
|
from .set_chat_photo import SetChatPhoto
|
||||||
from .set_chat_title import SetChatTitle
|
from .set_chat_title import SetChatTitle
|
||||||
from .unarchive_chats import UnarchiveChats
|
from .unarchive_chats import UnarchiveChats
|
||||||
@ -65,9 +71,15 @@ class Chats(
|
|||||||
IterDialogs,
|
IterDialogs,
|
||||||
IterChatMembers,
|
IterChatMembers,
|
||||||
UpdateChatUsername,
|
UpdateChatUsername,
|
||||||
RestrictChat,
|
SetChatPermissions,
|
||||||
GetDialogsCount,
|
GetDialogsCount,
|
||||||
ArchiveChats,
|
ArchiveChats,
|
||||||
UnarchiveChats
|
UnarchiveChats,
|
||||||
|
CreateGroup,
|
||||||
|
CreateSupergroup,
|
||||||
|
CreateChannel,
|
||||||
|
AddChatMembers,
|
||||||
|
DeleteChannel,
|
||||||
|
DeleteSupergroup
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
88
pyrogram/client/methods/chats/add_chat_members.py
Normal file
88
pyrogram/client/methods/chats/add_chat_members.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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, List
|
||||||
|
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class AddChatMembers(BaseClient):
|
||||||
|
def add_chat_members(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
user_ids: Union[Union[int, str], List[Union[int, str]]],
|
||||||
|
forward_limit: int = 100
|
||||||
|
) -> bool:
|
||||||
|
"""Add new chat members to a group, supergroup or channel
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
The group, supergroup or channel id
|
||||||
|
|
||||||
|
user_ids (``int`` | ``str`` | List of ``int`` or ``str``):
|
||||||
|
Users to add in the chat
|
||||||
|
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.
|
||||||
|
|
||||||
|
forward_limit (``int``, *optional*):
|
||||||
|
How many of the latest messages you want to forward to the new members. Pass 0 to forward none of them.
|
||||||
|
Only applicable to basic groups (the argument is ignored for supergroups or channels).
|
||||||
|
Defaults to 100 (max amount).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Add one member to a group or channel
|
||||||
|
app.add_chat_members(chat_id, user_id)
|
||||||
|
|
||||||
|
# Add multiple members to a group or channel
|
||||||
|
app.add_chat_members(chat_id, [user_id1, user_id2, user_id3])
|
||||||
|
|
||||||
|
# Change forward_limit (for basic groups only)
|
||||||
|
app.add_chat_members(chat_id, user_id, forward_limit=25)
|
||||||
|
"""
|
||||||
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
if not isinstance(user_ids, list):
|
||||||
|
user_ids = [user_ids]
|
||||||
|
|
||||||
|
if isinstance(peer, types.InputPeerChat):
|
||||||
|
for user_id in user_ids:
|
||||||
|
self.send(
|
||||||
|
functions.messages.AddChatUser(
|
||||||
|
chat_id=peer.chat_id,
|
||||||
|
user_id=self.resolve_peer(user_id),
|
||||||
|
fwd_limit=forward_limit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.send(
|
||||||
|
functions.channels.InviteToChannel(
|
||||||
|
channel=peer,
|
||||||
|
users=[
|
||||||
|
self.resolve_peer(user_id)
|
||||||
|
for user_id in user_ids
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -37,8 +37,14 @@ class ArchiveChats(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Archive chat
|
||||||
|
app.archive_chats(chat_id)
|
||||||
|
|
||||||
|
# Archive multiple chats at once
|
||||||
|
app.archive_chats([chat_id1, chat_id2, chat_id3])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(chat_ids, list):
|
if not isinstance(chat_ids, list):
|
||||||
|
55
pyrogram/client/methods/chats/create_channel.py
Normal file
55
pyrogram/client/methods/chats/create_channel.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateChannel(BaseClient):
|
||||||
|
def create_channel(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
description: str = ""
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new broadcast channel.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The channel title.
|
||||||
|
|
||||||
|
description (``str``, *optional*):
|
||||||
|
The channel description.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_channel("Channel Title", "Channel Description")
|
||||||
|
"""
|
||||||
|
r = self.send(
|
||||||
|
functions.channels.CreateChannel(
|
||||||
|
title=title,
|
||||||
|
about=description,
|
||||||
|
broadcast=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
65
pyrogram/client/methods/chats/create_group.py
Normal file
65
pyrogram/client/methods/chats/create_group.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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, List
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateGroup(BaseClient):
|
||||||
|
def create_group(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
users: Union[Union[int, str], List[Union[int, str]]]
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new basic group.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you want to create a new supergroup, use :meth:`~pyrogram.Client.create_supergroup` instead.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The group title.
|
||||||
|
|
||||||
|
users (``int`` | ``str`` | List of ``int`` or ``str``):
|
||||||
|
Users to create a chat with.
|
||||||
|
You must pass at least one user using their IDs (int), usernames (str) or phone numbers (str).
|
||||||
|
Multiple users can be invited by passing a list of IDs, usernames or phone numbers.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_group("Group Title", user_id)
|
||||||
|
"""
|
||||||
|
if not isinstance(users, list):
|
||||||
|
users = [users]
|
||||||
|
|
||||||
|
r = self.send(
|
||||||
|
functions.messages.CreateChat(
|
||||||
|
title=title,
|
||||||
|
users=[self.resolve_peer(u) for u in users]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
59
pyrogram/client/methods/chats/create_supergroup.py
Normal file
59
pyrogram/client/methods/chats/create_supergroup.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateSupergroup(BaseClient):
|
||||||
|
def create_supergroup(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
description: str = ""
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new supergroup.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you want to create a new basic group, use :meth:`~pyrogram.Client.create_group` instead.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The supergroup title.
|
||||||
|
|
||||||
|
description (``str``, *optional*):
|
||||||
|
The supergroup description.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_supergroup("Supergroup Title", "Supergroup Description")
|
||||||
|
"""
|
||||||
|
r = self.send(
|
||||||
|
functions.channels.CreateChannel(
|
||||||
|
title=title,
|
||||||
|
about=description,
|
||||||
|
megagroup=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
48
pyrogram/client/methods/chats/delete_channel.py
Normal file
48
pyrogram/client/methods/chats/delete_channel.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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
|
||||||
|
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteChannel(BaseClient):
|
||||||
|
def delete_channel(self, chat_id: Union[int, str]) -> bool:
|
||||||
|
"""Delete a channel.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
The id of the channel to be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_channel(channel_id)
|
||||||
|
"""
|
||||||
|
self.send(
|
||||||
|
functions.channels.DeleteChannel(
|
||||||
|
channel=self.resolve_peer(chat_id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -28,12 +28,8 @@ class DeleteChatPhoto(BaseClient):
|
|||||||
chat_id: Union[int, str]
|
chat_id: Union[int, str]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Delete a chat photo.
|
"""Delete a chat photo.
|
||||||
Photos can't be changed for private chats.
|
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
|
||||||
|
|
||||||
Note:
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
|
|
||||||
setting is off.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -43,8 +39,12 @@ class DeleteChatPhoto(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: if a chat_id belongs to user.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_chat_photo(chat_id)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
48
pyrogram/client/methods/chats/delete_supergroup.py
Normal file
48
pyrogram/client/methods/chats/delete_supergroup.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <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
|
||||||
|
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteSupergroup(BaseClient):
|
||||||
|
def delete_supergroup(self, chat_id: Union[int, str]) -> bool:
|
||||||
|
"""Delete a supergroup.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
The id of the supergroup to be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_supergroup(supergroup_id)
|
||||||
|
"""
|
||||||
|
self.send(
|
||||||
|
functions.channels.DeleteChannel(
|
||||||
|
channel=self.resolve_peer(chat_id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -47,19 +47,21 @@ class ExportChatInviteLink(BaseClient):
|
|||||||
``str``: On success, the exported invite link is returned.
|
``str``: On success, the exported invite link is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: In case the chat_id belongs to a user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
link = app.export_chat_invite_link(chat_id)
|
||||||
|
print(link)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if isinstance(peer, types.InputPeerChat):
|
if isinstance(peer, (types.InputPeerChat, types.InputPeerChannel)):
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.ExportChatInvite(
|
functions.messages.ExportChatInvite(
|
||||||
peer=peer
|
peer=peer
|
||||||
)
|
)
|
||||||
).link
|
).link
|
||||||
elif isinstance(peer, types.InputPeerChannel):
|
else:
|
||||||
return self.send(
|
raise ValueError('The chat_id "{}" belongs to a user'.format(chat_id))
|
||||||
functions.channels.ExportInvite(
|
|
||||||
channel=peer
|
|
||||||
)
|
|
||||||
).link
|
|
||||||
|
@ -20,7 +20,7 @@ from typing import Union
|
|||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
|
|
||||||
class GetChat(BaseClient):
|
class GetChat(BaseClient):
|
||||||
@ -44,8 +44,13 @@ class GetChat(BaseClient):
|
|||||||
otherwise, a chat preview object is returned.
|
otherwise, a chat preview object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case the chat invite link points to a chat you haven't joined yet.
|
ValueError: In case the chat invite link points to a chat you haven't joined yet.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
chat = app.get_chat("pyrogram")
|
||||||
|
print(chat)
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(str(chat_id))
|
match = self.INVITE_LINK_RE.match(str(chat_id))
|
||||||
|
|
||||||
@ -65,7 +70,7 @@ class GetChat(BaseClient):
|
|||||||
chat_id = -r.chat.id
|
chat_id = -r.chat.id
|
||||||
|
|
||||||
if isinstance(r.chat, types.Channel):
|
if isinstance(r.chat, types.Channel):
|
||||||
chat_id = int("-100" + str(r.chat.id))
|
chat_id = utils.get_channel_id(r.chat.id)
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -44,8 +44,11 @@ class GetChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`ChatMember`: On success, a chat member is returned.
|
:obj:`ChatMember`: On success, a chat member is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
dan = app.get_chat_member("pyrogramchat", "haskell")
|
||||||
|
print(dan)
|
||||||
"""
|
"""
|
||||||
chat = self.resolve_peer(chat_id)
|
chat = self.resolve_peer(chat_id)
|
||||||
user = self.resolve_peer(user_id)
|
user = self.resolve_peer(user_id)
|
||||||
|
@ -91,8 +91,19 @@ class GetChatMembers(BaseClient):
|
|||||||
List of :obj:`ChatMember`: On success, a list of chat members is returned.
|
List of :obj:`ChatMember`: On success, a list of chat members is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case you used an invalid filter or a chat id that belongs to a user.
|
ValueError: In case you used an invalid filter or a chat id that belongs to a user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get first 200 recent members
|
||||||
|
app.get_chat_members("pyrogramchat")
|
||||||
|
|
||||||
|
# Get all administrators
|
||||||
|
app.get_chat_members("pyrogramchat", filter="administrators")
|
||||||
|
|
||||||
|
# Get all bots
|
||||||
|
app.get_chat_members("pyrogramchat", filter="bots")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -37,8 +37,13 @@ class GetChatMembersCount(BaseClient):
|
|||||||
``int``: On success, the chat members count is returned.
|
``int``: On success, the chat members count is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to user.
|
ValueError: In case a chat id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_chat_members_count("pyrogramchat")
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ from typing import List
|
|||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FloodWait
|
from pyrogram.errors import FloodWait
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -56,8 +56,14 @@ class GetDialogs(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`Dialog`: On success, a list of dialogs is returned.
|
List of :obj:`Dialog`: On success, a list of dialogs is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get first 100 dialogs
|
||||||
|
app.get_dialogs()
|
||||||
|
|
||||||
|
# Get pinned dialogs
|
||||||
|
app.get_dialogs(pinned_only=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -94,10 +100,8 @@ class GetDialogs(BaseClient):
|
|||||||
chat_id = to_id.user_id
|
chat_id = to_id.user_id
|
||||||
else:
|
else:
|
||||||
chat_id = message.from_id
|
chat_id = message.from_id
|
||||||
elif isinstance(to_id, types.PeerChat):
|
|
||||||
chat_id = -to_id.chat_id
|
|
||||||
else:
|
else:
|
||||||
chat_id = int("-100" + str(to_id.channel_id))
|
chat_id = utils.get_peer_id(to_id)
|
||||||
|
|
||||||
messages[chat_id] = pyrogram.Message._parse(self, message, users, chats)
|
messages[chat_id] = pyrogram.Message._parse(self, message, users, chats)
|
||||||
|
|
||||||
|
@ -31,8 +31,11 @@ class GetDialogsCount(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``int``: On success, the dialogs count is returned.
|
``int``: On success, the dialogs count is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_dialogs_count()
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if pinned_only:
|
if pinned_only:
|
||||||
|
@ -77,8 +77,20 @@ class IterChatMembers(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``Generator``: A generator yielding :obj:`ChatMember` objects.
|
``Generator``: A generator yielding :obj:`ChatMember` objects.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Iterate though all chat members
|
||||||
|
for member in app.iter_chat_members("pyrogramchat"):
|
||||||
|
print(member.user.first_name)
|
||||||
|
|
||||||
|
# Iterate though all administrators
|
||||||
|
for member in app.iter_chat_members("pyrogramchat", filter="administrators"):
|
||||||
|
print(member.user.first_name)
|
||||||
|
|
||||||
|
# Iterate though all bots
|
||||||
|
for member in app.iter_chat_members("pyrogramchat", filter="bots"):
|
||||||
|
print(member.user.first_name)
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
yielded = set()
|
yielded = set()
|
||||||
|
@ -46,8 +46,12 @@ class IterDialogs(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``Generator``: A generator yielding :obj:`Dialog` objects.
|
``Generator``: A generator yielding :obj:`Dialog` objects.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Iterate through all dialogs
|
||||||
|
for dialog in app.iter_dialogs():
|
||||||
|
print(dialog.chat.first_name or dialog.chat.title)
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
total = limit or (1 << 31) - 1
|
total = limit or (1 << 31) - 1
|
||||||
|
@ -36,8 +36,14 @@ class JoinChat(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Join chat via username
|
||||||
|
app.join_chat("pyrogram")
|
||||||
|
|
||||||
|
# Join chat via invite link
|
||||||
|
app.join_chat("https://t.me/joinchat/AAAAAE0QmSW3IUmm3UFR7A")
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(chat_id)
|
match = self.INVITE_LINK_RE.match(chat_id)
|
||||||
|
|
||||||
|
@ -57,8 +57,16 @@ class KickChatMember(BaseClient):
|
|||||||
:obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
|
:obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
|
||||||
case a message object couldn't be returned, True is returned.
|
case a message object couldn't be returned, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
# Ban chat member forever
|
||||||
|
app.kick_chat_member(chat_id, user_id)
|
||||||
|
|
||||||
|
# Kick chat member and automatically unban after 24h
|
||||||
|
app.kick_chat_member(chat_id, user_id, int(time.time() + 86400))
|
||||||
"""
|
"""
|
||||||
chat_peer = self.resolve_peer(chat_id)
|
chat_peer = self.resolve_peer(chat_id)
|
||||||
user_peer = self.resolve_peer(user_id)
|
user_peer = self.resolve_peer(user_id)
|
||||||
|
@ -37,9 +37,16 @@ class LeaveChat(BaseClient):
|
|||||||
|
|
||||||
delete (``bool``, *optional*):
|
delete (``bool``, *optional*):
|
||||||
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
||||||
|
Defaults to False.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Leave chat or channel
|
||||||
|
app.leave_chat(chat_id)
|
||||||
|
|
||||||
|
# Leave basic chat and also delete the dialog
|
||||||
|
app.leave_chat(chat_id, delete=True)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -47,8 +47,14 @@ class PinChatMessage(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Pin with notification
|
||||||
|
app.pin_chat_message(chat_id, message_id)
|
||||||
|
|
||||||
|
# Pin without notification
|
||||||
|
app.pin_chat_message(chat_id, message_id, disable_notification=True)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
|
@ -78,8 +78,11 @@ class PromoteChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Promote chat member to supergroup admin
|
||||||
|
app.promote_chat_member(chat_id, user_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditAdmin(
|
functions.channels.EditAdmin(
|
||||||
|
@ -20,7 +20,7 @@ from typing import Union
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
from ...types.user_and_chats import Chat
|
from ...types.user_and_chats import Chat, ChatPermissions
|
||||||
|
|
||||||
|
|
||||||
class RestrictChatMember(BaseClient):
|
class RestrictChatMember(BaseClient):
|
||||||
@ -28,20 +28,13 @@ class RestrictChatMember(BaseClient):
|
|||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
until_date: int = 0,
|
permissions: ChatPermissions,
|
||||||
can_send_messages: bool = False,
|
until_date: int = 0
|
||||||
can_send_media_messages: bool = False,
|
|
||||||
can_send_other_messages: bool = False,
|
|
||||||
can_add_web_page_previews: bool = False,
|
|
||||||
can_send_polls: bool = False,
|
|
||||||
can_change_info: bool = False,
|
|
||||||
can_invite_users: bool = False,
|
|
||||||
can_pin_messages: bool = False
|
|
||||||
) -> Chat:
|
) -> Chat:
|
||||||
"""Restrict a user in a supergroup.
|
"""Restrict a user in a supergroup.
|
||||||
|
|
||||||
The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
|
You must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
|
||||||
Pass True for all boolean parameters to lift restrictions from a user.
|
Pass True for all permissions to lift restrictions from a user.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -51,42 +44,32 @@ class RestrictChatMember(BaseClient):
|
|||||||
Unique identifier (int) or username (str) of the target user.
|
Unique identifier (int) or username (str) of the target user.
|
||||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
|
permissions (:obj:`ChatPermissions`):
|
||||||
|
New user permissions.
|
||||||
|
|
||||||
until_date (``int``, *optional*):
|
until_date (``int``, *optional*):
|
||||||
Date when the user will be unbanned, unix time.
|
Date when the user will be unbanned, unix time.
|
||||||
If user is banned for more than 366 days or less than 30 seconds from the current time they are
|
If user is banned for more than 366 days or less than 30 seconds from the current time they are
|
||||||
considered to be banned forever. Defaults to 0 (ban forever).
|
considered to be banned forever. Defaults to 0 (ban forever).
|
||||||
|
|
||||||
can_send_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send text messages, contacts, locations and venues.
|
|
||||||
|
|
||||||
can_send_media_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send audios, documents, photos, videos, video notes and voice notes,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_other_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send animations, games, stickers and use inline bots,
|
|
||||||
implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_add_web_page_previews (``bool``, *optional*):
|
|
||||||
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_send_polls (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send polls, implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_change_info (``bool``, *optional*):
|
|
||||||
Pass True, if the user can change the chat title, photo and other settings.
|
|
||||||
|
|
||||||
can_invite_users (``bool``, *optional*):
|
|
||||||
Pass True, if the user can invite new users to the chat.
|
|
||||||
|
|
||||||
can_pin_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can pin messages.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
from pyrogram import ChatPermissions
|
||||||
|
|
||||||
|
# Completely restrict chat member (mute) forever
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions())
|
||||||
|
|
||||||
|
# Chat member muted for 24h
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions(), int(time.time() + 86400))
|
||||||
|
|
||||||
|
# Chat member can only send text messages
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions(can_send_messages=True))
|
||||||
"""
|
"""
|
||||||
send_messages = True
|
send_messages = True
|
||||||
send_media = True
|
send_media = True
|
||||||
@ -100,37 +83,35 @@ class RestrictChatMember(BaseClient):
|
|||||||
invite_users = True
|
invite_users = True
|
||||||
pin_messages = True
|
pin_messages = True
|
||||||
|
|
||||||
if can_send_messages:
|
if permissions.can_send_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
|
|
||||||
if can_send_media_messages:
|
if permissions.can_send_media_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
|
|
||||||
if can_send_other_messages:
|
if permissions.can_send_other_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
|
||||||
send_stickers = None
|
send_stickers = None
|
||||||
send_gifs = None
|
send_gifs = None
|
||||||
send_games = None
|
send_games = None
|
||||||
send_inline = None
|
send_inline = None
|
||||||
|
|
||||||
if can_add_web_page_previews:
|
if permissions.can_add_web_page_previews:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
|
||||||
embed_links = None
|
embed_links = None
|
||||||
|
|
||||||
if can_send_polls:
|
if permissions.can_send_polls:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_polls = None
|
send_polls = None
|
||||||
|
|
||||||
if can_change_info:
|
if permissions.can_change_info:
|
||||||
change_info = None
|
change_info = None
|
||||||
|
|
||||||
if can_invite_users:
|
if permissions.can_invite_users:
|
||||||
invite_users = None
|
invite_users = None
|
||||||
|
|
||||||
if can_pin_messages:
|
if permissions.can_pin_messages:
|
||||||
pin_messages = None
|
pin_messages = None
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -42,8 +42,12 @@ class SetChatDescription(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: if a chat_id doesn't belong to a supergroup or a channel.
|
||||||
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.set_chat_description(chat_id, "New Description")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -20,60 +20,47 @@ from typing import Union
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
from ...types.user_and_chats import Chat
|
from ...types.user_and_chats import Chat, ChatPermissions
|
||||||
|
|
||||||
|
|
||||||
class RestrictChat(BaseClient):
|
class SetChatPermissions(BaseClient):
|
||||||
def restrict_chat(
|
def set_chat_permissions(
|
||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
can_send_messages: bool = False,
|
permissions: ChatPermissions,
|
||||||
can_send_media_messages: bool = False,
|
|
||||||
can_send_other_messages: bool = False,
|
|
||||||
can_add_web_page_previews: bool = False,
|
|
||||||
can_send_polls: bool = False,
|
|
||||||
can_change_info: bool = False,
|
|
||||||
can_invite_users: bool = False,
|
|
||||||
can_pin_messages: bool = False
|
|
||||||
) -> Chat:
|
) -> Chat:
|
||||||
"""Restrict a chat.
|
"""Set default chat permissions for all members.
|
||||||
Pass True for all boolean parameters to lift restrictions from a chat.
|
|
||||||
|
You must be an administrator in the group or a supergroup for this to work and must have the
|
||||||
|
*can_restrict_members* admin rights.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
can_send_messages (``bool``, *optional*):
|
permissions (:obj:`ChatPermissions`):
|
||||||
Pass True, if the user can send text messages, contacts, locations and venues.
|
New default chat permissions.
|
||||||
|
|
||||||
can_send_media_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send audios, documents, photos, videos, video notes and voice notes,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_other_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send animations, games, stickers and use inline bots,
|
|
||||||
implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_add_web_page_previews (``bool``, *optional*):
|
|
||||||
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_send_polls (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send polls, implies can_send_media_messages.
|
|
||||||
|
|
||||||
can_change_info (``bool``, *optional*):
|
|
||||||
Pass True, if the user can change the chat title, photo and other settings.
|
|
||||||
|
|
||||||
can_invite_users (``bool``, *optional*):
|
|
||||||
Pass True, if the user can invite new users to the chat.
|
|
||||||
|
|
||||||
can_pin_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can pin messages.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import ChatPermissions
|
||||||
|
|
||||||
|
# Completely restrict chat
|
||||||
|
app.set_chat_permissions(chat_id, ChatPermissions())
|
||||||
|
|
||||||
|
# Chat members can only send text messages, media, stickers and GIFs
|
||||||
|
app.set_chat_permissions(
|
||||||
|
chat_id,
|
||||||
|
ChatPermissions(
|
||||||
|
can_send_messages=True,
|
||||||
|
can_send_media_messages=True,
|
||||||
|
can_send_other_messages=True
|
||||||
|
)
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
send_messages = True
|
send_messages = True
|
||||||
send_media = True
|
send_media = True
|
||||||
@ -87,37 +74,35 @@ class RestrictChat(BaseClient):
|
|||||||
invite_users = True
|
invite_users = True
|
||||||
pin_messages = True
|
pin_messages = True
|
||||||
|
|
||||||
if can_send_messages:
|
if permissions.can_send_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
|
|
||||||
if can_send_media_messages:
|
if permissions.can_send_media_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
|
|
||||||
if can_send_other_messages:
|
if permissions.can_send_other_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
|
||||||
send_stickers = None
|
send_stickers = None
|
||||||
send_gifs = None
|
send_gifs = None
|
||||||
send_games = None
|
send_games = None
|
||||||
send_inline = None
|
send_inline = None
|
||||||
|
|
||||||
if can_add_web_page_previews:
|
if permissions.can_add_web_page_previews:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
|
||||||
embed_links = None
|
embed_links = None
|
||||||
|
|
||||||
if can_send_polls:
|
if permissions.can_send_polls:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_polls = None
|
send_polls = None
|
||||||
|
|
||||||
if can_change_info:
|
if permissions.can_change_info:
|
||||||
change_info = None
|
change_info = None
|
||||||
|
|
||||||
if can_invite_users:
|
if permissions.can_invite_users:
|
||||||
invite_users = None
|
invite_users = None
|
||||||
|
|
||||||
if can_pin_messages:
|
if permissions.can_pin_messages:
|
||||||
pin_messages = None
|
pin_messages = None
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
@ -17,12 +17,11 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from base64 import b64decode
|
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
|
|
||||||
class SetChatPhoto(BaseClient):
|
class SetChatPhoto(BaseClient):
|
||||||
@ -32,38 +31,43 @@ class SetChatPhoto(BaseClient):
|
|||||||
photo: str
|
photo: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Set a new profile photo for the chat.
|
"""Set a new profile photo for the chat.
|
||||||
Photos can't be changed for private chats.
|
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
|
||||||
|
|
||||||
Note:
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
|
|
||||||
setting is off.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
photo (``str``):
|
photo (``str``):
|
||||||
New chat photo. You can pass a :obj:`Photo` id or a file path to upload a new photo.
|
New chat photo. You can pass a :obj:`Photo` file_id or a file path to upload a new photo from your local
|
||||||
|
machine.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: if a chat_id belongs to user.
|
ValueError: if a chat_id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Set chat photo using a local file
|
||||||
|
app.set_chat_photo(chat_id, "photo.jpg")
|
||||||
|
|
||||||
|
# Set chat photo using an exiting Photo file_id
|
||||||
|
app.set_chat_photo(chat_id, photo.file_id)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if os.path.exists(photo):
|
if os.path.exists(photo):
|
||||||
photo = types.InputChatUploadedPhoto(file=self.save_file(photo))
|
photo = types.InputChatUploadedPhoto(file=self.save_file(photo))
|
||||||
else:
|
else:
|
||||||
s = unpack("<qq", b64decode(photo + "=" * (-len(photo) % 4), "-_"))
|
unpacked = unpack("<iiqqc", utils.decode(photo))
|
||||||
|
|
||||||
photo = types.InputChatPhoto(
|
photo = types.InputChatPhoto(
|
||||||
id=types.InputPhoto(
|
id=types.InputPhoto(
|
||||||
id=s[0],
|
id=unpacked[2],
|
||||||
access_hash=s[1],
|
access_hash=unpacked[3],
|
||||||
file_reference=b""
|
file_reference=b""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -47,8 +47,12 @@ class SetChatTitle(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to user.
|
ValueError: In case a chat id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.set_chat_title(chat_id, "New Title")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -37,8 +37,14 @@ class UnarchiveChats(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Unarchive chat
|
||||||
|
app.unarchive_chats(chat_id)
|
||||||
|
|
||||||
|
# Unarchive multiple chats at once
|
||||||
|
app.unarchive_chats([chat_id1, chat_id2, chat_id3])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(chat_ids, list):
|
if not isinstance(chat_ids, list):
|
||||||
|
@ -43,8 +43,11 @@ class UnbanChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Unban chat member right now
|
||||||
|
app.unban_chat_member(chat_id, user_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditBanned(
|
functions.channels.EditBanned(
|
||||||
|
@ -38,8 +38,10 @@ class UnpinChatMessage(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.unpin_chat_message(chat_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
|
@ -42,8 +42,12 @@ class UpdateChatUsername(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to a user or chat.
|
ValueError: In case a chat id belongs to a user or chat.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.update_chat_username(chat_id, "new_username")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -37,8 +37,15 @@ class AddContacts(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`types.contacts.ImportedContacts`
|
:obj:`types.contacts.ImportedContacts`
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InputPhoneContact
|
||||||
|
|
||||||
|
app.add_contacts([
|
||||||
|
InputPhoneContact("39123456789", "Foo"),
|
||||||
|
InputPhoneContact("38987654321", "Bar"),
|
||||||
|
InputPhoneContact("01234567891", "Baz")])
|
||||||
"""
|
"""
|
||||||
imported_contacts = self.send(
|
imported_contacts = self.send(
|
||||||
functions.contacts.ImportContacts(
|
functions.contacts.ImportContacts(
|
||||||
|
@ -38,8 +38,10 @@ class DeleteContacts(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_contacts([user_id1, user_id2, user_id3])
|
||||||
"""
|
"""
|
||||||
contacts = []
|
contacts = []
|
||||||
|
|
||||||
|
@ -30,14 +30,16 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class GetContacts(BaseClient):
|
class GetContacts(BaseClient):
|
||||||
def get_contacts(self) -> List["pyrogram.User"]:
|
def get_contacts(self) -> List["pyrogram.User"]:
|
||||||
# TODO: Create a Users object and return that
|
|
||||||
"""Get contacts from your Telegram address book.
|
"""Get contacts from your Telegram address book.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of :obj:`User`: On success, a list of users is returned.
|
List of :obj:`User`: On success, a list of users is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
contacts = app.get_contacts()
|
||||||
|
print(contacts)
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@ -46,5 +48,4 @@ class GetContacts(BaseClient):
|
|||||||
log.warning("get_contacts flood: waiting {} seconds".format(e.x))
|
log.warning("get_contacts flood: waiting {} seconds".format(e.x))
|
||||||
time.sleep(e.x)
|
time.sleep(e.x)
|
||||||
else:
|
else:
|
||||||
log.info("Total contacts: {}".format(len(self.peers_by_phone)))
|
|
||||||
return pyrogram.List(pyrogram.User._parse(self, user) for user in contacts.users)
|
return pyrogram.List(pyrogram.User._parse(self, user) for user in contacts.users)
|
||||||
|
@ -27,8 +27,11 @@ class GetContactsCount(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``int``: On success, the contacts count is returned.
|
``int``: On success, the contacts count is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_contacts_count()
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return len(self.send(functions.contacts.GetContacts(hash=0)).contacts)
|
return len(self.send(functions.contacts.GetContacts(hash=0)).contacts)
|
||||||
|
@ -16,11 +16,10 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Callable
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.client.filters.filter import Filter
|
from pyrogram.client.filters.filter import Filter
|
||||||
from pyrogram.client.handlers.handler import Handler
|
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
@ -44,18 +43,15 @@ class OnCallbackQuery(BaseClient):
|
|||||||
The group identifier, defaults to 0.
|
The group identifier, defaults to 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func: callable) -> Tuple[Handler, int]:
|
def decorator(func: Callable) -> Callable:
|
||||||
if isinstance(func, tuple):
|
if isinstance(self, pyrogram.Client):
|
||||||
func = func[0].callback
|
self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
|
||||||
|
elif isinstance(self, Filter) or self is None:
|
||||||
|
func.handler = (
|
||||||
|
pyrogram.CallbackQueryHandler(func, self),
|
||||||
|
group if filters is None else filters
|
||||||
|
)
|
||||||
|
|
||||||
handler = pyrogram.CallbackQueryHandler(func, filters)
|
return func
|
||||||
|
|
||||||
if isinstance(self, Filter):
|
|
||||||
return pyrogram.CallbackQueryHandler(func, self), group if filters is None else filters
|
|
||||||
|
|
||||||
if self is not None:
|
|
||||||
self.add_handler(handler, group)
|
|
||||||
|
|
||||||
return handler, group
|
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -16,11 +16,10 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Callable
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.client.filters.filter import Filter
|
from pyrogram.client.filters.filter import Filter
|
||||||
from pyrogram.client.handlers.handler import Handler
|
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
@ -44,18 +43,15 @@ class OnDeletedMessages(BaseClient):
|
|||||||
The group identifier, defaults to 0.
|
The group identifier, defaults to 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func: callable) -> Tuple[Handler, int]:
|
def decorator(func: Callable) -> Callable:
|
||||||
if isinstance(func, tuple):
|
if isinstance(self, pyrogram.Client):
|
||||||
func = func[0].callback
|
self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group)
|
||||||
|
elif isinstance(self, Filter) or self is None:
|
||||||
|
func.handler = (
|
||||||
|
pyrogram.DeletedMessagesHandler(func, self),
|
||||||
|
group if filters is None else filters
|
||||||
|
)
|
||||||
|
|
||||||
handler = pyrogram.DeletedMessagesHandler(func, filters)
|
return func
|
||||||
|
|
||||||
if isinstance(self, Filter):
|
|
||||||
return pyrogram.DeletedMessagesHandler(func, self), group if filters is None else filters
|
|
||||||
|
|
||||||
if self is not None:
|
|
||||||
self.add_handler(handler, group)
|
|
||||||
|
|
||||||
return handler, group
|
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user