Compare commits

...

20 commits

Author SHA1 Message Date
wulan17
c09057c6f4
pyrofork: Update API schema to Layer 200
Some checks failed
Build-docs / build (push) Has been cancelled
Pyrofork / build (macos-latest, 3.10) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.11) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.12) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.13) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.9) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.10) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.11) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.12) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.13) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.9) (push) Has been cancelled
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 21:42:11 +07:00
wulan17
0a8ae63294
pyrofork: disable publish workflows
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 21:26:21 +07:00
wulan17
8074557922
pyrofork: Bump version to 2.3.59
Some checks failed
Pyrofork / build (macos-latest, 3.10) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.11) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.12) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.13) (push) Has been cancelled
Pyrofork / build (macos-latest, 3.9) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.10) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.11) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.12) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.13) (push) Has been cancelled
Pyrofork / build (ubuntu-latest, 3.9) (push) Has been cancelled
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:53:11 +07:00
wulan17
7562d04596
pyrofork: docs: text-formatting: Add missings text format
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:10 +07:00
wulan17
149dd4a708
pyrofork: docs: text-formatting: Move up HTML section
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:10 +07:00
wulan17
4926eda4c5
pyrofork: docs: Add warning regarding markdown text formatting
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:10 +07:00
wulan17
c4b587b493
pyrofork: parser: markdown: Check if PRE is inside blockquote before unparsing it
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:09 +07:00
wulan17
1108c52f53
pyrofork: Add support for custom emoji in markdown unparser
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:09 +07:00
wulan17
fc84041397
pyrofork: Add offset_{date,id,topic} parameters to get_forum_topics method
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:09 +07:00
wulan17
71c39b8e6f
pyrofork: Add support for multi-line blockquote in markdown unparser
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:09 +07:00
wulan17
bec31032cc
pyrofork: Adapt markdown unparser from telethon
* The problem with current implementation is when we have nested markdown inside a url the markdown order is messed up.
for example link with bold text will be unparsed like this [**github](https://github.com**).

Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:08 +07:00
wulan17
5c9470fd4f
pyrofork: Fix nested url markdown parsing
* The problem with current implepementation is when we add another markdown inside an url markdown will not be parsed.
for example we add bold (**) markdown inside an url markdown, the url text show as `**text**` instead of making the text bold.

Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:08 +07:00
KurimuzonAkuma
13681302a0
Pyrofork: Add delete_chat_history method
Signed-off-by: Yasir Aris <git@yasir.id>
2025-03-08 20:52:08 +07:00
Yasir Aris M
c31d41e3d3
Pyrofork: Fix video cover
Signed-off-by: Yasir Aris <git@yasir.id>
2025-03-08 20:52:07 +07:00
Yasir Aris M
8528eea303
Pyrofork: Fix get_chat_gifts_count description
Signed-off-by: Yasir Aris <git@yasir.id>
2025-03-08 20:52:07 +07:00
Yasir Aris M
39cd79794e
Pyrofork: Update get_chat_gifts description
Signed-off-by: Yasir Aris <git@yasir.id>
2025-03-08 20:52:07 +07:00
KurimuzonAkuma
ea8ff2806f
Pyrofork: Add message.content property
Signed-off-by: Yasir Aris <git@yasir.id>
2025-03-08 20:52:07 +07:00
wulan17
e33a9d95df
pyrofork: Update API schema to Layer 199
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:06 +07:00
wulan17
ee3e9002fc
pyrofork: Add get_chat_forum_topics_count method
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:52:06 +07:00
wulan17
4e200e2a5d
pyrofork: Add ForumTopicDeleted
Signed-off-by: wulan17 <wulan17@nusantararom.org>
2025-03-08 20:51:58 +07:00
20 changed files with 577 additions and 234 deletions

View file

@ -1,40 +0,0 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Upload Python Package
on:
push:
tags:
- '*'
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e '.[dev]'
- name: Build package
run: hatch build
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1

View file

@ -93,7 +93,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
user#4b46c37e flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long = User;
user#20b1422 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
@ -108,11 +108,11 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
channel#e00998b7 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long = Chat;
channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true paid_messages_available:flags2.20?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -125,7 +125,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#96fdbbe9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int = Message;
message#eabcdd4d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long = Message;
messageService#d3d28540 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true reactions_are_possible:flags.9?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction reactions:flags.20?MessageReactions ttl_period:flags.25?int = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@ -184,7 +184,7 @@ messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags
messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
messageActionRequestedPeer#31518e9b button_id:int peers:Vector<Peer> = MessageAction;
messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction;
messageActionGiftCode#56d03994 flags:# via_giveaway:flags.0?true unclaimed:flags.2?true boost_peer:flags.1?Peer months:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long message:flags.4?TextWithEntities = MessageAction;
messageActionGiftCode#56d03994 flags:# via_giveaway:flags.0?true unclaimed:flags.5?true boost_peer:flags.1?Peer months:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long message:flags.4?TextWithEntities = MessageAction;
messageActionGiveawayLaunch#a80f51e4 flags:# stars:flags.0?long = MessageAction;
messageActionGiveawayResults#87e2f155 flags:# stars:flags.0?true winners_count:int unclaimed_count:int = MessageAction;
messageActionBoostApply#cc02aa6d boosts:int = MessageAction;
@ -229,7 +229,7 @@ inputPeerNotifySettings#cacb6ae2 flags:# show_previews:flags.0?Bool silent:flags
peerNotifySettings#99622c0c flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int ios_sound:flags.3?NotificationSound android_sound:flags.4?NotificationSound other_sound:flags.5?NotificationSound stories_muted:flags.6?Bool stories_hide_sender:flags.7?Bool stories_ios_sound:flags.8?NotificationSound stories_android_sound:flags.9?NotificationSound stories_other_sound:flags.10?NotificationSound = PeerNotifySettings;
peerSettings#acd66c5e 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 autoarchived:flags.7?true invite_members:flags.8?true request_chat_broadcast:flags.10?true business_bot_paused:flags.11?true business_bot_can_reply:flags.12?true geo_distance:flags.6?int request_chat_title:flags.9?string request_chat_date:flags.9?int business_bot_id:flags.13?long business_bot_manage_url:flags.13?string = PeerSettings;
peerSettings#f47741f7 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 autoarchived:flags.7?true invite_members:flags.8?true request_chat_broadcast:flags.10?true business_bot_paused:flags.11?true business_bot_can_reply:flags.12?true geo_distance:flags.6?int request_chat_title:flags.9?string request_chat_date:flags.9?int business_bot_id:flags.13?long business_bot_manage_url:flags.13?string charge_paid_message_stars:flags.14?long registration_month:flags.15?string phone_country:flags.16?string name_change_date:flags.17?int photo_change_date:flags.18?int = 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;
wallPaperNoFile#e0804116 id:long flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;
@ -245,7 +245,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#4d975bbc flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification = UserFull;
userFull#d2234ea0 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact;
@ -435,7 +435,7 @@ updateStarsBalance#4e80a379 balance:StarsAmount = Update;
updateBusinessBotCallbackQuery#1ea2fda7 flags:# query_id:long user_id:long connection_id:string message:Message reply_to_message:flags.2?Message chat_instance:long data:flags.0?bytes = Update;
updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update;
updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update;
updatePaidReactionPrivacy#51ca7aec private:Bool = Update;
updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -543,6 +543,7 @@ inputPrivacyKeyVoiceMessages#aee69d68 = InputPrivacyKey;
inputPrivacyKeyAbout#3823cc40 = InputPrivacyKey;
inputPrivacyKeyBirthday#d65a11cc = InputPrivacyKey;
inputPrivacyKeyStarGiftsAutoSave#e1732341 = InputPrivacyKey;
inputPrivacyKeyNoPaidMessages#bdc597b4 = InputPrivacyKey;
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
privacyKeyChatInvite#500e6dfa = PrivacyKey;
@ -556,6 +557,7 @@ privacyKeyVoiceMessages#697f414 = PrivacyKey;
privacyKeyAbout#a486b761 = PrivacyKey;
privacyKeyBirthday#2000a518 = PrivacyKey;
privacyKeyStarGiftsAutoSave#2ca4fdf8 = PrivacyKey;
privacyKeyNoPaidMessages#17d348d2 = PrivacyKey;
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
@ -1318,7 +1320,7 @@ statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInvite
stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;
globalPrivacySettings#734c4ccb flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true = GlobalPrivacySettings;
globalPrivacySettings#c9d8df1c flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true noncontact_peers_paid_stars:flags.5?long = GlobalPrivacySettings;
help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode;
@ -1486,7 +1488,7 @@ inputInvoiceStars#65f00ce3 purpose:InputStorePaymentPurpose = InputInvoice;
inputInvoiceChatInviteSubscription#34e793f1 hash:string = InputInvoice;
inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:flags.2?true peer:InputPeer gift_id:long message:flags.1?TextWithEntities = InputInvoice;
inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice;
inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice;
inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
@ -1502,8 +1504,6 @@ inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = In
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumGiftOption;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus;
@ -1847,7 +1847,7 @@ starsTransactionPeerAPI#f9677aad = StarsTransactionPeer;
starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption;
starsTransaction#64dfc926 flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true stargift_upgrade:flags.18?true id:string stars:StarsAmount date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int starref_commission_permille:flags.16?int starref_peer:flags.17?Peer starref_amount:flags.17?StarsAmount = StarsTransaction;
starsTransaction#a39fd94a flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true stargift_upgrade:flags.18?true id:string stars:StarsAmount date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int starref_commission_permille:flags.16?int starref_peer:flags.17?Peer starref_amount:flags.17?StarsAmount paid_messages:flags.19?int premium_gift_months:flags.20?int = StarsTransaction;
payments.starsStatus#6c9ce8ed flags:# balance:StarsAmount subscriptions:flags.1?Vector<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
@ -1886,7 +1886,7 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
starGift#2cc73c8 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long = StarGift;
starGiftUnique#f2fe7e4a flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int = StarGift;
starGiftUnique#5c62d151 flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string = StarGift;
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
payments.starGifts#901689ea hash:int gifts:Vector<StarGift> = payments.StarGifts;
@ -1934,7 +1934,7 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.Uni
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
savedStarGift#6056dba5 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = SavedStarGift;
savedStarGift#6056dba5 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long = SavedStarGift;
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
@ -1943,6 +1943,16 @@ inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGif
payments.starGiftWithdrawalUrl#84aa3a9c url:string = payments.StarGiftWithdrawalUrl;
paidReactionPrivacyDefault#206ad49e = PaidReactionPrivacy;
paidReactionPrivacyAnonymous#1f0c1ad9 = PaidReactionPrivacy;
paidReactionPrivacyPeer#dc6cfcf0 peer:InputPeer = PaidReactionPrivacy;
account.paidMessagesRevenue#1e109708 stars_amount:long = account.PaidMessagesRevenue;
requirementToContactEmpty#50a9839 = RequirementToContact;
requirementToContactPremium#e581e4e9 = RequirementToContact;
requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1955,6 +1965,7 @@ invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
invokeWithBusinessConnection#dd289f8e {X:Type} connection_id:string query:!X = X;
invokeWithGooglePlayIntegrity#1df92984 {X:Type} nonce:string token:string query:!X = X;
invokeWithApnsSecret#0dae54f8 {X:Type} nonce:string secret:string query:!X = X;
invokeWithReCaptcha#adbb0f94 {X:Type} token:string query:!X = X;
auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
auth.signUp#aac7b717 flags:# no_joined_notifications:flags.0?true phone_number:string phone_code_hash:string first_name:string last_name:string = auth.Authorization;
@ -2093,11 +2104,13 @@ account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
account.getReactionsNotifySettings#6dd654c = ReactionsNotifySettings;
account.setReactionsNotifySettings#316ce548 settings:ReactionsNotifySettings = ReactionsNotifySettings;
account.getCollectibleEmojiStatuses#2e7b4543 hash:long = account.EmojiStatuses;
account.addNoPaidMessagesException#6f688aa7 flags:# refund_charged:flags.0?true user_id:InputUser = Bool;
account.getPaidMessagesRevenue#f1266f38 user_id:InputUser = account.PaidMessagesRevenue;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
users.getIsPremiumRequiredToContact#a622aa10 id:Vector<InputUser> = Vector<Bool>;
users.getRequirementsToContact#d89a83a3 id:Vector<InputUser> = Vector<RequirementToContact>;
contacts.getContactIDs#7adc669d hash:long = Vector<int>;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
@ -2135,9 +2148,9 @@ messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?t
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
messages.sendMessage#983f9745 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.sendMedia#7852834e flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.forwardMessages#6d74da08 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int = Updates;
messages.sendMessage#fbf2340a flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
messages.sendMedia#a550cd78 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
messages.forwardMessages#bb9fa475 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
@ -2180,7 +2193,7 @@ messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
messages.setInlineBotResults#bb12a419 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM switch_webview:flags.4?InlineBotWebView = Bool;
messages.sendInlineBotResult#3ebee86a flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to:flags.0?InputReplyTo random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;
messages.sendInlineBotResult#c0cf7646 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to:flags.0?InputReplyTo random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut allow_paid_stars:flags.21?long = Updates;
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
messages.editMessage#dfd14005 flags:# no_webpage:flags.1?true invert_media:flags.16?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.15?int quick_reply_shortcut_id:flags.17?int = Updates;
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true invert_media:flags.16?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
@ -2215,7 +2228,7 @@ messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
messages.getUnreadMentions#f107e790 flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readMentions#36e5bf4d flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages;
messages.sendMultiMedia#37b74355 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long = Updates;
messages.sendMultiMedia#1bf89d74 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
@ -2340,8 +2353,8 @@ messages.editFactCheck#589ee75 peer:InputPeer msg_id:int text:TextWithEntities =
messages.deleteFactCheck#d1da940c peer:InputPeer msg_id:int = Updates;
messages.getFactCheck#b9cdc5ee peer:InputPeer msg_id:Vector<int> = Vector<FactCheck>;
messages.requestMainWebView#c9e01e7b flags:# compact:flags.7?true fullscreen:flags.8?true peer:InputPeer bot:InputUser start_param:flags.1?string theme_params:flags.0?DataJSON platform:string = WebViewResult;
messages.sendPaidReaction#9dd6a67b flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?Bool = Updates;
messages.togglePaidReactionPrivacy#849ad397 peer:InputPeer msg_id:int private:Bool = Bool;
messages.sendPaidReaction#58bbcb50 flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?PaidReactionPrivacy = Updates;
messages.togglePaidReactionPrivacy#435885b5 peer:InputPeer msg_id:int private:PaidReactionPrivacy = Bool;
messages.getPaidReactionPrivacy#472455aa = Updates;
messages.viewSponsoredMessage#673ad8f1 peer:InputPeer random_id:bytes = Bool;
messages.clickSponsoredMessage#f093465 flags:# media:flags.0?true fullscreen:flags.1?true peer:InputPeer random_id:bytes = Bool;
@ -2432,7 +2445,7 @@ channels.editLocation#58e63f6d channel:InputChannel geo_point:InputGeoPoint addr
channels.toggleSlowMode#edd49ef0 channel:InputChannel seconds:int = Updates;
channels.getInactiveChannels#11e831ee = messages.InactiveChats;
channels.convertToGigagroup#b290c69 channel:InputChannel = Updates;
channels.getSendAs#dc770ee peer:InputPeer = channels.SendAsPeers;
channels.getSendAs#e785a43f flags:# for_paid_reactions:flags.0?true peer:InputPeer = channels.SendAsPeers;
channels.deleteParticipantHistory#367544db channel:InputChannel participant:InputPeer = messages.AffectedHistory;
channels.toggleJoinToSend#e4cb9580 channel:InputChannel enabled:Bool = Updates;
channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates;
@ -2458,6 +2471,7 @@ channels.setBoostsToUnblockRestrictions#ad399cee channel:InputChannel boosts:int
channels.setEmojiStickers#3cd930b7 channel:InputChannel stickerset:InputStickerSet = Bool;
channels.restrictSponsoredMessages#9ae91519 channel:InputChannel restricted:Bool = Updates;
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
channels.updatePaidMessagesPrice#fc84653f channel:InputChannel send_paid_messages_stars:long = Updates;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
@ -2537,6 +2551,7 @@ payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude
payments.getSavedStarGift#b455a106 stargift:Vector<InputSavedStarGift> = payments.SavedStarGifts;
payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl;
payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool;
payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<InputSavedStarGift> = Bool;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
@ -2657,4 +2672,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
// LAYER 198
// LAYER 200

View file

@ -223,6 +223,7 @@ def pyrogram_api():
transcribe_audio
translate_message_text
start_bot
delete_chat_history
""",
chats="""
Chats
@ -253,6 +254,7 @@ def pyrogram_api():
get_folders
get_forum_topics
get_forum_topics_by_id
get_forum_topics_count
set_chat_username
archive_chats
unarchive_chats
@ -553,6 +555,7 @@ def pyrogram_api():
ForumTopicCreated
ForumTopicEdited
ForumTopicClosed
ForumTopicDeleted
ForumTopicReopened
GeneralTopicHidden
GeneralTopicUnhidden

View file

@ -37,68 +37,16 @@ list of the basic styles currently supported by Pyrofork.
- spoiler
- `text URL <https://pyrogram.org>`_
- `user text mention <tg://user?id=123456789>`_
- :emoji:`🔥`
- ``inline fixed-width code``
- .. code-block:: text
pre-formatted
fixed-width
code block
- > Quoted text
Markdown Style
--------------
To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the *parse_mode* parameter when using
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
.. code-block:: text
**bold**
__italic__
--underline--
~~strike~~
||spoiler||
[text URL](https://pyrogram.org/)
[text user mention](tg://user?id=123456789)
`inline fixed-width code`
```
pre-formatted
fixed-width
code block
```
> Quoted text
**Example**:
.. code-block:: python
from pyrogram import enums
await app.send_message(
"me",
(
"**bold**, "
"__italic__, "
"--underline--, "
"~~strike~~, "
"||spoiler||, "
"[URL](https://pyrogram.org), "
"`code`, "
"```"
"for i in range(10):\n"
" print(i)"
"```"
),
parse_mode=enums.ParseMode.MARKDOWN
)
- > Quoted text with collapse/expand button
HTML Style
----------
@ -122,10 +70,10 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.HTML` to the *parse_mode*
<a href="tg://user?id=123456789">inline mention</a>
<code>inline fixed-width code</code>
<emoji id="12345678901234567890">🔥</emoji>
<code>inline fixed-width code</code>
<pre>
pre-formatted
fixed-width
@ -134,6 +82,8 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.HTML` to the *parse_mode*
<blockquote>Quoted text</blockquote>
<blockquote expandable>Quoted text with collapse/expand button</blockquote>
**Example**:
.. code-block:: python
@ -178,6 +128,72 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.HTML` to the *parse_mode*
&lt;my text&gt;
Markdown Style
--------------
.. warning::
The Markdown style is not recommended for complex text formatting.
If you want to use complex text formatting such as nested entities, overlapping entities use the HTML style instead.
To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the *parse_mode* parameter when using
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
.. code-block:: text
**bold**
__italic__
--underline--
~~strike~~
||spoiler||
[text URL](https://pyrogram.org/)
[text user mention](tg://user?id=123456789)
![🔥](tg://emoji?id=12345678901234567890)
`inline fixed-width code`
```
pre-formatted
fixed-width
code block
```
> Quoted text
**> Quoted text with collapse/expand button
**Example**:
.. code-block:: python
from pyrogram import enums
await app.send_message(
"me",
(
"**bold**, "
"__italic__, "
"--underline--, "
"~~strike~~, "
"||spoiler||, "
"[URL](https://pyrogram.org), "
"`code`, "
"```"
"for i in range(10):\n"
" print(i)"
"```"
),
parse_mode=enums.ParseMode.MARKDOWN
)
Different Styles
----------------
@ -230,18 +246,18 @@ 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>``
**Markdown (Not Recommended)**:
- ``**bold, --underline--**``
- ``**bold __italic --underline ~~strike~~--__**``
- ``**bold __and** italic__``
**Combined**:
- ``--you can combine <i>HTML</i> with **Markdown**--``

View file

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

View file

@ -50,6 +50,7 @@ from .get_dialogs_count import GetDialogsCount
from .get_folders import GetFolders
from .get_forum_topics import GetForumTopics
from .get_forum_topics_by_id import GetForumTopicsByID
from .get_forum_topics_count import GetForumTopicsCount
from .get_send_as_chats import GetSendAsChats
from .join_chat import JoinChat
from .leave_chat import LeaveChat
@ -98,6 +99,7 @@ class Chats(
GetFolders,
GetForumTopics,
GetForumTopicsByID,
GetForumTopicsCount,
ArchiveChats,
UnarchiveChats,
CreateGroup,

View file

@ -32,7 +32,10 @@ class GetForumTopics:
async def get_forum_topics(
self: "pyrogram.Client",
chat_id: Union[int, str],
limit: int = 0
limit: int = 0,
offset_date: int = 0,
offset_id: int = 0,
offset_topic: int = 0
) -> Optional[AsyncGenerator["types.ForumTopic", None]]:
"""Get one or more topic from a chat.
@ -46,6 +49,15 @@ class GetForumTopics:
limit (``int``, *optional*):
Limits the number of topics to be retrieved.
offset_date (``int``, *optional*):
Date of the last message of the last found topic.
offset_id (``int``, *optional*):
ID of the last message of the last found topic.
offset_topic (``int``, *optional*):
ID of the last found topic.
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.ForumTopic` objects is returned.
@ -62,7 +74,7 @@ class GetForumTopics:
peer = await self.resolve_peer(chat_id)
rpc = raw.functions.channels.GetForumTopics(channel=peer, offset_date=0, offset_id=0, offset_topic=0, limit=limit)
rpc = raw.functions.channels.GetForumTopics(channel=peer, offset_date=offset_date, offset_id=offset_id, offset_topic=offset_topic, limit=limit)
r = await self.invoke(rpc, sleep_threshold=-1)

View file

@ -0,0 +1,63 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
import logging
from typing import Union, Optional, AsyncGenerator
import pyrogram
from pyrogram import raw
from pyrogram import types
log = logging.getLogger(__name__)
class GetForumTopicsCount:
async def get_forum_topics_count(
self: "pyrogram.Client",
chat_id: Union[int, str]
) -> Optional[AsyncGenerator["types.ForumTopic", None]]:
"""Get forum topics count from a chat.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
You can also use chat public link in form of *t.me/<username>* (str).
Returns:
``int``: On success, the count of forum topics is returned.
Example:
.. code-block:: python
# get all forum topics count
app.get_forum_topics_count(chat_id)
Raises:
ValueError: In case of invalid arguments.
"""
peer = await self.resolve_peer(chat_id)
rpc = raw.functions.channels.GetForumTopics(channel=peer, offset_date=0, offset_id=0, offset_topic=0, limit=0)
r = await self.invoke(rpc, sleep_threshold=-1)
return r.count

View file

@ -19,6 +19,7 @@
from .copy_media_group import CopyMediaGroup
from .copy_message import CopyMessage
from .delete_chat_history import DeleteChatHistory
from .delete_messages import DeleteMessages
from .delete_scheduled_messages import DeleteScheduledMessages
from .download_media import DownloadMedia
@ -78,6 +79,7 @@ from .transcribe_audio import TranscribeAudio
from .translate_text import TranslateText
class Messages(
DeleteChatHistory,
DeleteMessages,
DeleteScheduledMessages,
EditMessageCaption,

View file

@ -0,0 +1,102 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
import logging
from typing import Union
import pyrogram
from pyrogram import raw
from pyrogram import utils
log = logging.getLogger(__name__)
class DeleteChatHistory:
async def delete_chat_history(
self: "pyrogram.Client",
chat_id: Union[int, str],
max_id: int = 0,
revoke: bool = None,
just_clear = None,
min_date: datetime = None,
max_date: datetime = None,
) -> int:
"""Delete the history of a chat.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
max_id (``int``, *optional*):
Maximum ID of message to delete.
revoke (``bool``, *optional*):
Deletes messages history for everyone.
Required ``True`` if using in channel.
just_clear (``bool``, *optional*):
If True, clear history for the current user, without actually removing chat.
For private and simple group chats only.
min_date (:py:obj:`~datetime.datetime`, *optional*):
Delete all messages newer than this time.
For private and simple group chats only.
max_date (:py:obj:`~datetime.datetime`, *optional*):
Delete all messages older than this time.
For private and simple group chats only.
Returns:
``int``: Amount of affected messages
Example:
.. code-block:: python
# Delete all messages in channel
await app.delete_chat_history(chat_id, revoke=True)
"""
peer = await self.resolve_peer(chat_id)
if isinstance(peer, raw.types.InputPeerChannel):
r = await self.invoke(
raw.functions.channels.DeleteHistory(
channel=raw.types.InputChannel(
channel_id=peer.channel_id,
access_hash=peer.access_hash
),
max_id=max_id,
for_everyone=revoke
)
)
else:
r = await self.invoke(
raw.functions.messages.DeleteHistory(
peer=peer,
max_id=max_id,
just_clear=just_clear,
revoke=revoke,
min_date=utils.datetime_to_timestamp(min_date),
max_date=utils.datetime_to_timestamp(max_date)
)
)
return len(r.updates[0].messages) if isinstance(peer, raw.types.InputPeerChannel) else r.pts_count

View file

@ -23,10 +23,7 @@ from datetime import datetime
from typing import Union, BinaryIO, List, Optional, Callable
import pyrogram
from pyrogram import StopTransmission, enums
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram import StopTransmission, enums, raw, types, utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
@ -55,7 +52,7 @@ class SendVideo:
reply_to_chat_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
cover: Optional[Union[str, "io.BytesIO"]] = None,
cover: Union[str, BinaryIO] = None,
start_timestamp: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
@ -161,8 +158,12 @@ class SendVideo:
List of special entities that appear in quote_text, which can be specified instead of *parse_mode*.
for reply_to_message only.
cover (``str`` | :obj:`io.BytesIO`, *optional*):
Cover of the video; pass None to skip cover uploading.
cover (``str`` | ``BinaryIO``, *optional*):
Video cover.
Pass a file_id as string to attach a photo that exists on the Telegram servers,
pass a HTTP URL as a string for Telegram to get a video from the Internet,
pass a file path as string to upload a new photo civer that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
start_timestamp (``int``, *optional*):
Timestamp from which the video playing must start, in seconds.
@ -224,6 +225,9 @@ class SendVideo:
# Send self-destructing video
await app.send_video("me", "video.mp4", ttl_seconds=10)
# Add video_cover to the video
await app.send_video(channel_id, "video.mp4", video_cover="coverku.jpg")
# Keep track of the progress while uploading
async def progress(current, total):
print(f"{current * 100 / total:.1f}%")
@ -231,6 +235,9 @@ class SendVideo:
await app.send_video("me", "video.mp4", progress=progress)
"""
file = None
vidcover_file = None
vidcover_media = None
peer = await self.resolve_peer(chat_id)
reply_to = await utils.get_reply_to(
client=self,
@ -245,6 +252,45 @@ class SendVideo:
)
try:
if cover is not None:
if isinstance(cover, str):
if os.path.isfile(cover):
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(cover)
)
)
)
elif re.match("^https?://", cover):
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaPhotoExternal(
url=cover
)
)
)
else:
vidcover_file = utils.get_input_media_from_file_id(cover, FileType.PHOTO).id
else:
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(cover)
)
)
)
if vidcover_media:
vidcover_file = raw.types.InputPhoto(
id=vidcover_media.photo.id,
access_hash=vidcover_media.photo.access_hash,
file_reference=vidcover_media.photo.file_reference
)
if isinstance(video, str):
if os.path.isfile(video):
thumb = await self.save_file(thumb)
@ -264,7 +310,7 @@ class SendVideo:
),
raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
],
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
elif re.match("^https?://", video):
@ -272,7 +318,7 @@ class SendVideo:
url=video,
ttl_seconds=ttl_seconds,
spoiler=has_spoiler,
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
else:
@ -296,14 +342,14 @@ class SendVideo:
),
raw.types.DocumentAttributeFilename(file_name=file_name or video.name)
],
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
while True:
try:
rpc = raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=reply_to,

View file

@ -35,7 +35,7 @@ class GetChatGifts:
limit: int = 0,
offset: str = ""
):
"""Get user star gifts.
"""Get all gifts owned by specified chat.
.. include:: /_includes/usable-by/users.rst

View file

@ -35,7 +35,7 @@ class GetChatGiftsCount:
exclude_limited: Optional[bool] = None,
exclude_upgraded: Optional[bool] = None
) -> int:
"""Get the total count of star gifts of specified user.
"""Get the total count of owned gifts of specified chat.
.. include:: /_includes/usable-by/users.rst

View file

@ -37,7 +37,7 @@ PRE_DELIM = "```"
BLOCKQUOTE_DELIM = ">"
BLOCKQUOTE_EXPANDABLE_DELIM = "**>"
MARKDOWN_RE = re.compile(r"({d})|(!?)\[(.+?)\]\((.+?)\)".format(
MARKDOWN_RE = re.compile(r"({d})".format(
d="|".join(
["".join(i) for i in [
[rf"\{j}" for j in i]
@ -52,6 +52,7 @@ MARKDOWN_RE = re.compile(r"({d})|(!?)\[(.+?)\]\((.+?)\)".format(
]
]]
)))
URL_RE = re.compile(r"(!?)\[(.+?)\]\((.+?)\)")
OPENING_TAG = "<{}>"
CLOSING_TAG = "</{}>"
@ -118,7 +119,7 @@ class Markdown:
for i, match in enumerate(re.finditer(MARKDOWN_RE, text)):
start, _ = match.span()
delim, is_emoji, text_url, url = match.groups()
delim = match.group(1)
full = match.group(0)
if delim in FIXED_WIDTH_DELIMS:
@ -127,16 +128,6 @@ class Markdown:
if is_fixed_width and delim not in FIXED_WIDTH_DELIMS:
continue
if not is_emoji and text_url:
text = utils.replace_once(text, full, URL_MARKUP.format(url, text_url), start)
continue
if is_emoji:
emoji = text_url
emoji_id = url.lstrip("tg://emoji?id=")
text = utils.replace_once(text, full, EMOJI_MARKUP.format(emoji_id, emoji), start)
continue
if delim == BOLD_DELIM:
tag = "b"
elif delim == ITALIC_DELIM:
@ -169,6 +160,21 @@ class Markdown:
text = utils.replace_once(text, delim, tag, start)
for i, match in enumerate(re.finditer(URL_RE, text)):
start, _ = match.span()
is_emoji, text_url, url = match.groups()
full = match.group(0)
if not is_emoji and text_url:
text = utils.replace_once(text, full, URL_MARKUP.format(url, text_url), start)
continue
if is_emoji:
emoji = text_url
emoji_id = url.lstrip("tg://emoji?id=")
text = utils.replace_once(text, full, EMOJI_MARKUP.format(emoji_id, emoji), start)
continue
for placeholder, code_section in placeholders.items():
text = text.replace(placeholder, code_section)
@ -176,78 +182,110 @@ class Markdown:
@staticmethod
def unparse(text: str, entities: list):
"""
Performs the reverse operation to .parse(), effectively returning
markdown-like syntax given a normal text and its MessageEntity's.
:param text: the text to be reconverted into markdown.
:param entities: list of MessageEntity's applied to the text.
:return: a markdown-like text representing the combination of both inputs.
"""
delimiters = {
MessageEntityType.BOLD: BOLD_DELIM,
MessageEntityType.ITALIC: ITALIC_DELIM,
MessageEntityType.UNDERLINE: UNDERLINE_DELIM,
MessageEntityType.STRIKETHROUGH: STRIKE_DELIM,
MessageEntityType.CODE: CODE_DELIM,
MessageEntityType.PRE: PRE_DELIM,
MessageEntityType.BLOCKQUOTE: BLOCKQUOTE_DELIM,
MessageEntityType.EXPANDABLE_BLOCKQUOTE: BLOCKQUOTE_EXPANDABLE_DELIM,
MessageEntityType.SPOILER: SPOILER_DELIM
}
text = utils.add_surrogates(text)
entities_offsets = []
for entity in entities:
entity_type = entity.type
start = entity.offset
end = start + entity.length
if entity_type == MessageEntityType.BOLD:
start_tag = end_tag = BOLD_DELIM
elif entity_type == MessageEntityType.ITALIC:
start_tag = end_tag = ITALIC_DELIM
elif entity_type == MessageEntityType.UNDERLINE:
start_tag = end_tag = UNDERLINE_DELIM
elif entity_type == MessageEntityType.STRIKETHROUGH:
start_tag = end_tag = STRIKE_DELIM
elif entity_type == MessageEntityType.CODE:
start_tag = end_tag = CODE_DELIM
elif entity_type == MessageEntityType.PRE:
language = getattr(entity, "language", "") or ""
start_tag = f"{PRE_DELIM}{language}\n"
end_tag = f"\n{PRE_DELIM}"
elif entity_type == MessageEntityType.BLOCKQUOTE:
if entity.collapsed:
start_tag = BLOCKQUOTE_EXPANDABLE_DELIM + " "
insert_at = []
for i, entity in enumerate(entities):
s = entity.offset
e = entity.offset + entity.length
delimiter = delimiters.get(entity.type, None)
if delimiter:
if entity.type == MessageEntityType.PRE:
inside_blockquote = any(
blk_entity.offset <= s < blk_entity.offset + blk_entity.length and
blk_entity.offset < e <= blk_entity.offset + blk_entity.length
for blk_entity in entities
if blk_entity.type == MessageEntityType.BLOCKQUOTE
)
is_expandable = any(
blk_entity.offset <= s < blk_entity.offset + blk_entity.length and
blk_entity.offset < e <= blk_entity.offset + blk_entity.length and
blk_entity.collapsed
for blk_entity in entities
if blk_entity.type == MessageEntityType.BLOCKQUOTE
)
if inside_blockquote:
if is_expandable:
if entity.language:
open_delimiter = f"{delimiter}{entity.language}\n**>"
else:
open_delimiter = f"{delimiter}\n**>"
close_delimiter = f"\n**>{delimiter}"
else:
if entity.language:
open_delimiter = f"{delimiter}{entity.language}\n>"
else:
open_delimiter = f"{delimiter}\n>"
close_delimiter = f"\n>{delimiter}"
else:
open_delimiter = delimiter
close_delimiter = delimiter
insert_at.append((s, i, open_delimiter))
insert_at.append((e, -i, close_delimiter))
elif entity.type != MessageEntityType.BLOCKQUOTE and entity.type != MessageEntityType.EXPANDABLE_BLOCKQUOTE:
open_delimiter = delimiter
close_delimiter = delimiter
insert_at.append((s, i, open_delimiter))
insert_at.append((e, -i, close_delimiter))
else:
start_tag = BLOCKQUOTE_DELIM + " "
end_tag = ""
blockquote_text = text[start:end]
lines = blockquote_text.split("\n")
last_length = 0
for line in lines:
if len(line) == 0 and last_length == end:
continue
start_offset = start+last_length
last_length = last_length+len(line)
end_offset = start_offset+last_length
entities_offsets.append((start_tag, start_offset,))
entities_offsets.append((end_tag, end_offset,))
last_length = last_length+1
continue
elif entity_type == MessageEntityType.SPOILER:
start_tag = end_tag = SPOILER_DELIM
elif entity_type == MessageEntityType.TEXT_LINK:
url = entity.url
start_tag = "["
end_tag = f"]({url})"
elif entity_type == MessageEntityType.TEXT_MENTION:
user = entity.user
start_tag = "["
end_tag = f"](tg://user?id={user.id})"
elif entity_type == MessageEntityType.CUSTOM_EMOJI:
emoji_id = entity.custom_emoji_id
start_tag = "!["
end_tag = f"](tg://emoji?id={emoji_id})"
# Handle multiline blockquotes
text_subset = text[s:e]
lines = text_subset.splitlines()
for line_num, line in enumerate(lines):
line_start = s + sum(len(l) + 1 for l in lines[:line_num])
if entity.collapsed:
insert_at.append((line_start, i, BLOCKQUOTE_EXPANDABLE_DELIM))
else:
insert_at.append((line_start, i, BLOCKQUOTE_DELIM))
# No closing delimiter for blockquotes
else:
continue
url = None
is_emoji = False
if entity.type == MessageEntityType.TEXT_LINK:
url = entity.url
elif entity.type == MessageEntityType.TEXT_MENTION:
url = f'tg://user?id={entity.user.id}'
elif entity.type == MessageEntityType.CUSTOM_EMOJI:
url = f"tg://emoji?id={entity.custom_emoji_id}"
is_emoji = True
if url:
if is_emoji:
insert_at.append((s, i, '!['))
else:
insert_at.append((s, i, '['))
insert_at.append((e, -i, f']({url})'))
entities_offsets.append((start_tag, start,))
entities_offsets.append((end_tag, end,))
insert_at.sort(key=lambda t: (t[0], t[1]))
while insert_at:
at, _, what = insert_at.pop()
entities_offsets = map(
lambda x: x[1],
sorted(
enumerate(entities_offsets),
key=lambda x: (x[1][1], x[0]),
reverse=True
)
)
# If we are in the middle of a surrogate nudge the position by -1.
# Otherwise we would end up with malformed text and fail to encode.
# For example of bad input: "Hi \ud83d\ude1c"
# https://en.wikipedia.org/wiki/UTF-16#U+010000_to_U+10FFFF
while utils.within_surrogate(text, at):
at += 1
for entity, offset in entities_offsets:
text = text[:offset] + entity + text[offset:]
text = text[:at] + what + text[at:]
return utils.remove_surrogates(text)

View file

@ -40,3 +40,16 @@ def remove_surrogates(text):
def replace_once(source: str, old: str, new: str, start: int):
return source[:start] + source[start:].replace(old, new, 1)
def within_surrogate(text, index, *, length=None):
"""
`True` if ``index`` is within a surrogate (before and after it, not at!).
"""
if length is None:
length = len(text)
return (
1 < index < len(text) and # in bounds
'\ud800' <= text[index - 1] <= '\udbff' and # previous is
'\ud800' <= text[index] <= '\udfff' # current is
)

View file

@ -23,9 +23,7 @@ from functools import partial
from typing import List, Match, Union, BinaryIO, Optional, Callable
import pyrogram
from pyrogram import raw, enums
from pyrogram import types
from pyrogram import utils
from pyrogram import enums, raw, types, utils
from pyrogram.errors import ChannelPrivate, MessageIdsEmpty, PeerIdInvalid
from pyrogram.parser import utils as parser_utils, Parser
from ..object import Object
@ -424,6 +422,9 @@ class Message(Object, Update):
link (``str``, *property*):
Generate a link to this message, only for groups and channels.
content (``str``, *property*):
The text or caption content of the message.
scheduled (``bool``, *optional*):
Message is a scheduled message and still in schedule.
@ -1112,7 +1113,7 @@ class Message(Object, Update):
video_note = types.VideoNote._parse(client, doc, video_attributes)
media_type = enums.MessageMediaType.VIDEO_NOTE
else:
video = types.Video._parse(client, doc, video_attributes, file_name, media.ttl_seconds)
video = types.Video._parse(client, doc, video_attributes, file_name, media.ttl_seconds, media.video_cover, media.video_timestamp)
media_type = enums.MessageMediaType.VIDEO
has_media_spoiler = media.spoiler
@ -1358,6 +1359,10 @@ class Message(Object, Update):
else:
return f"https://t.me/c/{utils.get_channel_id(self.chat.id)}/{self.id}"
@property
def content(self) -> str:
return self.text or self.caption or Str("").init([])
async def get_media_group(self) -> List["types.Message"]:
"""Bound method *get_media_group* of :obj:`~pyrogram.types.Message`.
@ -3593,7 +3598,7 @@ class Message(Object, Update):
quote_entities: List["types.MessageEntity"] = None,
allow_paid_broadcast: bool = None,
message_effect_id: int = None,
cover: Optional[Union[str, "io.BytesIO"]] = None,
cover: Union[str, BinaryIO] = None,
start_timestamp: int = None,
schedule_date: datetime = None,
invert_media: bool = None,
@ -3700,8 +3705,12 @@ class Message(Object, Update):
allow_paid_broadcast (``bool``, *optional*):
Pass True to allow the message to ignore regular broadcast limits for a small fee; for bots.
cover (``str`` | :obj:`io.BytesIO`, *optional*):
Cover of the video; pass None to skip cover uploading.
cover (``str`` | ``BinaryIO``, *optional*):
Video cover.
Pass a file_id as string to attach a photo that exists on the Telegram servers,
pass a HTTP URL as a string for Telegram to get a video from the Internet,
pass a file path as string to upload a new photo civer that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
start_timestamp (``int``, *optional*):
Timestamp from which the video playing must start, in seconds.

View file

@ -21,8 +21,7 @@ from datetime import datetime
from typing import List
import pyrogram
from pyrogram import raw, utils
from pyrogram import types
from pyrogram import raw, types, utils
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
@ -67,6 +66,12 @@ class Video(Object):
thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Video thumbnails.
cover (:obj:`~pyrogram.types.Photo`, *optional*):
Video cover.
start_timestamp (``int``, *optional*):
Video startpoint, in seconds.
"""
def __init__(
@ -84,7 +89,9 @@ class Video(Object):
supports_streaming: bool = None,
ttl_seconds: int = None,
date: datetime = None,
thumbs: List["types.Thumbnail"] = None
thumbs: List["types.Thumbnail"] = None,
cover: "types.Photo" = None,
start_timestamp: int = None,
):
super().__init__(client)
@ -100,6 +107,8 @@ class Video(Object):
self.ttl_seconds = ttl_seconds
self.date = date
self.thumbs = thumbs
self.cover = cover
self.start_timestamp = start_timestamp
@staticmethod
def _parse(
@ -107,7 +116,9 @@ class Video(Object):
video: "raw.types.Document",
video_attributes: "raw.types.DocumentAttributeVideo",
file_name: str,
ttl_seconds: int = None
ttl_seconds: int = None,
cover = None,
start_timestamp: int = None
) -> "Video":
return Video(
file_id=FileId(
@ -131,5 +142,7 @@ class Video(Object):
date=utils.timestamp_to_datetime(video.date),
ttl_seconds=ttl_seconds,
thumbs=types.Thumbnail._parse(client, video),
cover=types.Photo._parse(client, cover),
start_timestamp=start_timestamp,
client=client
)

View file

@ -50,6 +50,7 @@ from .username import Username
from .forum_topic import ForumTopic
from .forum_topic_created import ForumTopicCreated
from .forum_topic_closed import ForumTopicClosed
from .forum_topic_deleted import ForumTopicDeleted
from .forum_topic_reopened import ForumTopicReopened
from .forum_topic_edited import ForumTopicEdited
from .general_forum_topic_hidden import GeneralTopicHidden
@ -88,6 +89,7 @@ __all__ = [
"ForumTopic",
"ForumTopicCreated",
"ForumTopicClosed",
"ForumTopicDeleted",
"ForumTopicReopened",
"ForumTopicEdited",
"GeneralTopicHidden",

View file

@ -123,7 +123,9 @@ class ForumTopic(Object):
#self.draft = draft //todo
@staticmethod
def _parse(forum_topic: "raw.types.forum_topic") -> "ForumTopic":
def _parse(forum_topic: "raw.types.ForumTopic") -> "ForumTopic":
if isinstance(forum_topic, raw.types.ForumTopicDeleted):
return types.ForumTopicDeleted._parse(forum_topic)
from_id = forum_topic.from_id
if isinstance(from_id, raw.types.PeerChannel):
peer = types.PeerChannel._parse(from_id)

View file

@ -0,0 +1,45 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw, types
from typing import Union
from ..object import Object
class ForumTopicDeleted(Object):
"""A deleted forum topic.
Parameters:
id (``Integer``):
Id of the topic
"""
def __init__(
self,
*,
id: int
):
super().__init__()
self.id = id
@staticmethod
def _parse(forum_topic: "raw.types.ForumTopicDeleted") -> "ForumTopicDeleted":
return ForumTopicDeleted(
id=getattr(forum_topic,"id", None)
)