From bb2034ae362d3e4d886a778df81880f4dcd1de77 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 8 Aug 2022 23:00:06 +0300 Subject: [PATCH 001/200] Update layer to 145. --- td/generate/scheme/telegram_api.tl | 92 +++++++++++++++++++++------- td/telegram/AttachMenuManager.cpp | 3 +- td/telegram/AuthManager.cpp | 14 +++-- td/telegram/ContactsManager.cpp | 2 +- td/telegram/DialogEventLog.cpp | 3 +- td/telegram/InlineQueriesManager.cpp | 4 +- td/telegram/MessageReaction.cpp | 70 +++++++++++++++------ td/telegram/MessagesManager.cpp | 22 ++++--- td/telegram/MessagesManager.h | 4 +- td/telegram/NotificationManager.cpp | 4 +- td/telegram/PasswordManager.cpp | 8 ++- td/telegram/Premium.cpp | 11 +--- td/telegram/SendCodeHelper.cpp | 8 +++ td/telegram/UpdatesManager.cpp | 16 +++++ td/telegram/UpdatesManager.h | 8 +++ td/telegram/Version.h | 2 +- 16 files changed, 190 insertions(+), 81 deletions(-) diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index 68ad20578..4f17c4aa8 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -101,7 +101,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType; storage.fileWebp#1081464c = storage.FileType; userEmpty#d3bc4b7a id:long = User; -user#3ff6ecb0 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 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 bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User; +user#5d99adee 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 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 bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus = User; userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto; userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto; @@ -119,8 +119,8 @@ chatForbidden#6592a1a7 id:long title:string = Chat; channel#8261ac61 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 id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = 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#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?Vector = ChatFull; -channelFull#ea68a619 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 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 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 groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?Vector = ChatFull; +chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions = ChatFull; +channelFull#f2355507 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 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 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 groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions = ChatFull; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; @@ -315,7 +315,7 @@ updateChannelMessageViews#f226ac08 channel_id:long id:int views:int = Update; updateChatParticipantAdmin#d7ca61a2 chat_id:long user_id:long is_admin:Bool version:int = Update; updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update; updateStickerSetsOrder#bb2d201 flags:# masks:flags.0?true emojis:flags.1?true order:Vector = Update; -updateStickerSets#43ae3dec = Update; +updateStickerSets#31c24808 flags:# masks:flags.0?true emojis:flags.1?true = Update; updateSavedGifs#9375341e = Update; updateBotInlineQuery#496f379c flags:# query_id:long user_id:long query:string geo:flags.0?GeoPoint peer_type:flags.1?InlineQueryPeerType offset:string = Update; updateBotInlineSend#12f12a07 flags:# user_id:long query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update; @@ -384,6 +384,10 @@ updateBotMenuButton#14b85813 bot_id:long button:BotMenuButton = Update; updateSavedRingtones#74d8be99 = Update; updateTranscribedAudio#84cd5a flags:# pending:flags.0?true peer:Peer msg_id:int transcription_id:long text:string = Update; updateReadFeaturedEmojiStickers#fb4c496c = Update; +updateUserEmojiStatus#28373599 user_id:long emoji_status:EmojiStatus = Update; +updateRecentEmojiStatuses#30f443db = Update; +updateRecentReactions#6f7863f4 = Update; +updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?true stickerset:long = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -410,7 +414,7 @@ upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true this_port_only:flags.5?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption; -config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config; +config#232566ac flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int reactions_default:flags.15?Reaction = Config; nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc; @@ -548,7 +552,7 @@ authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true pa account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector = account.Authorizations; -account.password#185b184f flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int = account.Password; +account.password#957b50fb flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int login_email_pattern:flags.6?string = account.Password; account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings; @@ -572,6 +576,8 @@ inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet; inputStickerSetDice#e67f520e emoticon:string = InputStickerSet; inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet; inputStickerSetPremiumGifts#c88b3b02 = InputStickerSet; +inputStickerSetEmojiGenericAnimations#4c4d4ce = InputStickerSet; +inputStickerSetEmojiDefaultStatuses#29d0f5ee = InputStickerSet; stickerSet#2dd14edc flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true videos:flags.6?true emojis:flags.7?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector thumb_dc_id:flags.4?int thumb_version:flags.4?int thumb_document_id:flags.8?long count:int hash:int = StickerSet; @@ -707,6 +713,8 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType; auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType; auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType; auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeType; +auth.sentCodeTypeEmailCode#5a159841 flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int next_phone_login_date:flags.2?int = auth.SentCodeType; +auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType; messages.botCallbackAnswer#36585ea4 flags:# alert:flags.1?true has_url:flags.3?true native_ui:flags.4?true message:flags.0?string url:flags.2?string cache_time:int = messages.BotCallbackAnswer; @@ -933,7 +941,7 @@ channelAdminLogEventActionChangeHistoryTTL#6e941a38 prev_value:int new_value:int channelAdminLogEventActionParticipantJoinByRequest#afb6144a invite:ExportedChatInvite approved_by:long = ChannelAdminLogEventAction; channelAdminLogEventActionToggleNoForwards#cb2ac766 new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionSendMessage#278f2868 message:Message = ChannelAdminLogEventAction; -channelAdminLogEventActionChangeAvailableReactions#9cf7f76a prev_value:Vector new_value:Vector = ChannelAdminLogEventAction; +channelAdminLogEventActionChangeAvailableReactions#be4e0ef8 prev_value:ChatReactions new_value:ChatReactions = ChannelAdminLogEventAction; channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent; @@ -1318,7 +1326,7 @@ messages.peerSettings#6880b94d settings:PeerSettings chats:Vector users:Ve auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut; -reactionCount#6fb250d1 flags:# chosen:flags.0?true reaction:string count:int = ReactionCount; +reactionCount#a3d1cb80 flags:# chosen_order:flags.0?int reaction:Reaction count:int = ReactionCount; messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector recent_reactions:flags.1?Vector = MessageReactions; @@ -1332,7 +1340,7 @@ messages.availableReactions#768e3aad hash:int reactions:Vector video_sections:Vector videos:Vector currency:string monthly_amount:long users:Vector = help.PremiumPromo; +help.premiumPromo#5334759c status_text:string status_entities:Vector video_sections:Vector videos:Vector period_options:Vector users:Vector = help.PremiumPromo; inputStorePaymentPremiumSubscription#a6751e66 flags:# restore:flags.0?true = InputStorePaymentPurpose; inputStorePaymentGiftPremium#616f7fe8 user_id:InputUser currency:string amount:long = InputStorePaymentPurpose; @@ -1394,6 +1402,37 @@ premiumGiftOption#74c34319 flags:# months:int currency:string amount:long bot_ur paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod; +emojiStatusEmpty#2de11aae = EmojiStatus; +emojiStatus#929b619d document_id:long = EmojiStatus; +emojiStatusUntil#fa30a8c7 document_id:long until:int = EmojiStatus; + +account.emojiStatusesNotModified#d08ce645 = account.EmojiStatuses; +account.emojiStatuses#90c467d1 hash:long statuses:Vector = account.EmojiStatuses; + +reactionEmpty#79f5d419 = Reaction; +reactionEmoji#1b2286b8 emoticon:string = Reaction; +reactionCustomEmoji#8935fc73 document_id:long = Reaction; + +chatReactionsNone#eafc32bc = ChatReactions; +chatReactionsAll#52928bca flags:# allow_custom:flags.0?true = ChatReactions; +chatReactionsSome#661d4037 reactions:Vector = ChatReactions; + +messages.reactionsNotModified#b06fdbdf = messages.Reactions; +messages.reactions#eafdf716 hash:long reactions:Vector = messages.Reactions; + +emailVerifyPurposeLoginSetup#4345be73 phone_number:string phone_code_hash:string = EmailVerifyPurpose; +emailVerifyPurposeLoginChange#527d22eb = EmailVerifyPurpose; +emailVerifyPurposePassport#bbf51685 = EmailVerifyPurpose; + +emailVerificationCode#922e55a9 code:string = EmailVerification; +emailVerificationGoogle#db909ec2 token:string = EmailVerification; +emailVerificationApple#96d074fd token:string = EmailVerification; + +account.emailVerified#2b96cd1b email:string = account.EmailVerified; +account.emailVerifiedLogin#e1bb0d61 email:string sent_code:auth.SentCode = account.EmailVerified; + +premiumSubscriptionOption#b6f11ebe flags:# current:flags.1?true can_purchase_upgrade:flags.2?true months:int currency:string amount:long bot_url:string store_product:flags.0?string = PremiumSubscriptionOption; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1406,7 +1445,7 @@ invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X; auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode; auth.signUp#80eee427 phone_number:string phone_code_hash:string first_name:string last_name:string = auth.Authorization; -auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization; +auth.signIn#8d52a951 flags:# phone_number:string phone_code_hash:string phone_code:flags.0?string email_verification:flags.1?EmailVerification = auth.Authorization; auth.logOut#3e72ba19 = auth.LoggedOut; auth.resetAuthorizations#9fab0d1a = Bool; auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization; @@ -1462,8 +1501,8 @@ account.getAuthorizationForm#a929597a bot_id:long scope:string public_key:string account.acceptAuthorization#f3ed4c73 bot_id:long scope:string public_key:string value_hashes:Vector credentials:SecureCredentialsEncrypted = Bool; account.sendVerifyPhoneCode#a5a356f9 phone_number:string settings:CodeSettings = auth.SentCode; account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool; -account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode; -account.verifyEmail#ecba39db email:string code:string = Bool; +account.sendVerifyEmailCode#98e037bb purpose:EmailVerifyPurpose email:string = account.SentEmailCode; +account.verifyEmail#32da4cf purpose:EmailVerifyPurpose verification:EmailVerification = account.EmailVerified; account.initTakeoutSession#8ef3eab0 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?long = account.Takeout; account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool; account.confirmPasswordEmail#8fdf1920 code:string = Bool; @@ -1500,6 +1539,10 @@ account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_request account.getSavedRingtones#e1902288 hash:long = account.SavedRingtones; account.saveRingtone#3dea5b03 id:InputDocument unsave:Bool = account.SavedRingtone; account.uploadRingtone#831a83a2 file:InputFile file_name:string mime_type:string = Document; +account.updateEmojiStatus#fbd3de6b emoji_status:EmojiStatus = Bool; +account.getDefaultEmojiStatuses#d6753386 hash:long = account.EmojiStatuses; +account.getRecentEmojiStatuses#f578105 hash:long = account.EmojiStatuses; +account.clearRecentEmojiStatuses#18201aae = Bool; users.getUsers#d91a548 id:Vector = Vector; users.getFullUser#b60f5918 id:InputUser = users.UserFull; @@ -1536,8 +1579,8 @@ messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?t messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector = messages.AffectedMessages; messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool; -messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; -messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?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 schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMessage#d9d75a4 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 peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?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 schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.forwardMessages#cc30290b 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 from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings; @@ -1617,7 +1660,7 @@ messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool; messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory; messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages; -messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = 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; @@ -1676,12 +1719,12 @@ messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPe messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates; messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates; messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool; -messages.sendReaction#25690ce4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?string = Updates; +messages.sendReaction#d30d78d4 flags:# big:flags.1?true add_to_recent:flags.2?true peer:InputPeer msg_id:int reaction:flags.0?Vector = Updates; messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector = Updates; -messages.getMessageReactionsList#e0ee6b77 flags:# peer:InputPeer id:int reaction:flags.0?string offset:flags.1?string limit:int = messages.MessageReactionsList; -messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector = Updates; +messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList; +messages.setChatAvailableReactions#feb16771 peer:InputPeer available_reactions:ChatReactions = Updates; messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions; -messages.setDefaultReaction#d960c4d4 reaction:string = Bool; +messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool; messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText; messages.getUnreadReactions#e85bae1a peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.readReactions#82e251d7 peer:InputPeer = messages.AffectedHistory; @@ -1689,9 +1732,9 @@ messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = mes messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots; messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot; messages.toggleBotInAttachMenu#1aee33af bot:InputUser enabled:Bool = Bool; -messages.requestWebView#91b15831 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON reply_to_msg_id:flags.0?int send_as:flags.13?InputPeer = WebViewResult; +messages.requestWebView#fc87a53c flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to_msg_id:flags.0?int send_as:flags.13?InputPeer = WebViewResult; messages.prolongWebView#ea5fbcce flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to_msg_id:flags.0?int send_as:flags.13?InputPeer = Bool; -messages.requestSimpleWebView#6abb2f73 flags:# bot:InputUser url:string theme_params:flags.0?DataJSON = SimpleWebViewResult; +messages.requestSimpleWebView#299bec8e flags:# bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult; messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent; messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates; messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio; @@ -1699,6 +1742,10 @@ messages.rateTranscribedAudio#7f1d072f peer:InputPeer msg_id:int transcription_i messages.getCustomEmojiDocuments#d9ab0f54 document_id:Vector = Vector; messages.getEmojiStickers#fbfca18f hash:long = messages.AllStickers; messages.getFeaturedEmojiStickers#ecf6736 hash:long = messages.FeaturedStickers; +messages.reportReaction#3f64c076 peer:InputPeer id:int reaction_peer:InputPeer = Bool; +messages.getTopReactions#bb8125ba limit:int hash:long = messages.Reactions; +messages.getRecentReactions#39461db2 limit:int hash:long = messages.Reactions; +messages.clearRecentReactions#9dfeefb4 = Bool; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; @@ -1805,7 +1852,6 @@ payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoi payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates; payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates; payments.canPurchasePremium#9fc19eb6 purpose:InputStorePaymentPurpose = Bool; -payments.requestRecurringPayment#146e958d user_id:InputUser recurring_init_charge:string invoice_media:InputMedia = Updates; stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true videos:flags.4?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet; diff --git a/td/telegram/AttachMenuManager.cpp b/td/telegram/AttachMenuManager.cpp index 224bd23da..1002c4724 100644 --- a/td/telegram/AttachMenuManager.cpp +++ b/td/telegram/AttachMenuManager.cpp @@ -104,7 +104,8 @@ class RequestWebViewQuery final : public Td::ResultHandler { send_query(G()->net_query_creator().create(telegram_api::messages_requestWebView( flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), std::move(input_user), url, start_parameter, - std::move(theme_parameters), reply_to_message_id.get_server_message_id().get(), std::move(as_input_peer)))); + std::move(theme_parameters), string(), reply_to_message_id.get_server_message_id().get(), + std::move(as_input_peer)))); } void on_result(BufferSlice packet) final { diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 010a68583..99fb0cf5b 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -289,10 +289,11 @@ void AuthManager::check_code(uint64 query_id, string code) { } code_ = std::move(code); + int32 flags = telegram_api::auth_signIn::PHONE_CODE_MASK; on_new_query(query_id); - start_net_query(NetQueryType::SignIn, - G()->net_query_creator().create_unauth(telegram_api::auth_signIn( - send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_))); + start_net_query(NetQueryType::SignIn, G()->net_query_creator().create_unauth(telegram_api::auth_signIn( + flags, send_code_helper_.phone_number().str(), + send_code_helper_.phone_code_hash().str(), code_, nullptr))); } void AuthManager::register_user(uint64 query_id, string first_name, string last_name) { @@ -615,9 +616,10 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) { set_login_token_expires_at(Time::now() + login_code_retry_delay_); return; } else { - start_net_query(NetQueryType::SignIn, - G()->net_query_creator().create_unauth(telegram_api::auth_signIn( - send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_))); + int32 flags = telegram_api::auth_signIn::PHONE_CODE_MASK; + start_net_query(NetQueryType::SignIn, G()->net_query_creator().create_unauth(telegram_api::auth_signIn( + flags, send_code_helper_.phone_number().str(), + send_code_helper_.phone_code_hash().str(), code_, nullptr))); return; } diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 0a4e3f549..2748c2acc 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -9073,7 +9073,7 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) { false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, user_id.get(), 1, first_name, string(), username, - phone_number, std::move(profile_photo), nullptr, bot_info_version, Auto(), string(), string()); + phone_number, std::move(profile_photo), nullptr, bot_info_version, Auto(), string(), string(), nullptr); on_get_user(std::move(user), "get_user_force"); u = get_user(user_id); CHECK(u != nullptr && u->is_received); diff --git a/td/telegram/DialogEventLog.cpp b/td/telegram/DialogEventLog.cpp index 41d7b65c0..76763f1f4 100644 --- a/td/telegram/DialogEventLog.cpp +++ b/td/telegram/DialogEventLog.cpp @@ -346,8 +346,7 @@ static td_api::object_ptr get_chat_event_action_object( } case telegram_api::channelAdminLogEventActionChangeAvailableReactions::ID: { auto action = move_tl_object_as(action_ptr); - return td_api::make_object(std::move(action->prev_value_), - std::move(action->new_value_)); + return nullptr; } default: UNREACHABLE(); diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 25561d0df..d0f10c48a 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -183,8 +183,8 @@ class RequestSimpleWebViewQuery final : public Td::ResultHandler { theme_parameters = make_tl_object(string()); theme_parameters->data_ = ThemeManager::get_theme_parameters_json_string(theme, false); } - send_query(G()->net_query_creator().create( - telegram_api::messages_requestSimpleWebView(flags, std::move(input_user), url, std::move(theme_parameters)))); + send_query(G()->net_query_creator().create(telegram_api::messages_requestSimpleWebView( + flags, std::move(input_user), url, std::move(theme_parameters), string()))); } void on_result(BufferSlice packet) final { diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index ca6a429c4..4153b1c3a 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -31,6 +31,30 @@ namespace td { +static telegram_api::object_ptr get_input_reaction(const string &reaction) { + if (reaction.empty()) { + return telegram_api::make_object(); + } + return telegram_api::make_object(reaction); +} + +static string get_reaction_string(const telegram_api::object_ptr &reaction) { + if (reaction == nullptr) { + return string(); + } + switch (reaction->get_id()) { + case telegram_api::reactionEmpty::ID: + return string(); + case telegram_api::reactionEmoji::ID: + return static_cast(reaction.get())->emoticon_; + case telegram_api::reactionCustomEmoji::ID: + return string(); + default: + UNREACHABLE(); + return string(); + } +} + class GetMessagesReactionsQuery final : public Td::ResultHandler { DialogId dialog_id_; vector message_ids_; @@ -108,9 +132,15 @@ class SendReactionQuery final : public Td::ResultHandler { } } + vector> reactions; + if (!reaction.empty()) { + reactions.push_back(get_input_reaction(reaction)); + } + send_query(G()->net_query_creator().create( - telegram_api::messages_sendReaction(flags, false /*ignored*/, std::move(input_peer), - full_message_id.get_message_id().get_server_message_id().get(), reaction), + telegram_api::messages_sendReaction(flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), + full_message_id.get_message_id().get_server_message_id().get(), + std::move(reactions)), {{dialog_id_}, {full_message_id}})); } @@ -163,8 +193,9 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler { } send_query(G()->net_query_creator().create( - telegram_api::messages_getMessageReactionsList( - flags, std::move(input_peer), message_id_.get_server_message_id().get(), reaction_, offset_, limit), + telegram_api::messages_getMessageReactionsList(flags, std::move(input_peer), + message_id_.get_server_message_id().get(), + get_input_reaction(reaction_), offset_, limit), {{full_message_id}})); } @@ -191,19 +222,19 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler { FlatHashMap> recent_reactions; for (const auto &reaction : ptr->reactions_) { DialogId dialog_id(reaction->peer_id_); - if (!dialog_id.is_valid() || - (reaction_.empty() ? reaction->reaction_.empty() : reaction_ != reaction->reaction_)) { + auto reaction_str = get_reaction_string(reaction->reaction_); + if (!dialog_id.is_valid() || (reaction_.empty() ? reaction_str.empty() : reaction_ != reaction_str)) { LOG(ERROR) << "Receive unexpected " << to_string(reaction); continue; } if (offset_.empty()) { - recent_reactions[reaction->reaction_].push_back(dialog_id); + recent_reactions[reaction_str].push_back(dialog_id); } auto message_sender = get_min_message_sender_object(td_, dialog_id, "GetMessageReactionsListQuery"); if (message_sender != nullptr) { - reactions.push_back(td_api::make_object(reaction->reaction_, std::move(message_sender))); + reactions.push_back(td_api::make_object(reaction_str, std::move(message_sender))); } } @@ -228,7 +259,8 @@ class SetDefaultReactionQuery final : public Td::ResultHandler { public: void send(const string &reaction) { reaction_ = reaction; - send_query(G()->net_query_creator().create(telegram_api::messages_setDefaultReaction(reaction))); + send_query( + G()->net_query_creator().create(telegram_api::messages_setDefaultReaction(get_input_reaction(reaction)))); } void on_result(BufferSlice packet) final { @@ -367,22 +399,23 @@ unique_ptr MessageReactions::get_message_reactions( FlatHashSet reaction_strings; FlatHashSet recent_choosers; for (auto &reaction_count : reactions->results_) { + auto reaction_str = get_reaction_string(reaction_count->reaction_); if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT || - reaction_count->reaction_.empty()) { - LOG(ERROR) << "Receive reaction " << reaction_count->reaction_ << " with invalid count " - << reaction_count->count_; + reaction_str.empty()) { + LOG(ERROR) << "Receive reaction " << reaction_str << " with invalid count " << reaction_count->count_; continue; } - if (!reaction_strings.insert(reaction_count->reaction_).second) { - LOG(ERROR) << "Receive duplicate reaction " << reaction_count->reaction_; + if (!reaction_strings.insert(reaction_str).second) { + LOG(ERROR) << "Receive duplicate reaction " << reaction_str; continue; } vector recent_chooser_dialog_ids; vector> recent_chooser_min_channels; for (auto &peer_reaction : reactions->recent_reactions_) { - if (peer_reaction->reaction_ == reaction_count->reaction_) { + auto peer_reaction_str = get_reaction_string(peer_reaction->reaction_); + if (peer_reaction_str == reaction_str) { DialogId dialog_id(peer_reaction->peer_id_); if (!dialog_id.is_valid()) { LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser"; @@ -416,7 +449,7 @@ unique_ptr MessageReactions::get_message_reactions( recent_chooser_dialog_ids.push_back(dialog_id); if (peer_reaction->unread_) { - result->unread_reactions_.emplace_back(std::move(peer_reaction->reaction_), dialog_id, peer_reaction->big_); + result->unread_reactions_.emplace_back(std::move(peer_reaction_str), dialog_id, peer_reaction->big_); } if (recent_chooser_dialog_ids.size() == MessageReaction::MAX_RECENT_CHOOSERS) { break; @@ -424,9 +457,8 @@ unique_ptr MessageReactions::get_message_reactions( } } - result->reactions_.emplace_back(std::move(reaction_count->reaction_), reaction_count->count_, - reaction_count->chosen_, std::move(recent_chooser_dialog_ids), - std::move(recent_chooser_min_channels)); + result->reactions_.emplace_back(std::move(reaction_str), reaction_count->count_, reaction_count->chosen_order_ != 0, + std::move(recent_chooser_dialog_ids), std::move(recent_chooser_min_channels)); } return result; } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 25913c59d..712fee75f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1428,8 +1428,8 @@ class SetChatAvailableReactionsQuery final : public Td::ResultHandler { if (input_peer == nullptr) { return on_error(Status::Error(400, "Can't access the chat")); } - send_query(G()->net_query_creator().create( - telegram_api::messages_setChatAvailableReactions(std::move(input_peer), std::move(available_reactions)))); + send_query(G()->net_query_creator().create(telegram_api::messages_setChatAvailableReactions( + std::move(input_peer), make_tl_object()))); } void on_result(BufferSlice packet) final { @@ -3208,8 +3208,8 @@ class SendMessageQuery final : public Td::ResultHandler { auto query = G()->net_query_creator().create( telegram_api::messages_sendMessage( flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - std::move(input_peer), reply_to_message_id.get_server_message_id().get(), text, random_id, - std::move(reply_markup), std::move(entities), schedule_date, std::move(as_input_peer)), + false /*ignored*/, std::move(input_peer), reply_to_message_id.get_server_message_id().get(), text, + random_id, std::move(reply_markup), std::move(entities), schedule_date, std::move(as_input_peer)), {{dialog_id, MessageContentType::Text}, {dialog_id, is_copy ? MessageContentType::Photo : MessageContentType::Text}}); if (td_->option_manager_->get_option_boolean("use_quick_ack")) { @@ -3404,7 +3404,7 @@ class SendMultiMediaQuery final : public Td::ResultHandler { CHECK(reply_to_message_id == MessageId() || reply_to_message_id.is_server()); send_query(G()->net_query_creator().create( telegram_api::messages_sendMultiMedia(flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, - false /*ignored*/, std::move(input_peer), + false /*ignored*/, false /*ignored*/, std::move(input_peer), reply_to_message_id.get_server_message_id().get(), std::move(input_single_media), schedule_date, std::move(as_input_peer)), {{dialog_id, is_copy ? MessageContentType::Text : MessageContentType::Photo}, @@ -3521,9 +3521,9 @@ class SendMediaQuery final : public Td::ResultHandler { CHECK(reply_to_message_id == MessageId() || reply_to_message_id.is_server()); auto query = G()->net_query_creator().create( telegram_api::messages_sendMedia( - flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(input_peer), - reply_to_message_id.get_server_message_id().get(), std::move(input_media), text, random_id, - std::move(reply_markup), std::move(entities), schedule_date, std::move(as_input_peer)), + flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, + std::move(input_peer), reply_to_message_id.get_server_message_id().get(), std::move(input_media), text, + random_id, std::move(reply_markup), std::move(entities), schedule_date, std::move(as_input_peer)), {{dialog_id, content_type}, {dialog_id, is_copy ? MessageContentType::Text : content_type}}); if (td_->option_manager_->get_option_boolean("use_quick_ack") && was_uploaded_) { query->quick_ack_promise_ = PromiseCreator::lambda([random_id](Result result) { @@ -8114,7 +8114,8 @@ void MessagesManager::on_update_dialog_notify_settings( update_dialog_notification_settings(dialog_id, current_settings, std::move(notification_settings)); } -void MessagesManager::on_update_dialog_available_reactions(DialogId dialog_id, vector &&available_reactions) { +void MessagesManager::on_update_dialog_available_reactions( + DialogId dialog_id, telegram_api::object_ptr &&available_reactions) { if (td_->auth_manager_->is_bot()) { return; } @@ -8124,7 +8125,8 @@ void MessagesManager::on_update_dialog_available_reactions(DialogId dialog_id, v return; } - set_dialog_available_reactions(d, std::move(available_reactions)); + vector legacy_available_reactions; + set_dialog_available_reactions(d, std::move(legacy_available_reactions)); } void MessagesManager::set_dialog_available_reactions(Dialog *d, vector &&available_reactions) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 849a8e2ae..d0ba6bdc6 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -144,6 +144,7 @@ class MessagesManager final : public Actor { static constexpr int32 SEND_MESSAGE_FLAG_HAS_MESSAGE = 1 << 11; static constexpr int32 SEND_MESSAGE_FLAG_HAS_SEND_AS = 1 << 13; static constexpr int32 SEND_MESSAGE_FLAG_NOFORWARDS = 1 << 14; + static constexpr int32 SEND_MESSAGE_FLAG_UPDATE_STICKER_SETS_ORDER = 1 << 15; static constexpr int32 ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME = 30 * 60; @@ -861,7 +862,8 @@ class MessagesManager final : public Actor { tl_object_ptr &&peer_notify_settings, const char *source); - void on_update_dialog_available_reactions(DialogId dialog_id, vector &&available_reactions); + void on_update_dialog_available_reactions( + DialogId dialog_id, telegram_api::object_ptr &&available_reactions); void hide_dialog_action_bar(DialogId dialog_id); diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 7409d0ec3..a82aebf5a 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -3328,7 +3328,7 @@ Status NotificationManager::process_push_notification_payload(string payload, bo false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), sender_access_hash, user_name, - string(), string(), string(), std::move(sender_photo), nullptr, 0, Auto(), string(), string()); + string(), string(), string(), std::move(sender_photo), nullptr, 0, Auto(), string(), string(), nullptr); td_->contacts_manager_->on_get_user(std::move(user), "process_push_notification_payload"); } @@ -3686,7 +3686,7 @@ void NotificationManager::add_message_push_notification(DialogId dialog_id, Mess false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), 0, user_name, string(), string(), - string(), nullptr, nullptr, 0, Auto(), string(), string()); + string(), nullptr, nullptr, 0, Auto(), string(), string(), nullptr); td_->contacts_manager_->on_get_user(std::move(user), "add_message_push_notification"); } diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index e95900e03..765c78253 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -423,7 +423,8 @@ void PasswordManager::resend_recovery_email_address_code(Promise promise) void PasswordManager::send_email_address_verification_code( string email, Promise> promise) { last_verified_email_address_ = email; - auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode(std::move(email))); + auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode( + make_tl_object(), std::move(email))); send_with_promise( std::move(query), PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { auto r_result = fetch_result(std::move(r_query)); @@ -452,8 +453,9 @@ void PasswordManager::check_email_address_verification_code(string code, Promise if (last_verified_email_address_.empty()) { return promise.set_error(Status::Error(400, "No email address verification was sent")); } - auto query = - G()->net_query_creator().create(telegram_api::account_verifyEmail(last_verified_email_address_, std::move(code))); + auto verification_code = make_tl_object(std::move(code)); + auto query = G()->net_query_creator().create(telegram_api::account_verifyEmail( + make_tl_object(), std::move(verification_code))); send_with_promise(std::move(query), PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { auto r_result = fetch_result(std::move(r_query)); diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index b43df2ccf..c0fab14ca 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -130,14 +130,6 @@ class GetPremiumPromoQuery final : public Td::ResultHandler { return on_error(Status::Error(500, "Receive wrong number of videos")); } - if (promo->monthly_amount_ < 0 || !check_currency_amount(promo->monthly_amount_)) { - return on_error(Status::Error(500, "Receive invalid monthly amount")); - } - - if (promo->currency_.size() != 3) { - return on_error(Status::Error(500, "Receive invalid currency")); - } - vector> animations; for (size_t i = 0; i < promo->video_sections_.size(); i++) { auto feature = get_premium_feature_object(promo->video_sections_[i]); @@ -164,8 +156,7 @@ class GetPremiumPromoQuery final : public Td::ResultHandler { std::move(animation_object))); } - promise_.set_value(td_api::make_object(get_formatted_text_object(state, true, 0), - std::move(promo->currency_), promo->monthly_amount_, + promise_.set_value(td_api::make_object(get_formatted_text_object(state, true, 0), "USD", 499, std::move(animations))); } diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index 3a2d69f03..025532a65 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -141,6 +141,14 @@ SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_i return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::MissedCall, code_type->length_, std::move(code_type->prefix_)}; } + case telegram_api::auth_sentCodeTypeEmailCode::ID: { + auto code_type = move_tl_object_as(sent_code_type_ptr); + return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::Message, code_type->length_, ""}; + } + case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: { + auto code_type = move_tl_object_as(sent_code_type_ptr); + return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::Message, 0, ""}; + } default: UNREACHABLE(); return AuthenticationCodeInfo(); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index ffde03cc9..d4326002b 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3570,4 +3570,20 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + promise.set_value(Unit()); +} + +void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + promise.set_value(Unit()); +} + +void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + promise.set_value(Unit()); +} + +void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + promise.set_value(Unit()); +} + } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index dd4e9291e..17f97560e 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -535,6 +535,14 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); // unsupported updates + + void on_update(tl_object_ptr update, Promise &&promise); + + void on_update(tl_object_ptr update, Promise &&promise); + + void on_update(tl_object_ptr update, Promise &&promise); + + void on_update(tl_object_ptr update, Promise &&promise); }; } // namespace td diff --git a/td/telegram/Version.h b/td/telegram/Version.h index 7d74db9b8..b53466f6a 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -10,7 +10,7 @@ namespace td { -constexpr int32 MTPROTO_LAYER = 144; +constexpr int32 MTPROTO_LAYER = 145; enum class Version : int32 { Initial, // 0 From ff039e21952d1d1802c46f74af2a639e74d4f338 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 8 Aug 2022 23:41:06 +0300 Subject: [PATCH 002/200] Add user.premium_badge_custom_emoji_id. --- td/generate/scheme/td_api.tl | 3 ++- td/telegram/ContactsManager.cpp | 30 ++++++++++++++++++++++++++---- td/telegram/ContactsManager.h | 2 ++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 823f8e524..a38e821c9 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -484,6 +484,7 @@ premiumGiftOption currency:string amount:int53 discount_percentage:int32 month_c //@phone_number Phone number of the user //@status Current online status of the user //@profile_photo Profile photo of the user; may be null +//@premium_badge_custom_emoji_id Identifier of the custom emoji to be shown instead of the Telegram Premium badge; 0 if none. For Telegram Premium users only //@is_contact The user is a contact of the current user //@is_mutual_contact The user is a contact of the current user and the current user is a contact of the user //@is_verified True, if the user is verified @@ -496,7 +497,7 @@ premiumGiftOption currency:string amount:int53 discount_percentage:int32 month_c //@type Type of the user //@language_code IETF language tag of the user's language; only available to bots //@added_to_attachment_menu True, if the user added the current bot to attachment menu; only available to bots -user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; +user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto premium_badge_custom_emoji_id:int64 is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; //@description Contains information about a bot diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 2748c2acc..82428b4cd 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3621,6 +3621,7 @@ void ContactsManager::User::store(StorerT &storer) const { bool has_cache_version = cache_version != 0; bool has_is_contact = true; bool has_restriction_reasons = !restriction_reasons.empty(); + bool has_emoji_status = emoji_status != 0; BEGIN_STORE_FLAGS(); STORE_FLAG(is_received); STORE_FLAG(is_verified); @@ -3649,6 +3650,7 @@ void ContactsManager::User::store(StorerT &storer) const { STORE_FLAG(can_be_added_to_attach_menu); STORE_FLAG(is_premium); // 25 STORE_FLAG(attach_menu_enabled); + STORE_FLAG(has_emoji_status); END_STORE_FLAGS(); store(first_name, storer); if (has_last_name) { @@ -3680,6 +3682,9 @@ void ContactsManager::User::store(StorerT &storer) const { if (has_cache_version) { store(cache_version, storer); } + if (has_emoji_status) { + store(emoji_status, storer); + } } template @@ -3694,6 +3699,7 @@ void ContactsManager::User::parse(ParserT &parser) { bool has_cache_version; bool has_is_contact; bool has_restriction_reasons; + bool has_emoji_status; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_received); PARSE_FLAG(is_verified); @@ -3722,6 +3728,7 @@ void ContactsManager::User::parse(ParserT &parser) { PARSE_FLAG(can_be_added_to_attach_menu); PARSE_FLAG(is_premium); PARSE_FLAG(attach_menu_enabled); + PARSE_FLAG(has_emoji_status); END_PARSE_FLAGS(); parse(first_name, parser); if (has_last_name) { @@ -3773,6 +3780,9 @@ void ContactsManager::User::parse(ParserT &parser) { if (has_cache_version) { parse(cache_version, parser); } + if (has_emoji_status) { + parse(emoji_status, parser); + } if (!check_utf8(first_name)) { LOG(ERROR) << "Have invalid first name \"" << first_name << '"'; @@ -8692,6 +8702,10 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, bool has_bot_info_version = (flags & USER_FLAG_HAS_BOT_INFO_VERSION) != 0; bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0; bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0; + int64 emoji_status = 0; + if (user->emoji_status_ != nullptr && user->emoji_status_->get_id() == telegram_api::emojiStatus::ID) { + emoji_status = static_cast(user->emoji_status_.get())->document_id_; + } LOG_IF(ERROR, !can_join_groups && !is_bot) << "Receive not bot " << user_id << " which can't join groups from " << source; @@ -8723,6 +8737,13 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, << "Receive not bot " << user_id << " which has bot info version from " << source; int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; + if (u->emoji_status != emoji_status) { + if ((u->is_premium ? u->emoji_status : 0) != (is_premium ? emoji_status : 0)) { + u->is_changed = true; + } + u->emoji_status = emoji_status; + u->need_save_to_database = true; + } if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support || is_bot != u->is_bot || can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages || restriction_reasons != u->restriction_reasons || @@ -16641,7 +16662,7 @@ td_api::object_ptr ContactsManager::get_user_status_object(U td_api::object_ptr ContactsManager::get_update_unknown_user_object(UserId user_id) { return td_api::make_object(td_api::make_object( - user_id.get(), "", "", "", "", td_api::make_object(), nullptr, false, false, false, + user_id.get(), "", "", "", "", td_api::make_object(), nullptr, 0, false, false, false, false, false, "", false, false, false, td_api::make_object(), "", false)); } @@ -16673,11 +16694,12 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } + int64 emoji_status = u->is_premium ? u->emoji_status : 0; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), - get_profile_photo_object(td_->file_manager_.get(), u->photo), u->is_contact, u->is_mutual_contact, u->is_verified, - u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, - u->is_received, std::move(type), u->language_code, u->attach_menu_enabled); + get_profile_photo_object(td_->file_manager_.get(), u->photo), emoji_status, u->is_contact, u->is_mutual_contact, + u->is_verified, u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), + u->is_scam, u->is_fake, u->is_received, std::move(type), u->language_code, u->attach_menu_enabled); } vector ContactsManager::get_user_ids_object(const vector &user_ids, const char *source) const { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 3f1abcc59..ce4a9a31c 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -641,6 +641,7 @@ class ContactsManager final : public Actor { string username; string phone_number; int64 access_hash = -1; + int64 emoji_status = 0; ProfilePhoto photo; @@ -1070,6 +1071,7 @@ class ContactsManager final : public Actor { static constexpr int32 USER_FLAG_IS_ATTACH_MENU_BOT = 1 << 27; static constexpr int32 USER_FLAG_IS_PREMIUM = 1 << 28; static constexpr int32 USER_FLAG_ATTACH_MENU_ENABLED = 1 << 29; + static constexpr int32 USER_FLAG_HAS_EMOJI_STATUS = 1 << 30; static constexpr int32 USER_FULL_FLAG_IS_BLOCKED = 1 << 0; static constexpr int32 USER_FULL_FLAG_HAS_ABOUT = 1 << 1; From 02b42d7ee683d033553e23301c2e93b5fdb1b69f Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 9 Aug 2022 15:49:47 +0300 Subject: [PATCH 003/200] Add td_api::setPremiumBadge. --- td/generate/scheme/td_api.tl | 3 ++ td/telegram/ContactsManager.cpp | 62 +++++++++++++++++++++++++++++++++ td/telegram/ContactsManager.h | 4 +++ td/telegram/Td.cpp | 6 ++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 79 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a38e821c9..0ff6cf40e 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6053,6 +6053,9 @@ setBio bio:string = Ok; //@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username setUsername username:string = Ok; +//@description Changes the premium badge of the current user; for Telegram Premium users only @custom_emoji_id Identifier of the custom emoji to use as premium badge; pass 0 to switch to default badge. The custom emoji must have stickerFormatTgs +setPremiumBadge custom_emoji_id:int64 = Ok; + //@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user setLocation location:location = Ok; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 82428b4cd..4cb6fede8 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -670,6 +670,42 @@ class UpdateUsernameQuery final : public Td::ResultHandler { } }; +class UpdateEmojiStatusQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit UpdateEmojiStatusQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(int64 custom_emoji_id) { + auto emoji_status = [custom_emoji_id]() -> telegram_api::object_ptr { + if (custom_emoji_id == 0) { + return make_tl_object(); + } + return make_tl_object(custom_emoji_id); + }(); + send_query(G()->net_query_creator().create(telegram_api::account_updateEmojiStatus(std::move(emoji_status)))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + LOG(DEBUG) << "Receive result for UpdateEmojiStatusQuery: " << result_ptr.ok(); + if (result_ptr.ok()) { + promise_.set_value(Unit()); + } else { + promise_.set_error(Status::Error(400, "Failed to change Premium badge")); + } + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + class CheckChannelUsernameQuery final : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; @@ -6565,6 +6601,32 @@ void ContactsManager::set_username(const string &username, Promise &&promi td_->create_handler(std::move(promise))->send(username); } +void ContactsManager::set_emoji_status(int64 custom_emoji_id, Promise &&promise) { + if (!td_->option_manager_->get_option_boolean("is_premium")) { + return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users")); + } + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), custom_emoji_id, promise = std::move(promise)](Result result) mutable { + if (result.is_ok()) { + send_closure(actor_id, &ContactsManager::on_set_emoji_status, custom_emoji_id, std::move(promise)); + } else { + promise.set_error(result.move_as_error()); + } + }); + td_->create_handler(std::move(query_promise))->send(custom_emoji_id); +} + +void ContactsManager::on_set_emoji_status(int64 custom_emoji_id, Promise &&promise) { + auto user_id = get_my_id(); + User *u = get_user(user_id); + if (u != nullptr && u->emoji_status != custom_emoji_id) { + u->emoji_status = custom_emoji_id; + u->is_changed = true; + update_user(u, user_id); + } + promise.set_value(Unit()); +} + void ContactsManager::set_chat_description(ChatId chat_id, const string &description, Promise &&promise) { auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH); auto c = get_chat(chat_id); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index ce4a9a31c..16b2b98ca 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -343,6 +343,8 @@ class ContactsManager final : public Actor { void set_username(const string &username, Promise &&promise); + void set_emoji_status(int64 suctom_emoji_id, Promise &&promise); + void set_chat_description(ChatId chat_id, const string &description, Promise &&promise); void set_channel_username(ChannelId channel_id, const string &username, Promise &&promise); @@ -1248,6 +1250,8 @@ class ContactsManager final : public Actor { static bool is_valid_username(const string &username); + void on_set_emoji_status(int64 custom_emoji_id, Promise &&promise); + void on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name, string &&username); void on_update_user_phone_number(User *u, UserId user_id, string &&phone_number); void on_update_user_photo(User *u, UserId user_id, tl_object_ptr &&photo, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f0c287b24..bc809f5bb 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6723,6 +6723,12 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { contacts_manager_->set_username(request.username_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::setPremiumBadge &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + contacts_manager_->set_emoji_status(request.custom_emoji_id_, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index e2a292089..bd70e3e48 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1010,6 +1010,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setUsername &request); + void on_request(uint64 id, const td_api::setPremiumBadge &request); + void on_request(uint64 id, td_api::setCommands &request); void on_request(uint64 id, td_api::deleteCommands &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 114fd27e0..b1707551b 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4456,6 +4456,8 @@ class CliClient final : public Actor { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); } else if (op == "sun") { send_request(td_api::make_object(args)); + } else if (op == "spb") { + send_request(td_api::make_object(to_integer(args))); } else if (op == "ccun") { ChatId chat_id; string username; From b14708f0f54356e9572a14c14ad0d409773d8536 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 16 Aug 2022 22:42:29 +0300 Subject: [PATCH 004/200] Support reactions with custom emoji. --- td/generate/scheme/td_api.tl | 31 +++++++++++------- td/telegram/MessageReaction.cpp | 58 +++++++++++++++++++++++++++++++-- td/telegram/MessageReaction.h | 2 ++ td/telegram/Td.cpp | 9 +++-- td/telegram/cli.cpp | 19 +++++++++-- 5 files changed, 97 insertions(+), 22 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0ff6cf40e..a385c3fe9 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -808,6 +808,15 @@ messageForwardOriginChannel chat_id:int53 message_id:int53 author_signature:stri messageForwardOriginMessageImport sender_name:string = MessageForwardOrigin; +//@class ReactionType @description Describes type of message reaction + +//@description A reaction with an emoji @emoji Text representation of the reaction +reactionTypeEmoji emoji:string = ReactionType; + +//@description A reaction with a custom emoji @custom_emoji_id Unique identifier of the custom emoji +reactionTypeCustomEmoji custom_emoji_id:int64 = ReactionType; + + //@description Contains information about a forwarded message //@origin Origin of a forwarded message //@date Point in time (Unix timestamp) when the message was originally sent @@ -825,11 +834,11 @@ messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announc messageReplyInfo reply_count:int32 recent_replier_ids:vector last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 last_message_id:int53 = MessageReplyInfo; //@description Contains information about a reaction to a message -//@reaction Text representation of the reaction +//@type Type of the reaction //@total_count Number of times the reaction was added //@is_chosen True, if the reaction is chosen by the current user //@recent_sender_ids Identifiers of at most 3 recent message senders, added the reaction; available in private, basic group and supergroup chats -messageReaction reaction:string total_count:int32 is_chosen:Bool recent_sender_ids:vector = MessageReaction; +messageReaction type:ReactionType total_count:int32 is_chosen:Bool recent_sender_ids:vector = MessageReaction; //@description Contains information about interactions with a message //@view_count Number of times the message was viewed @@ -839,10 +848,10 @@ messageReaction reaction:string total_count:int32 is_chosen:Bool recent_sender_i messageInteractionInfo view_count:int32 forward_count:int32 reply_info:messageReplyInfo reactions:vector = MessageInteractionInfo; //@description Contains information about an unread reaction to a message -//@reaction Text representation of the reaction +//@type Type of the reaction //@sender_id Identifier of the sender, added the reaction //@is_big True, if the reaction was added with a big animation -unreadReaction reaction:string sender_id:MessageSender is_big:Bool = UnreadReaction; +unreadReaction type:ReactionType sender_id:MessageSender is_big:Bool = UnreadReaction; //@class MessageSendingState @description Contains information about the sending state of the message @@ -2547,8 +2556,8 @@ call id:int32 user_id:int53 is_outgoing:Bool is_video:Bool state:CallState = Cal phoneNumberAuthenticationSettings allow_flash_call:Bool allow_missed_call:Bool is_current_phone_number:Bool allow_sms_retriever_api:Bool authentication_tokens:vector = PhoneNumberAuthenticationSettings; -//@description Represents a reaction applied to a message @reaction Text representation of the reaction @sender_id Identifier of the chat member, applied the reaction -addedReaction reaction:string sender_id:MessageSender = AddedReaction; +//@description Represents a reaction applied to a message @type Type of the reaction @sender_id Identifier of the chat member, applied the reaction +addedReaction type:ReactionType sender_id:MessageSender = AddedReaction; //@description Represents a list of reactions added to a message @total_count The total number of found reactions @reactions The list of added reactions @next_offset The offset for the next request. If empty, there are no more results addedReactions total_count:int32 reactions:vector next_offset:string = AddedReactions; @@ -2560,7 +2569,7 @@ availableReaction reaction:string needs_premium:Bool = AvailableReaction; availableReactions reactions:vector = AvailableReactions; -//@description Contains stickers which must be used for reaction animation rendering +//@description Contains stickers which must be used for emoji reaction animation rendering //@reaction Text representation of the reaction //@title Reaction title //@is_active True, if the reaction can be added to new messages and enabled in chats @@ -5116,17 +5125,17 @@ getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions //@description Changes chosen reaction for a message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message -//@reaction Text representation of the new chosen reaction. Can be an empty string or the currently chosen non-big reaction to remove the reaction +//@reaction_type Type of the new chosen reaction; pass null or the currently chosen non-big reaction to remove the reaction //@is_big Pass true if the reaction is added with a big animation -setMessageReaction chat_id:int53 message_id:int53 reaction:string is_big:Bool = Ok; +setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_big:Bool = Ok; //@description Returns reactions added for a message, along with their sender //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message -//@reaction If non-empty, only added reactions with the specified text representation will be returned +//@reaction_type Type of the reactions to return; pass null to return all added reactions //@offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results //@limit The maximum number of reactions to be returned; must be positive and can't be greater than 100 -getMessageAddedReactions chat_id:int53 message_id:int53 reaction:string offset:string limit:int32 = AddedReactions; +getMessageAddedReactions chat_id:int53 message_id:int53 reaction_type:ReactionType offset:string limit:int32 = AddedReactions; //@description Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) contained in the text. Can be called synchronously @text The text in which to look for entites diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 4153b1c3a..d41ba3c0e 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -21,20 +21,39 @@ #include "td/actor/actor.h" #include "td/utils/algorithm.h" +#include "td/utils/as.h" +#include "td/utils/base64.h" #include "td/utils/buffer.h" #include "td/utils/FlatHashSet.h" #include "td/utils/logging.h" #include "td/utils/Status.h" +#include "td/utils/utf8.h" #include #include namespace td { +static int64 get_custom_emoji_id(const string &reaction) { + auto r_decoded = base64_decode(Slice(&reaction[1], reaction.size() - 1)); + CHECK(r_decoded.is_ok()); + CHECK(r_decoded.ok().size() == 8); + return as(r_decoded.ok().c_str()); +} + +static string get_custom_emoji_string(int64 custom_emoji_id) { + char s[8]; + as(&s) = custom_emoji_id; + return PSTRING() << '#' << base64_encode(Slice(s, 8)); +} + static telegram_api::object_ptr get_input_reaction(const string &reaction) { if (reaction.empty()) { return telegram_api::make_object(); } + if (reaction[0] == '#') { + return telegram_api::make_object(get_custom_emoji_id(reaction)); + } return telegram_api::make_object(reaction); } @@ -48,7 +67,37 @@ static string get_reaction_string(const telegram_api::object_ptr(reaction.get())->emoticon_; case telegram_api::reactionCustomEmoji::ID: + return get_custom_emoji_string( + static_cast(reaction.get())->document_id_); + default: + UNREACHABLE(); return string(); + } +} + +static td_api::object_ptr get_reaction_type_object(const string &reaction) { + CHECK(!reaction.empty()); + if (reaction[0] == '#') { + return td_api::make_object(get_custom_emoji_id(reaction)); + } + return td_api::make_object(reaction); +} + +string get_message_reaction_string(const td_api::object_ptr &type) { + if (type == nullptr) { + return string(); + } + switch (type->get_id()) { + case td_api::reactionTypeEmoji::ID: { + const string &emoji = static_cast(type.get())->emoji_; + if (!check_utf8(emoji)) { + return string(); + } + return emoji; + } + case td_api::reactionTypeCustomEmoji::ID: + return get_custom_emoji_string( + static_cast(type.get())->custom_emoji_id_); default: UNREACHABLE(); return string(); @@ -234,7 +283,8 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler { auto message_sender = get_min_message_sender_object(td_, dialog_id, "GetMessageReactionsListQuery"); if (message_sender != nullptr) { - reactions.push_back(td_api::make_object(reaction_str, std::move(message_sender))); + reactions.push_back(td_api::make_object(get_reaction_type_object(reaction_str), + std::move(message_sender))); } } @@ -353,7 +403,8 @@ td_api::object_ptr MessageReaction::get_message_reactio } } } - return td_api::make_object(reaction_, choose_count_, is_chosen_, std::move(recent_choosers)); + return td_api::make_object(get_reaction_type_object(reaction_), choose_count_, is_chosen_, + std::move(recent_choosers)); } bool operator==(const MessageReaction &lhs, const MessageReaction &rhs) { @@ -374,7 +425,8 @@ td_api::object_ptr UnreadMessageReaction::get_unread_rea if (sender_id == nullptr) { return nullptr; } - return td_api::make_object(reaction_, std::move(sender_id), is_big_); + return td_api::make_object(get_reaction_type_object(reaction_), std::move(sender_id), + is_big_); } bool operator==(const UnreadMessageReaction &lhs, const UnreadMessageReaction &rhs) { diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index e46593921..bdb50b345 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -173,6 +173,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr &reactions); +string get_message_reaction_string(const td_api::object_ptr &type); + void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids); void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index bc809f5bb..e8758db65 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5249,20 +5249,19 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque void Td::on_request(uint64 id, td_api::setMessageReaction &request) { CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.reaction_); CREATE_OK_REQUEST_PROMISE(); messages_manager_->set_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)}, - std::move(request.reaction_), request.is_big_, std::move(promise)); + get_message_reaction_string(request.reaction_type_), request.is_big_, + std::move(promise)); } void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) { CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.reaction_); CLEAN_INPUT_STRING(request.offset_); CREATE_REQUEST_PROMISE(); get_message_added_reactions(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, - std::move(request.reaction_), std::move(request.offset_), request.limit_, - std::move(promise)); + get_message_reaction_string(request.reaction_type_), std::move(request.offset_), + request.limit_, std::move(promise)); } void Td::on_request(uint64 id, td_api::getMessagePublicForwards &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b1707551b..8ef5d01b6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -724,6 +724,18 @@ class CliClient final : public Actor { return td_api::make_object(to_double(latitude), to_double(longitude), to_double(accuracy)); } + td_api::object_ptr as_reaction_type(Slice type) const { + type = trim(type); + if (type.empty()) { + return nullptr; + } + auto r_custom_emoji_id = to_integer_safe(type); + if (r_custom_emoji_id.is_ok()) { + return td_api::make_object(r_custom_emoji_id.ok()); + } + return td_api::make_object(type.str()); + } + static bool as_bool(string str) { str = to_lower(trim(str)); return str == "true" || str == "1"; @@ -2215,7 +2227,8 @@ class CliClient final : public Actor { string reaction; bool is_big; get_args(args, chat_id, message_id, reaction, is_big); - send_request(td_api::make_object(chat_id, message_id, reaction, is_big)); + send_request( + td_api::make_object(chat_id, message_id, as_reaction_type(reaction), is_big)); } else if (op == "gmars") { ChatId chat_id; MessageId message_id; @@ -2223,8 +2236,8 @@ class CliClient final : public Actor { string offset; string limit; get_args(args, chat_id, message_id, reaction, offset, limit); - send_request(td_api::make_object(chat_id, message_id, reaction, offset, - as_limit(limit))); + send_request(td_api::make_object( + chat_id, message_id, as_reaction_type(reaction), offset, as_limit(limit))); } else if (op == "gmpf") { ChatId chat_id; MessageId message_id; From 2a2787b7ede6e02b18d0d7c47d28b70594f16c99 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 16 Aug 2022 23:08:36 +0300 Subject: [PATCH 005/200] Add td_api::setDefaultReactionType. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/ConfigManager.cpp | 8 -------- td/telegram/MessageReaction.cpp | 3 ++- td/telegram/MessageReaction.hpp | 2 ++ td/telegram/OptionManager.cpp | 13 +------------ td/telegram/Td.cpp | 6 ++++++ td/telegram/Td.h | 2 ++ 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a385c3fe9..c0a3b20b0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5137,6 +5137,9 @@ setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_ //@limit The maximum number of reactions to be returned; must be positive and can't be greater than 100 getMessageAddedReactions chat_id:int53 message_id:int53 reaction_type:ReactionType offset:string limit:int32 = AddedReactions; +//@description Changes default reaction type for the current user @reaction_type New type of the default reaction +setDefaultReactionType reaction_type:ReactionType = Ok; + //@description Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) contained in the text. Can be called synchronously @text The text in which to look for entites getTextEntities text:string = TextEntities; diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index d64d088ac..8d7d4233d 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1473,7 +1473,6 @@ void ConfigManager::process_app_config(tl_object_ptr &c int64 chat_read_mark_expire_period = 0; int64 chat_read_mark_size_threshold = 0; double animated_emoji_zoom = 0.0; - string default_reaction; int64 reactions_uniq_max = 0; vector premium_features; auto &premium_limit_keys = get_premium_limit_keys(); @@ -1722,10 +1721,6 @@ void ConfigManager::process_app_config(tl_object_ptr &c chat_read_mark_size_threshold = get_json_value_int(std::move(key_value->value_), key); continue; } - if (key == "reactions_default") { - default_reaction = get_json_value_string(std::move(key_value->value_), key); - continue; - } if (key == "reactions_uniq_max") { reactions_uniq_max = get_json_value_int(std::move(key_value->value_), key); continue; @@ -1872,9 +1867,6 @@ void ConfigManager::process_app_config(tl_object_ptr &c } else { options.set_option_integer("chat_read_mark_size_threshold", chat_read_mark_size_threshold); } - if (!options.have_option("default_reaction_need_sync")) { - options.set_option_string("default_reaction", default_reaction); - } if (reactions_uniq_max <= 0 || reactions_uniq_max == 11) { options.set_option_empty("reactions_uniq_max"); } else { diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index d41ba3c0e..1760a4888 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -340,7 +340,7 @@ class SetDefaultReactionQuery final : public Td::ResultHandler { LOG(INFO) << "Failed to set default reaction: " << status; td_->option_manager_->set_option_empty("default_reaction_needs_sync"); - send_closure(G()->config_manager(), &ConfigManager::reget_app_config, Promise()); + send_closure(G()->config_manager(), &ConfigManager::request_config, false); } }; @@ -683,6 +683,7 @@ void set_default_reaction(Td *td, string reaction, Promise &&promise) { td->option_manager_->set_option_string("default_reaction", reaction); if (!td->option_manager_->get_option_boolean("default_reaction_needs_sync")) { td->option_manager_->set_option_boolean("default_reaction_needs_sync", true); + send_set_default_reaction_query(td); } } promise.set_value(Unit()); diff --git a/td/telegram/MessageReaction.hpp b/td/telegram/MessageReaction.hpp index 8f7307d0f..4c8e7f8a3 100644 --- a/td/telegram/MessageReaction.hpp +++ b/td/telegram/MessageReaction.hpp @@ -51,6 +51,7 @@ void MessageReaction::parse(ParserT &parser) { td::parse(recent_chooser_min_channels_, parser); } CHECK(!is_empty()); + CHECK(!reaction_.empty()); } template @@ -69,6 +70,7 @@ void UnreadMessageReaction::parse(ParserT &parser) { END_PARSE_FLAGS(); td::parse(reaction_, parser); td::parse(sender_dialog_id_, parser); + CHECK(!reaction_.empty()); } template diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 6a15eb98b..88285224b 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -245,7 +245,7 @@ bool OptionManager::is_internal_option(Slice name) { name == "channels_read_media_period" || name == "chat_read_mark_expire_period" || name == "chat_read_mark_size_threshold"; case 'd': - return name == "dc_txt_domain_name" || name == "default_reaction_needs_sync" || + return name == "dc_txt_domain_name" || name == "default_reaction" || name == "default_reaction_needs_sync" || name == "dialog_filters_chats_limit_default" || name == "dialog_filters_chats_limit_premium" || name == "dialog_filters_limit_default" || name == "dialog_filters_limit_premium" || name == "dialogs_folder_pinned_limit_default" || name == "dialogs_folder_pinned_limit_premium" || @@ -317,9 +317,6 @@ void OptionManager::on_option_updated(Slice name) { } break; case 'd': - if (name == "default_reaction_needs_sync" && get_option_boolean(name)) { - send_set_default_reaction_query(td_); - } if (name == "dice_emojis") { send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_dice_emojis); } @@ -621,14 +618,6 @@ void OptionManager::set_option(const string &name, td_api::object_ptr(value.get())->value_; - } - set_default_reaction(td_, std::move(reaction), std::move(promise)); - return; - } if (!is_bot && set_boolean_option("disable_animated_emoji")) { return; } diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e8758db65..88d0d6eb3 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5264,6 +5264,12 @@ void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) { request.limit_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::setDefaultReactionType &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + set_default_reaction(this, get_message_reaction_string(request.reaction_type_), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::getMessagePublicForwards &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.offset_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index bd70e3e48..4e4794630 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -656,6 +656,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::getMessageAddedReactions &request); + void on_request(uint64 id, td_api::setDefaultReactionType &request); + void on_request(uint64 id, td_api::getMessagePublicForwards &request); void on_request(uint64 id, const td_api::removeNotification &request); From c2a62dbc098a8cacc80dc25d9148800dcddbc11b Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 22 Aug 2022 15:23:17 +0300 Subject: [PATCH 006/200] Add updateDefaultReactionType. --- td/generate/scheme/td_api.tl | 5 ++++- td/telegram/MessageReaction.cpp | 10 ++++++++++ td/telegram/MessageReaction.h | 2 ++ td/telegram/OptionManager.cpp | 5 +++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index c0a3b20b0..045f75ea5 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4476,6 +4476,9 @@ updateWebAppMessageSent web_app_launch_id:int64 = Update; //@description The list of supported reactions has changed @reactions The new list of supported reactions updateReactions reactions:vector = Update; +//@description The type of default reaction has changed @reaction_type The new type of the default reaction +updateDefaultReactionType reaction_type:ReactionType = Update; + //@description The list of supported dice emojis has changed @emojis The new list of supported dice emojis updateDiceEmojis emojis:vector = Update; @@ -5137,7 +5140,7 @@ setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_ //@limit The maximum number of reactions to be returned; must be positive and can't be greater than 100 getMessageAddedReactions chat_id:int53 message_id:int53 reaction_type:ReactionType offset:string limit:int32 = AddedReactions; -//@description Changes default reaction type for the current user @reaction_type New type of the default reaction +//@description Changes type of default reaction for the current user @reaction_type New type of the default reaction setDefaultReactionType reaction_type:ReactionType = Ok; diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 1760a4888..3a5fefc1a 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -693,4 +693,14 @@ void send_set_default_reaction_query(Td *td) { td->create_handler()->send(td->option_manager_->get_option_string("default_reaction")); } +void send_update_default_reaction_type() { + auto default_reaction = G()->get_option_string("default_reaction"); + if (default_reaction.empty()) { + LOG(ERROR) << "Have no default reaction"; + return; + } + send_closure(G()->td(), &Td::send_update, + td_api::make_object(get_reaction_type_object(default_reaction))); +} + } // namespace td diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index bdb50b345..1191088b1 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -186,4 +186,6 @@ void set_default_reaction(Td *td, string reaction, Promise &&promise); void send_set_default_reaction_query(Td *td); +void send_update_default_reaction_type(); + } // namespace td diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 88285224b..bf90751eb 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -65,6 +65,8 @@ OptionManager::OptionManager(Td *td) vector added_actions{SuggestedAction{SuggestedAction::Type::SetPassword, DialogId(), days}}; send_closure(G()->td(), &Td::send_update, get_update_suggested_actions_object(added_actions, {})); } + } else if (name == "default_reaction") { + send_update_default_reaction_type(); } } @@ -317,6 +319,9 @@ void OptionManager::on_option_updated(Slice name) { } break; case 'd': + if (name == "default_reaction") { + send_update_default_reaction_type(); + } if (name == "dice_emojis") { send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_dice_emojis); } From ef4f0989b12032e64220212e86ad2cd5360a2d4e Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 22 Aug 2022 15:44:38 +0300 Subject: [PATCH 007/200] Update default reaction from other apps. --- td/telegram/ConfigManager.cpp | 8 ++++++++ td/telegram/MessageReaction.cpp | 8 ++++---- td/telegram/MessageReaction.h | 2 ++ td/telegram/Td.cpp | 1 + 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 8d7d4233d..f5f18a884 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -12,6 +12,7 @@ #include "td/telegram/JsonValue.h" #include "td/telegram/LinkManager.h" #include "td/telegram/logevent/LogEvent.h" +#include "td/telegram/MessageReaction.h" #include "td/telegram/net/AuthDataShared.h" #include "td/telegram/net/ConnectionCreator.h" #include "td/telegram/net/DcId.h" @@ -1414,6 +1415,13 @@ void ConfigManager::process_config(tl_object_ptr config) { options.set_option_integer("notification_cloud_delay_ms", fix_timeout_ms(config->notify_cloud_delay_ms_)); options.set_option_integer("notification_default_delay_ms", fix_timeout_ms(config->notify_default_delay_ms_)); + if (is_from_main_dc && !options.have_option("default_reaction_need_sync")) { + auto reaction_str = get_message_reaction_string(config->reactions_default_); + if (!reaction_str.empty()) { + options.set_option_string("default_reaction", reaction_str); + } + } + // delete outdated options options.set_option_empty("suggested_language_code"); options.set_option_empty("chat_big_size"); diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 3a5fefc1a..f6bf1492a 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -57,7 +57,7 @@ static telegram_api::object_ptr get_input_reaction(const return telegram_api::make_object(reaction); } -static string get_reaction_string(const telegram_api::object_ptr &reaction) { +string get_message_reaction_string(const telegram_api::object_ptr &reaction) { if (reaction == nullptr) { return string(); } @@ -271,7 +271,7 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler { FlatHashMap> recent_reactions; for (const auto &reaction : ptr->reactions_) { DialogId dialog_id(reaction->peer_id_); - auto reaction_str = get_reaction_string(reaction->reaction_); + auto reaction_str = get_message_reaction_string(reaction->reaction_); if (!dialog_id.is_valid() || (reaction_.empty() ? reaction_str.empty() : reaction_ != reaction_str)) { LOG(ERROR) << "Receive unexpected " << to_string(reaction); continue; @@ -451,7 +451,7 @@ unique_ptr MessageReactions::get_message_reactions( FlatHashSet reaction_strings; FlatHashSet recent_choosers; for (auto &reaction_count : reactions->results_) { - auto reaction_str = get_reaction_string(reaction_count->reaction_); + auto reaction_str = get_message_reaction_string(reaction_count->reaction_); if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT || reaction_str.empty()) { LOG(ERROR) << "Receive reaction " << reaction_str << " with invalid count " << reaction_count->count_; @@ -466,7 +466,7 @@ unique_ptr MessageReactions::get_message_reactions( vector recent_chooser_dialog_ids; vector> recent_chooser_min_channels; for (auto &peer_reaction : reactions->recent_reactions_) { - auto peer_reaction_str = get_reaction_string(peer_reaction->reaction_); + auto peer_reaction_str = get_message_reaction_string(peer_reaction->reaction_); if (peer_reaction_str == reaction_str) { DialogId dialog_id(peer_reaction->peer_id_); if (!dialog_id.is_valid()) { diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 1191088b1..465d912fd 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -173,6 +173,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr &reactions); +string get_message_reaction_string(const telegram_api::object_ptr &reaction); + string get_message_reaction_string(const td_api::object_ptr &type); void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 88d0d6eb3..531f31404 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4053,6 +4053,7 @@ void Td::send_update(tl_object_ptr &&object) { case td_api::updateFileAddedToDownloads::ID / 2: case td_api::updateFileDownload::ID / 2: case td_api::updateFileRemovedFromDownloads::ID / 2: + case td_api::updateDefaultReactionType::ID: LOG(ERROR) << "Sending update: " << oneline(to_string(object)); break; default: From fa07382e5be5c4c136d98cd71b88877d354e0ed6 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 22 Aug 2022 21:29:09 +0300 Subject: [PATCH 008/200] Explicitly pass default_reaction to send_update_default_reaction_type. --- td/telegram/MessageReaction.cpp | 8 +++++--- td/telegram/MessageReaction.h | 2 +- td/telegram/OptionManager.cpp | 9 ++++----- td/telegram/cli.cpp | 4 ++++ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index f6bf1492a..2d466adc0 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -675,7 +675,10 @@ void get_message_added_reactions(Td *td, FullMessageId full_message_id, string r } void set_default_reaction(Td *td, string reaction, Promise &&promise) { - if (!td->stickers_manager_->is_active_reaction(reaction)) { + if (reaction.empty()) { + return promise.set_error(Status::Error(400, "Default reaction must be non-empty")); + } + if (reaction[0] != '#' && !td->stickers_manager_->is_active_reaction(reaction)) { return promise.set_error(Status::Error(400, "Can't set incative reaction as default")); } @@ -693,8 +696,7 @@ void send_set_default_reaction_query(Td *td) { td->create_handler()->send(td->option_manager_->get_option_string("default_reaction")); } -void send_update_default_reaction_type() { - auto default_reaction = G()->get_option_string("default_reaction"); +void send_update_default_reaction_type(const string &default_reaction) { if (default_reaction.empty()) { LOG(ERROR) << "Have no default reaction"; return; diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 465d912fd..b9d2f64c6 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -188,6 +188,6 @@ void set_default_reaction(Td *td, string reaction, Promise &&promise); void send_set_default_reaction_query(Td *td); -void send_update_default_reaction_type(); +void send_update_default_reaction_type(const string &default_reaction); } // namespace td diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index bf90751eb..fd9b36536 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -54,11 +54,10 @@ OptionManager::OptionManager(Td *td) all_options["utc_time_offset"] = PSTRING() << 'I' << Clocks::tz_offset(); for (const auto &name_value : all_options) { const string &name = name_value.first; - const string &value = name_value.second; - options_->set(name, value); + options_->set(name, name_value.second); if (!is_internal_option(name)) { send_closure(G()->td(), &Td::send_update, - td_api::make_object(name, get_option_value_object(value))); + td_api::make_object(name, get_option_value_object(name_value.second))); } else if (name == "otherwise_relogin_days") { auto days = narrow_cast(get_option_integer(name)); if (days > 0) { @@ -66,7 +65,7 @@ OptionManager::OptionManager(Td *td) send_closure(G()->td(), &Td::send_update, get_update_suggested_actions_object(added_actions, {})); } } else if (name == "default_reaction") { - send_update_default_reaction_type(); + send_update_default_reaction_type(get_option_string(name)); } } @@ -320,7 +319,7 @@ void OptionManager::on_option_updated(Slice name) { break; case 'd': if (name == "default_reaction") { - send_update_default_reaction_type(); + send_update_default_reaction_type(get_option_string(name)); } if (name == "dice_emojis") { send_closure(td_->stickers_manager_actor_, &StickersManager::on_update_dice_emojis); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8ef5d01b6..7c9ee41c1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2216,6 +2216,10 @@ class CliClient final : public Actor { ChatId chat_id; get_args(args, chat_id); send_request(td_api::make_object(chat_id)); + } else if (op == "sdrt") { + string reaction; + get_args(args, reaction); + send_request(td_api::make_object(as_reaction_type(reaction))); } else if (op == "gmar") { ChatId chat_id; MessageId message_id; From c0f1a9850da3e590f0a74a24f13a62edb836c7af Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 22 Aug 2022 21:51:55 +0300 Subject: [PATCH 009/200] Disallow emoji starting with # as reactions. --- td/telegram/MessageReaction.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 2d466adc0..017413ab9 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -64,8 +64,13 @@ string get_message_reaction_string(const telegram_api::object_ptrget_id()) { case telegram_api::reactionEmpty::ID: return string(); - case telegram_api::reactionEmoji::ID: - return static_cast(reaction.get())->emoticon_; + case telegram_api::reactionEmoji::ID: { + const string &emoji = static_cast(reaction.get())->emoticon_; + if (emoji[0] == '#') { + return string(); + } + return emoji; + } case telegram_api::reactionCustomEmoji::ID: return get_custom_emoji_string( static_cast(reaction.get())->document_id_); @@ -90,7 +95,7 @@ string get_message_reaction_string(const td_api::object_ptrget_id()) { case td_api::reactionTypeEmoji::ID: { const string &emoji = static_cast(type.get())->emoji_; - if (!check_utf8(emoji)) { + if (!check_utf8(emoji) || emoji[0] == '#') { return string(); } return emoji; From d1cc119b9da588fa593a4cbe744ea9ffc7797bb2 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 22 Aug 2022 22:12:00 +0300 Subject: [PATCH 010/200] Use invokeAfter for self-edit queries. --- td/telegram/Account.cpp | 12 +++++++----- td/telegram/ContactsManager.cpp | 18 +++++++++++------- td/telegram/Td.cpp | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/td/telegram/Account.cpp b/td/telegram/Account.cpp index 2ccccb973..94921c845 100644 --- a/td/telegram/Account.cpp +++ b/td/telegram/Account.cpp @@ -118,7 +118,7 @@ class SetAccountTtlQuery final : public Td::ResultHandler { void send(int32 account_ttl) { send_query(G()->net_query_creator().create( - telegram_api::account_setAccountTTL(make_tl_object(account_ttl)))); + telegram_api::account_setAccountTTL(make_tl_object(account_ttl)), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -315,7 +315,8 @@ class ChangeAuthorizationSettingsQuery final : public Td::ResultHandler { flags |= telegram_api::account_changeAuthorizationSettings::CALL_REQUESTS_DISABLED_MASK; } send_query(G()->net_query_creator().create(telegram_api::account_changeAuthorizationSettings( - flags, hash, encrypted_requests_disabled, call_requests_disabled))); + flags, hash, encrypted_requests_disabled, call_requests_disabled), + {{"me"}})); } void on_result(BufferSlice packet) final { @@ -342,7 +343,8 @@ class SetAuthorizationTtlQuery final : public Td::ResultHandler { } void send(int32 authorization_ttl_days) { - send_query(G()->net_query_creator().create(telegram_api::account_setAuthorizationTTL(authorization_ttl_days))); + send_query( + G()->net_query_creator().create(telegram_api::account_setAuthorizationTTL(authorization_ttl_days), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -472,7 +474,7 @@ class SetBotGroupDefaultAdminRightsQuery final : public Td::ResultHandler { void send(AdministratorRights administrator_rights) { send_query(G()->net_query_creator().create( - telegram_api::bots_setBotGroupDefaultAdminRights(administrator_rights.get_chat_admin_rights()))); + telegram_api::bots_setBotGroupDefaultAdminRights(administrator_rights.get_chat_admin_rights()), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -505,7 +507,7 @@ class SetBotBroadcastDefaultAdminRightsQuery final : public Td::ResultHandler { void send(AdministratorRights administrator_rights) { send_query(G()->net_query_creator().create( - telegram_api::bots_setBotBroadcastDefaultAdminRights(administrator_rights.get_chat_admin_rights()))); + telegram_api::bots_setBotBroadcastDefaultAdminRights(administrator_rights.get_chat_admin_rights()), {{"me"}})); } void on_result(BufferSlice packet) final { diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 4cb6fede8..ebbffbef4 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -462,8 +462,10 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler { flags |= telegram_api::photos_uploadProfilePhoto::FILE_MASK; photo_input_file = std::move(input_file); } - send_query(G()->net_query_creator().create(telegram_api::photos_uploadProfilePhoto( - flags, std::move(photo_input_file), std::move(video_input_file), main_frame_timestamp))); + send_query(G()->net_query_creator().create( + telegram_api::photos_uploadProfilePhoto(flags, std::move(photo_input_file), std::move(video_input_file), + main_frame_timestamp), + {{"me"}})); } void on_result(BufferSlice packet) final { @@ -501,7 +503,8 @@ class UpdateProfilePhotoQuery final : public Td::ResultHandler { file_id_ = file_id; old_photo_id_ = old_photo_id; file_reference_ = FileManager::extract_file_reference(input_photo); - send_query(G()->net_query_creator().create(telegram_api::photos_updateProfilePhoto(std::move(input_photo)))); + send_query( + G()->net_query_creator().create(telegram_api::photos_updateProfilePhoto(std::move(input_photo)), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -592,8 +595,8 @@ class UpdateProfileQuery final : public Td::ResultHandler { first_name_ = first_name; last_name_ = last_name; about_ = about; - send_query( - G()->net_query_creator().create(telegram_api::account_updateProfile(flags, first_name, last_name, about))); + send_query(G()->net_query_creator().create(telegram_api::account_updateProfile(flags, first_name, last_name, about), + {{"me"}})); } void on_result(BufferSlice packet) final { @@ -647,7 +650,7 @@ class UpdateUsernameQuery final : public Td::ResultHandler { } void send(const string &username) { - send_query(G()->net_query_creator().create(telegram_api::account_updateUsername(username))); + send_query(G()->net_query_creator().create(telegram_api::account_updateUsername(username), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -684,7 +687,8 @@ class UpdateEmojiStatusQuery final : public Td::ResultHandler { } return make_tl_object(custom_emoji_id); }(); - send_query(G()->net_query_creator().create(telegram_api::account_updateEmojiStatus(std::move(emoji_status)))); + send_query( + G()->net_query_creator().create(telegram_api::account_updateEmojiStatus(std::move(emoji_status)), {{"me"}})); } void on_result(BufferSlice packet) final { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 531f31404..2658a5220 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4053,7 +4053,7 @@ void Td::send_update(tl_object_ptr &&object) { case td_api::updateFileAddedToDownloads::ID / 2: case td_api::updateFileDownload::ID / 2: case td_api::updateFileRemovedFromDownloads::ID / 2: - case td_api::updateDefaultReactionType::ID: + case td_api::updateDefaultReactionType::ID / 2: LOG(ERROR) << "Sending update: " << oneline(to_string(object)); break; default: From 43f91a9de5543dcec3d577b4f32d21869d28367c Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 23 Aug 2022 14:39:10 +0300 Subject: [PATCH 011/200] Add td_api::reportMessageReactions. --- td/generate/scheme/td_api.tl | 5 +++ td/telegram/MessageReaction.cpp | 66 +++++++++++++++++++++++++++++++++ td/telegram/MessageReaction.h | 3 ++ td/telegram/Td.cpp | 8 ++++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 7 ++++ 6 files changed, 91 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 045f75ea5..938c98710 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6323,6 +6323,11 @@ reportChat chat_id:int53 message_ids:vector reason:ChatReportReason text: //@chat_id Chat identifier @file_id Identifier of the photo to report. Only full photos from chatPhoto can be reported @reason The reason for reporting the chat photo @text Additional report details; 0-1024 characters reportChatPhoto chat_id:int53 file_id:int32 reason:ChatReportReason text:string = Ok; +//@description Reports reactions set on a message to the Telegram moderators. Reactions on a message can be reported only if message.can_report_reactions +//@chat_id Chat identifier @message_id Message identifier @sender_id Identifier of the sender, added the reaction +reportMessageReactions chat_id:int53 message_id:int53 sender_id:MessageSender = Ok; + + //@description Returns detailed statistics about a chat. Currently, this method can be used only for supergroups and channels. Can be used only if supergroupFullInfo.can_get_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application getChatStatistics chat_id:int53 is_dark:Bool = ChatStatistics; diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 017413ab9..01ad9b0c9 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -349,6 +349,44 @@ class SetDefaultReactionQuery final : public Td::ResultHandler { } }; +class ReportReactionQuery final : public Td::ResultHandler { + Promise promise_; + DialogId dialog_id_; + + public: + explicit ReportReactionQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, MessageId message_id, DialogId chooser_dialog_id) { + dialog_id_ = dialog_id; + + auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read); + CHECK(input_peer != nullptr); + + auto chooser_input_peer = td_->messages_manager_->get_input_peer(chooser_dialog_id, AccessRights::Know); + if (chooser_input_peer == nullptr) { + return promise_.set_error(Status::Error(400, "Reaction sender is not accessible")); + } + + send_query(G()->net_query_creator().create(telegram_api::messages_reportReaction( + std::move(input_peer), message_id.get_server_message_id().get(), std::move(chooser_input_peer)))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "ReportReactionQuery"); + promise_.set_error(std::move(status)); + } +}; + void MessageReaction::add_recent_chooser_dialog_id(DialogId dialog_id) { recent_chooser_dialog_ids_.insert(recent_chooser_dialog_ids_.begin(), dialog_id); if (recent_chooser_dialog_ids_.size() > MAX_RECENT_CHOOSERS + 1) { @@ -710,4 +748,32 @@ void send_update_default_reaction_type(const string &default_reaction) { td_api::make_object(get_reaction_type_object(default_reaction))); } +void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id, + Promise &&promise) { + auto dialog_id = full_message_id.get_dialog_id(); + if (!td->messages_manager_->have_dialog_force(dialog_id, "send_callback_query")) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + if (!td->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { + return promise.set_error(Status::Error(400, "Can't access the chat")); + } + + if (!td->messages_manager_->have_message_force(full_message_id, "report_user_reactions")) { + return promise.set_error(Status::Error(400, "Message not found")); + } + auto message_id = full_message_id.get_message_id(); + if (message_id.is_valid_scheduled()) { + return promise.set_error(Status::Error(400, "Can't report reactions on scheduled messages")); + } + if (!message_id.is_server()) { + return promise.set_error(Status::Error(400, "Message reactions can't be reported")); + } + + if (!td->messages_manager_->have_input_peer(chooser_dialog_id, AccessRights::Know)) { + return promise.set_error(Status::Error(400, "Reaction sender not found")); + } + + td->create_handler(std::move(promise))->send(dialog_id, message_id, chooser_dialog_id); +} + } // namespace td diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index b9d2f64c6..ba92d32a1 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -190,4 +190,7 @@ void send_set_default_reaction_query(Td *td); void send_update_default_reaction_type(const string &default_reaction); +void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id, + Promise &&promise); + } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 2658a5220..a923fb951 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -7180,6 +7180,14 @@ void Td::on_request(uint64 id, td_api::reportChatPhoto &request) { r_report_reason.move_as_ok(), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::reportMessageReactions &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + TRY_RESULT_PROMISE(promise, sender_dialog_id, get_message_sender_dialog_id(this, request.sender_id_, false, false)); + report_message_reactions(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, sender_dialog_id, + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getChatStatistics &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 4e4794630..bdda812a9 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1154,6 +1154,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::reportChatPhoto &request); + void on_request(uint64 id, const td_api::reportMessageReactions &request); + void on_request(uint64 id, const td_api::getChatStatistics &request); void on_request(uint64 id, const td_api::getMessageStatistics &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 7c9ee41c1..72c7eda76 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4748,6 +4748,13 @@ class CliClient final : public Actor { get_args(args, chat_id, file_id, reason, text); send_request( td_api::make_object(chat_id, file_id, get_chat_report_reason(reason), text)); + } else if (op == "rmr") { + ChatId chat_id; + MessageId message_id; + string sender_id; + get_args(args, chat_id, message_id, sender_id); + send_request( + td_api::make_object(chat_id, message_id, as_message_sender(sender_id))); } else if (op == "gcst") { ChatId chat_id; bool is_dark; From b359a09464e62e0d11a322f8662fb79000a275fe Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 23 Aug 2022 16:44:20 +0300 Subject: [PATCH 012/200] Add message.can_report_reactions. --- td/generate/scheme/td_api.tl | 3 ++- td/telegram/MessagesManager.cpp | 30 +++++++++++++++++++++++++----- td/telegram/MessagesManager.h | 2 ++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 938c98710..7944bacb9 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -884,6 +884,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool n //@can_get_message_thread True, if information about the message thread is available through getMessageThread and getMessageThreadHistory //@can_get_viewers True, if chat members already viewed the message can be received through getMessageViewers //@can_get_media_timestamp_links True, if media timestamp links can be generated for media timestamp entities in the message text, caption or web page description through getMessageLink +//@can_report_reactions True, if reactions on the message can be reported through reportMessageReactions //@has_timestamped_media True, if media timestamp entities refers to a media in this message as opposed to a media in the replied message //@is_channel_post True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts //@contains_unread_mention True, if the message contains an unread mention for the current user @@ -903,7 +904,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool n //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null -message id:int53 sender_id:MessageSender chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool is_pinned:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_saved:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_added_reactions:Bool can_get_statistics:Bool can_get_message_thread:Bool can_get_viewers:Bool can_get_media_timestamp_links:Bool has_timestamped_media:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo unread_reactions:vector reply_in_chat_id:int53 reply_to_message_id:int53 message_thread_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int53 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_id:MessageSender chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool is_pinned:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_saved:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_added_reactions:Bool can_get_statistics:Bool can_get_message_thread:Bool can_get_viewers:Bool can_get_media_timestamp_links:Bool can_report_reactions:Bool has_timestamped_media:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo unread_reactions:vector reply_in_chat_id:int53 reply_to_message_id:int53 message_thread_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int53 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total number of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 712fee75f..087671272 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -18723,6 +18723,25 @@ Status MessagesManager::can_get_media_timestamp_link(DialogId dialog_id, const M return Status::OK(); } +bool MessagesManager::can_report_message_reactions(DialogId dialog_id, const Message *m) const { + CHECK(m != nullptr); + if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id) || + !td_->contacts_manager_->is_channel_public(dialog_id.get_channel_id())) { + return false; + } + if (m->message_id.is_scheduled() || !m->message_id.is_server()) { + return false; + } + if (m->message_id.is_scheduled() || !m->message_id.is_server()) { + return false; + } + if (is_discussion_message(dialog_id, m)) { + return false; + } + + return true; +} + Result> MessagesManager::get_message_link(FullMessageId full_message_id, int32 media_timestamp, bool for_group, bool for_comment) { auto dialog_id = full_message_id.get_dialog_id(); @@ -24719,6 +24738,7 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial auto can_get_message_thread = for_event_log ? false : get_top_thread_full_message_id(dialog_id, m).is_ok(); auto can_get_viewers = for_event_log ? false : can_get_message_viewers(dialog_id, m).is_ok(); auto can_get_media_timestamp_links = for_event_log ? false : can_get_media_timestamp_link(dialog_id, m).is_ok(); + auto can_report_reactions = for_event_log ? false : can_report_message_reactions(dialog_id, m); auto via_bot_user_id = td_->contacts_manager_->get_user_id_object(m->via_bot_user_id, "via_bot_user_id"); auto media_album_id = for_event_log ? static_cast(0) : m->media_album_id; auto reply_to_message_id = for_event_log ? static_cast(0) : m->reply_to_message_id.get(); @@ -24742,11 +24762,11 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial m->message_id.get(), std::move(sender), dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, is_pinned, can_be_edited, can_be_forwarded, can_be_saved, can_delete_for_self, can_delete_for_all_users, can_get_added_reactions, can_get_statistics, can_get_message_thread, can_get_viewers, - can_get_media_timestamp_links, has_timestamped_media, m->is_channel_post, contains_unread_mention, date, - edit_date, std::move(forward_info), std::move(interaction_info), std::move(unread_reactions), - reply_in_dialog_id.get(), reply_to_message_id, top_thread_message_id, ttl, ttl_expires_in, via_bot_user_id, - m->author_signature, media_album_id, get_restriction_reason_description(m->restriction_reasons), - std::move(content), std::move(reply_markup)); + can_get_media_timestamp_links, can_report_reactions, has_timestamped_media, m->is_channel_post, + contains_unread_mention, date, edit_date, std::move(forward_info), std::move(interaction_info), + std::move(unread_reactions), reply_in_dialog_id.get(), reply_to_message_id, top_thread_message_id, ttl, + ttl_expires_in, via_bot_user_id, m->author_signature, media_album_id, + get_restriction_reason_description(m->restriction_reasons), std::move(content), std::move(reply_markup)); } tl_object_ptr MessagesManager::get_messages_object(int32 total_count, DialogId dialog_id, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index d0ba6bdc6..781ccfef3 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1903,6 +1903,8 @@ class MessagesManager final : public Actor { static Status can_get_media_timestamp_link(DialogId dialog_id, const Message *m); + bool can_report_message_reactions(DialogId dialog_id, const Message *m) const; + Status can_get_message_viewers(FullMessageId full_message_id) TD_WARN_UNUSED_RESULT; Status can_get_message_viewers(DialogId dialog_id, const Message *m) const TD_WARN_UNUSED_RESULT; From ce845b07538714bebb13dac6ea50a6ba429b2031 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 23 Aug 2022 18:14:46 +0300 Subject: [PATCH 013/200] Process updateUserEmojiStatus. --- td/telegram/ContactsManager.cpp | 28 ++++++++++++++++++++++++++++ td/telegram/ContactsManager.h | 2 ++ td/telegram/UpdatesManager.cpp | 10 +++++----- td/telegram/UpdatesManager.h | 3 +-- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index ebbffbef4..1e0e78af2 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -11761,6 +11761,34 @@ void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo & } } +void ContactsManager::on_update_user_emoji_status(UserId user_id, + tl_object_ptr &&emoji_status_ptr) { + if (!user_id.is_valid()) { + LOG(ERROR) << "Receive invalid " << user_id; + return; + } + + User *u = get_user_force(user_id); + if (u != nullptr) { + int64 emoji_status = 0; + if (emoji_status_ptr != nullptr && emoji_status_ptr->get_id() == telegram_api::emojiStatus::ID) { + emoji_status = static_cast(emoji_status_ptr.get())->document_id_; + } + on_update_user_emoji_status(u, user_id, emoji_status); + update_user(u, user_id); + } else { + LOG(INFO) << "Ignore update user emoji status about unknown " << user_id; + } +} + +void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, int64 emoji_status) { + if (u->emoji_status != emoji_status) { + u->emoji_status = emoji_status; + LOG(DEBUG) << "Emoji status has changed for " << user_id; + u->is_changed = true; + } +} + void ContactsManager::on_update_user_is_contact(User *u, UserId user_id, bool is_contact, bool is_mutual_contact) { UserId my_id = get_my_id(); if (user_id == my_id) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 16b2b98ca..cc1d9cd81 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -178,6 +178,7 @@ class ContactsManager final : public Actor { void on_update_user_name(UserId user_id, string &&first_name, string &&last_name, string &&username); void on_update_user_phone_number(UserId user_id, string &&phone_number); void on_update_user_photo(UserId user_id, tl_object_ptr &&photo_ptr); + void on_update_user_emoji_status(UserId user_id, tl_object_ptr &&emoji_status_ptr); void on_update_user_online(UserId user_id, tl_object_ptr &&status); void on_update_user_local_was_online(UserId user_id, int32 local_was_online); void on_update_user_is_blocked(UserId user_id, bool is_blocked); @@ -1256,6 +1257,7 @@ class ContactsManager final : public Actor { void on_update_user_phone_number(User *u, UserId user_id, string &&phone_number); void on_update_user_photo(User *u, UserId user_id, tl_object_ptr &&photo, const char *source); + void on_update_user_emoji_status(User *u, UserId user_id, int64 emoji_status); void on_update_user_is_contact(User *u, UserId user_id, bool is_contact, bool is_mutual_contact); void on_update_user_online(User *u, UserId user_id, tl_object_ptr &&status); void on_update_user_local_was_online(User *u, UserId user_id, int32 local_was_online); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index d4326002b..b6ab0a2cc 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3165,11 +3165,15 @@ void UpdatesManager::on_update(tl_object_ptr upda } void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - // TODO update->previous_, update->date_ td_->contacts_manager_->on_update_user_photo(UserId(update->user_id_), std::move(update->photo_)); promise.set_value(Unit()); } +void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + td_->contacts_manager_->on_update_user_emoji_status(UserId(update->user_id_), std::move(update->emoji_status_)); + promise.set_value(Unit()); +} + void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { td_->messages_manager_->on_update_dialog_is_blocked(DialogId(update->peer_id_), update->blocked_); promise.set_value(Unit()); @@ -3578,10 +3582,6 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - promise.set_value(Unit()); -} - void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { promise.set_value(Unit()); } diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 17f97560e..2e50c771a 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -420,6 +420,7 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); + void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); @@ -540,8 +541,6 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); - void on_update(tl_object_ptr update, Promise &&promise); - void on_update(tl_object_ptr update, Promise &&promise); }; From 663389f19d90e21d22b0e69017aad2a5bf22b151 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 23 Aug 2022 18:24:21 +0300 Subject: [PATCH 014/200] Support improved updateStickerSets. --- td/telegram/StickersManager.cpp | 12 +++++------- td/telegram/StickersManager.h | 2 +- td/telegram/UpdatesManager.cpp | 8 +++++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 399df03d3..2d6b0d23a 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -5151,13 +5151,11 @@ void StickersManager::on_update_disable_animated_emojis() { } } -void StickersManager::on_update_sticker_sets() { - // TODO better support - for (int32 type = 0; type < MAX_STICKER_TYPE; type++) { - archived_sticker_set_ids_[type].clear(); - total_archived_sticker_set_count_[type] = -1; - reload_installed_sticker_sets(static_cast(type), true); - } +void StickersManager::on_update_sticker_sets(StickerType sticker_type) { + auto type = static_cast(sticker_type); + archived_sticker_set_ids_[type].clear(); + total_archived_sticker_set_count_[type] = -1; + reload_installed_sticker_sets(sticker_type, true); } void StickersManager::try_update_animated_emoji_messages() { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 844ef0afe..0e21a8faa 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -205,7 +205,7 @@ class StickersManager final : public Actor { void on_update_emoji_sounds(); - void on_update_sticker_sets(); + void on_update_sticker_sets(StickerType sticker_type); void on_update_sticker_sets_order(StickerType sticker_type, const vector &sticker_set_ids); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index b6ab0a2cc..2fd5a3a4f 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3356,7 +3356,13 @@ void UpdatesManager::on_update(tl_object_ptr } void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - td_->stickers_manager_->on_update_sticker_sets(); + StickerType sticker_type = StickerType::Regular; + if (update->emojis_) { + sticker_type = StickerType::CustomEmoji; + } else if (update->masks_) { + sticker_type = StickerType::Mask; + } + td_->stickers_manager_->on_update_sticker_sets(sticker_type); promise.set_value(Unit()); } From 4e6046b9ec848caa3c0a22445a8e231583556208 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 24 Aug 2022 23:31:15 +0300 Subject: [PATCH 015/200] Treat all emoji reactions as non-premium. --- td/generate/scheme/td_api.tl | 10 +++------- td/telegram/AvailableReaction.cpp | 12 ++++-------- td/telegram/AvailableReaction.h | 5 +---- td/telegram/MessageReaction.cpp | 4 ++-- td/telegram/MessageReaction.h | 4 ++++ td/telegram/MessagesManager.cpp | 4 ++-- td/telegram/StickersManager.cpp | 15 +++++++++------ td/telegram/StickersManager.hpp | 2 ++ td/telegram/Td.cpp | 2 +- 9 files changed, 28 insertions(+), 30 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 7944bacb9..23959e9a5 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2563,18 +2563,14 @@ addedReaction type:ReactionType sender_id:MessageSender = AddedReaction; //@description Represents a list of reactions added to a message @total_count The total number of found reactions @reactions The list of added reactions @next_offset The offset for the next request. If empty, there are no more results addedReactions total_count:int32 reactions:vector next_offset:string = AddedReactions; -//@description Represents an available reaction @reaction Text representation of the reaction @needs_premium True, if Telegram Premium is needed to send the reaction -availableReaction reaction:string needs_premium:Bool = AvailableReaction; - -//@description Represents a list of available reactions @reactions List of reactions -availableReactions reactions:vector = AvailableReactions; +//@description Represents a list of available reactions @reactions List of available reactions +availableReactions reactions:vector = AvailableReactions; //@description Contains stickers which must be used for emoji reaction animation rendering //@reaction Text representation of the reaction //@title Reaction title //@is_active True, if the reaction can be added to new messages and enabled in chats -//@is_premium True, if the reaction is available only for Premium users //@static_icon Static icon for the reaction //@appear_animation Appear animation for the reaction //@select_animation Select animation for the reaction @@ -2582,7 +2578,7 @@ availableReactions reactions:vector = AvailableReactions; //@effect_animation Effect animation for the reaction //@around_animation Around animation for the reaction; may be null //@center_animation Center animation for the reaction; may be null -reaction reaction:string title:string is_active:Bool is_premium:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = Reaction; +reaction reaction:string title:string is_active:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = Reaction; //@description Represents a list of animations @animations List of animations diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index dfd794437..045a15903 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -11,11 +11,11 @@ namespace td { AvailableReactionType get_reaction_type(const vector &available_reactions, const string &reaction) { + if (reaction[0] == '#') { + return AvailableReactionType::NeedsPremium; + } for (auto &available_reaction : available_reactions) { if (available_reaction.reaction_ == reaction) { - if (available_reaction.is_premium_) { - return AvailableReactionType::NeedsPremium; - } return AvailableReactionType::Available; } } @@ -50,12 +50,8 @@ vector get_active_reactions(const vector &available_reactions, return result; } -td_api::object_ptr AvailableReaction::get_available_reaction_object() const { - return td_api::make_object(reaction_, is_premium_); -} - bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs) { - return lhs.reaction_ == rhs.reaction_ && lhs.is_premium_ == rhs.is_premium_; + return lhs.reaction_ == rhs.reaction_; } } // namespace td diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h index e3196382d..a5a56e3b7 100644 --- a/td/telegram/AvailableReaction.h +++ b/td/telegram/AvailableReaction.h @@ -14,12 +14,9 @@ namespace td { struct AvailableReaction { string reaction_; - bool is_premium_; - AvailableReaction(const string &reaction, bool is_premium) : reaction_(reaction), is_premium_(is_premium) { + explicit AvailableReaction(const string &reaction) : reaction_(reaction) { } - - td_api::object_ptr get_available_reaction_object() const; }; bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs); diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 01ad9b0c9..a51488a54 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -47,7 +47,7 @@ static string get_custom_emoji_string(int64 custom_emoji_id) { return PSTRING() << '#' << base64_encode(Slice(s, 8)); } -static telegram_api::object_ptr get_input_reaction(const string &reaction) { +telegram_api::object_ptr get_input_reaction(const string &reaction) { if (reaction.empty()) { return telegram_api::make_object(); } @@ -80,7 +80,7 @@ string get_message_reaction_string(const telegram_api::object_ptr get_reaction_type_object(const string &reaction) { +td_api::object_ptr get_reaction_type_object(const string &reaction) { CHECK(!reaction.empty()); if (reaction[0] == '#') { return td_api::make_object(get_custom_emoji_id(reaction)); diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index ba92d32a1..75ab1726e 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -173,6 +173,10 @@ StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr &reactions); +telegram_api::object_ptr get_input_reaction(const string &reaction); + +td_api::object_ptr get_reaction_type_object(const string &reaction); + string get_message_reaction_string(const telegram_api::object_ptr &reaction); string get_message_reaction_string(const td_api::object_ptr &type); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 087671272..e6ba03bba 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24399,7 +24399,7 @@ vector MessagesManager::get_message_available_reactions(const // can add the reaction if it has already been used for the message or is available in the chat bool is_set = (m->reactions != nullptr && m->reactions->get_reaction(active_reaction.reaction_) != nullptr); if (is_set || (can_add_new_reactions && td::contains(active_reactions, active_reaction.reaction_))) { - result.emplace_back(active_reaction.reaction_, !is_premium && active_reaction.is_premium_ && !is_set); + result.emplace_back(active_reaction.reaction_); } } } @@ -24409,7 +24409,7 @@ vector MessagesManager::get_message_available_reactions(const get_reaction_type(result, reaction.get_reaction()) == AvailableReactionType::Unavailable) { CHECK(!can_use_reactions || get_reaction_type(active_reactions_, reaction.get_reaction()) == AvailableReactionType::Unavailable); - result.emplace_back(reaction.get_reaction(), false); + result.emplace_back(reaction.get_reaction()); } } } diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 2d6b0d23a..0d3e245f9 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -3640,11 +3640,10 @@ void StickersManager::on_get_special_sticker_set(const SpecialStickerSetType &ty td_api::object_ptr StickersManager::get_update_reactions_object() const { auto reactions = transform(reactions_.reactions_, [this](const Reaction &reaction) { return td_api::make_object( - reaction.reaction_, reaction.title_, reaction.is_active_, reaction.is_premium_, - get_sticker_object(reaction.static_icon_), get_sticker_object(reaction.appear_animation_), - get_sticker_object(reaction.select_animation_), get_sticker_object(reaction.activate_animation_), - get_sticker_object(reaction.effect_animation_), get_sticker_object(reaction.around_animation_), - get_sticker_object(reaction.center_animation_)); + reaction.reaction_, reaction.title_, reaction.is_active_, get_sticker_object(reaction.static_icon_), + get_sticker_object(reaction.appear_animation_), get_sticker_object(reaction.select_animation_), + get_sticker_object(reaction.activate_animation_), get_sticker_object(reaction.effect_animation_), + get_sticker_object(reaction.around_animation_), get_sticker_object(reaction.center_animation_)); }); return td_api::make_object(std::move(reactions)); } @@ -3685,7 +3684,7 @@ void StickersManager::update_active_reactions() { vector active_reactions; for (auto &reaction : reactions_.reactions_) { if (reaction.is_active_) { - active_reactions.emplace_back(reaction.reaction_, reaction.is_premium_); + active_reactions.emplace_back(reaction.reaction_); } } td_->messages_manager_->set_active_reactions(std::move(active_reactions)); @@ -3735,6 +3734,10 @@ void StickersManager::on_get_available_reactions( LOG(ERROR) << "Receive invalid reaction " << reaction.reaction_; continue; } + if (reaction.is_premium_) { + LOG(ERROR) << "Receive premium reaction " << reaction.reaction_; + continue; + } new_reactions.push_back(std::move(reaction)); } diff --git a/td/telegram/StickersManager.hpp b/td/telegram/StickersManager.hpp index 683f8d6c3..14b78eb61 100644 --- a/td/telegram/StickersManager.hpp +++ b/td/telegram/StickersManager.hpp @@ -499,6 +499,8 @@ void StickersManager::Reaction::parse(ParserT &parser) { if (has_center_animation) { center_animation_ = stickers_manager->parse_sticker(false, parser); } + + is_premium_ = false; } template diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index a923fb951..7a201b950 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5242,7 +5242,7 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque send_closure(actor_id(this), &Td::send_error, id, r_reactions.move_as_error()); } else { auto reactions = - transform(r_reactions.ok(), [](auto &reaction) { return reaction.get_available_reaction_object(); }); + transform(r_reactions.ok(), [](auto &reaction) { return get_reaction_type_object(reaction.reaction_); }); send_closure(actor_id(this), &Td::send_result, id, td_api::make_object(std::move(reactions))); } From 60c7a8a62252da867a183de8a0a156f7f9a57724 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 25 Aug 2022 20:39:44 +0300 Subject: [PATCH 016/200] Add more cases for reloading content settings. --- td/telegram/ConfigManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index f5f18a884..76f03a304 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1817,13 +1817,15 @@ void ConfigManager::process_app_config(tl_object_ptr &c if (ignored_restriction_reasons.empty()) { options.set_option_empty("ignored_restriction_reasons"); - if (options.get_option_boolean("ignore_sensitive_content_restrictions", true)) { + if (options.get_option_boolean("ignore_sensitive_content_restrictions", true) || + options.get_option_boolean("can_ignore_sensitive_content_restrictions", true)) { get_content_settings(Auto()); } } else { options.set_option_string("ignored_restriction_reasons", ignored_restriction_reasons); - if (!options.get_option_boolean("can_ignore_sensitive_content_restrictions")) { + if (!options.get_option_boolean("can_ignore_sensitive_content_restrictions") || + !options.get_option_boolean("ignore_sensitive_content_restrictions")) { get_content_settings(Auto()); } } From 2e31ba51885ac9d005ddcad3575555f5a9d4399b Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 25 Aug 2022 22:51:04 +0300 Subject: [PATCH 017/200] Return multiple payment options in premiumState. --- td/generate/scheme/td_api.tl | 15 +++++++-------- td/telegram/ContactsManager.cpp | 2 +- td/telegram/MessagesManager.cpp | 1 - td/telegram/Premium.cpp | 10 ++++++++-- td/telegram/PremiumGiftOption.cpp | 16 ++++++++++++++-- td/telegram/PremiumGiftOption.h | 3 ++- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 23959e9a5..295327313 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -466,14 +466,14 @@ chatPermissions can_send_messages:Bool can_send_media_messages:Bool can_send_pol chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool can_manage_video_chats:Bool is_anonymous:Bool = ChatAdministratorRights; -//@description Describes an option for gifting Telegram Premium to a user +//@description Describes an option for buying Telegram Premium to a user //@currency ISO 4217 currency code for Telegram Premium subscription payment //@amount The amount to pay, in the smallest units of the currency -//@discount_percentage The discount associated with this gift option, as a percentage +//@discount_percentage The discount associated with this option, as a percentage //@month_count Number of month the Telegram Premium subscription will be active //@store_product_id Identifier of the store product associated with the option -//@payment_link An internal link to be opened for gifting Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available -premiumGiftOption currency:string amount:int53 discount_percentage:int32 month_count:int32 store_product_id:string payment_link:InternalLinkType = PremiumGiftOption; +//@payment_link An internal link to be opened for buying Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available +premiumPaymentOption currency:string amount:int53 discount_percentage:int32 month_count:int32 store_product_id:string payment_link:InternalLinkType = PremiumPaymentOption; //@description Represents a user @@ -524,7 +524,7 @@ botInfo share_text:string description:string photo:photo animation:animation men //@premium_gift_options The list of available options for gifting Telegram Premium to the user //@group_in_common_count Number of group chats where both the other user and the current user are a member; 0 for the current user //@bot_info For bots, information about the bot; may be null -userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool has_restricted_voice_and_video_note_messages:Bool need_phone_number_privacy_exception:Bool bio:formattedText premium_gift_options:vector group_in_common_count:int32 bot_info:botInfo = UserFullInfo; +userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool has_restricted_voice_and_video_note_messages:Bool need_phone_number_privacy_exception:Bool bio:formattedText premium_gift_options:vector group_in_common_count:int32 bot_info:botInfo = UserFullInfo; //@description Represents a list of users @total_count Approximate total number of users found @user_ids A list of user identifiers users total_count:int32 user_ids:vector = Users; @@ -3056,10 +3056,9 @@ premiumFeaturePromotionAnimation feature:PremiumFeature animation:animation = Pr //@description Contains state of Telegram Premium subscription and promotion videos for Premium features //@state Text description of the state of the current Premium subscription; may be empty if the current user has no Telegram Premium subscription -//@currency ISO 4217 currency code for Telegram Premium subscription payment -//@monthly_amount Monthly subscription payment for Telegram Premium subscription, in the smallest units of the currency +//@payment_options The list of available options for buying Telegram Premium //@animations The list of available promotion animations for Premium features -premiumState state:formattedText currency:string monthly_amount:int53 animations:vector = PremiumState; +premiumState state:formattedText payment_options:vector animations:vector = PremiumState; //@class StorePaymentPurpose @description Describes a purpose of an in-store payment diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 1e0e78af2..e73f0e6cf 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -16855,7 +16855,7 @@ tl_object_ptr ContactsManager::get_user_full_info_object(U auto base_premium_gift_it = std::min_element(user_full->premium_gift_options.begin(), user_full->premium_gift_options.end()); auto premium_gift_options = transform(user_full->premium_gift_options, [&base_premium_gift_it](const auto &option) { - return option.get_premium_gift_option_object(*base_premium_gift_it); + return option.get_premium_payment_option_object(*base_premium_gift_it); }); auto voice_messages_forbidden = is_premium ? user_full->voice_messages_forbidden : false; return make_tl_object( diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e6ba03bba..1fcf5e409 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24390,7 +24390,6 @@ vector MessagesManager::get_message_available_reactions(const vector result; if (can_use_reactions) { - bool is_premium = td_->option_manager_->get_option_boolean("is_premium"); int64 reactions_uniq_max = td_->option_manager_->get_option_integer("reactions_uniq_max", 11); bool can_add_new_reactions = m->reactions == nullptr || static_cast(m->reactions->reactions_.size()) < reactions_uniq_max; diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index c0fab14ca..238d3485b 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -156,8 +156,14 @@ class GetPremiumPromoQuery final : public Td::ResultHandler { std::move(animation_object))); } - promise_.set_value(td_api::make_object(get_formatted_text_object(state, true, 0), "USD", 499, - std::move(animations))); + auto period_options = transform(std::move(promo->period_options_), + [](auto &&period_option) { return PremiumGiftOption(std::move(period_option)); }); + auto base_premium_gift_it = std::min_element(period_options.begin(), period_options.end()); + auto payment_options = transform(period_options, [&base_premium_gift_it](const auto &option) { + return option.get_premium_payment_option_object(*base_premium_gift_it); + }); + promise_.set_value(td_api::make_object(get_formatted_text_object(state, true, 0), + std::move(payment_options), std::move(animations))); } void on_error(Status status) final { diff --git a/td/telegram/PremiumGiftOption.cpp b/td/telegram/PremiumGiftOption.cpp index 733ca57b9..f9be04091 100644 --- a/td/telegram/PremiumGiftOption.cpp +++ b/td/telegram/PremiumGiftOption.cpp @@ -28,11 +28,23 @@ PremiumGiftOption::PremiumGiftOption(telegram_api::object_ptr &&option) + : months_(option->months_) + , currency_(std::move(option->currency_)) + , amount_(option->amount_) + , bot_url_(std::move(option->bot_url_)) + , store_product_(std::move(option->store_product_)) { + if (amount_ <= 0 || !check_currency_amount(amount_)) { + LOG(ERROR) << "Receive invalid premium gift option amount " << amount_; + amount_ = static_cast(1) << 40; + } +} + double PremiumGiftOption::get_monthly_price() const { return static_cast(amount_) / static_cast(months_); } -td_api::object_ptr PremiumGiftOption::get_premium_gift_option_object( +td_api::object_ptr PremiumGiftOption::get_premium_payment_option_object( const PremiumGiftOption &base_option) const { auto link_type = LinkManager::parse_internal_link(bot_url_, true); int32 discount_percentage = 0; @@ -42,7 +54,7 @@ td_api::object_ptr PremiumGiftOption::get_premium_gif discount_percentage = static_cast(100 * (1.0 - relative_price)); } } - return td_api::make_object( + return td_api::make_object( currency_, amount_, discount_percentage, months_, store_product_, link_type == nullptr ? nullptr : link_type->get_internal_link_type_object()); } diff --git a/td/telegram/PremiumGiftOption.h b/td/telegram/PremiumGiftOption.h index cb235ee76..694fb24c8 100644 --- a/td/telegram/PremiumGiftOption.h +++ b/td/telegram/PremiumGiftOption.h @@ -29,8 +29,9 @@ class PremiumGiftOption { public: PremiumGiftOption() = default; explicit PremiumGiftOption(telegram_api::object_ptr &&option); + explicit PremiumGiftOption(telegram_api::object_ptr &&option); - td_api::object_ptr get_premium_gift_option_object( + td_api::object_ptr get_premium_payment_option_object( const PremiumGiftOption &base_option) const; template From df238a70344c5470a7b90b1e5d511bc22265b269 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 25 Aug 2022 23:15:53 +0300 Subject: [PATCH 018/200] Allow to specify application name when opening Web App. --- td/generate/scheme/td_api.tl | 6 ++++-- td/telegram/AttachMenuManager.cpp | 12 ++++++------ td/telegram/AttachMenuManager.h | 2 +- td/telegram/InlineQueriesManager.cpp | 9 +++++---- td/telegram/InlineQueriesManager.h | 3 ++- td/telegram/Td.cpp | 11 +++++++---- td/telegram/cli.cpp | 4 ++-- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 295327313..dea413588 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5235,7 +5235,8 @@ answerInlineQuery inline_query_id:int64 is_personal:Bool results:vector &&input_user, string &&url, - td_api::object_ptr &&theme, MessageId reply_to_message_id, bool silent, - DialogId as_dialog_id) { + td_api::object_ptr &&theme, string &&platform, MessageId reply_to_message_id, + bool silent, DialogId as_dialog_id) { dialog_id_ = dialog_id; bot_user_id_ = bot_user_id; reply_to_message_id_ = reply_to_message_id; @@ -104,7 +104,7 @@ class RequestWebViewQuery final : public Td::ResultHandler { send_query(G()->net_query_creator().create(telegram_api::messages_requestWebView( flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), std::move(input_user), url, start_parameter, - std::move(theme_parameters), string(), reply_to_message_id.get_server_message_id().get(), + std::move(theme_parameters), platform, reply_to_message_id.get_server_message_id().get(), std::move(as_input_peer)))); } @@ -601,7 +601,7 @@ void AttachMenuManager::schedule_ping_web_view() { void AttachMenuManager::request_web_view(DialogId dialog_id, UserId bot_user_id, MessageId reply_to_message_id, string &&url, td_api::object_ptr &&theme, - Promise> &&promise) { + string &&platform, Promise> &&promise) { TRY_STATUS_PROMISE(promise, td_->contacts_manager_->get_bot_data(bot_user_id)); TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(bot_user_id)); @@ -635,8 +635,8 @@ void AttachMenuManager::request_web_view(DialogId dialog_id, UserId bot_user_id, DialogId as_dialog_id = td_->messages_manager_->get_dialog_default_send_message_as_dialog_id(dialog_id); td_->create_handler(std::move(promise)) - ->send(dialog_id, bot_user_id, std::move(input_user), std::move(url), std::move(theme), reply_to_message_id, - silent, as_dialog_id); + ->send(dialog_id, bot_user_id, std::move(input_user), std::move(url), std::move(theme), std::move(platform), + reply_to_message_id, silent, as_dialog_id); } void AttachMenuManager::open_web_view(int64 query_id, DialogId dialog_id, UserId bot_user_id, diff --git a/td/telegram/AttachMenuManager.h b/td/telegram/AttachMenuManager.h index 18e0822af..3110aaaa6 100644 --- a/td/telegram/AttachMenuManager.h +++ b/td/telegram/AttachMenuManager.h @@ -33,7 +33,7 @@ class AttachMenuManager final : public Actor { void init(); void request_web_view(DialogId dialog_id, UserId bot_user_id, MessageId reply_to_message_id, string &&url, - td_api::object_ptr &&theme, + td_api::object_ptr &&theme, string &&platform, Promise> &&promise); void open_web_view(int64 query_id, DialogId dialog_id, UserId bot_user_id, MessageId reply_to_message_id, diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index d0f10c48a..5aa673229 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -174,7 +174,7 @@ class RequestSimpleWebViewQuery final : public Td::ResultHandler { } void send(tl_object_ptr &&input_user, const string &url, - const td_api::object_ptr &theme) { + const td_api::object_ptr &theme, string &&platform) { tl_object_ptr theme_parameters; int32 flags = 0; if (theme != nullptr) { @@ -184,7 +184,7 @@ class RequestSimpleWebViewQuery final : public Td::ResultHandler { theme_parameters->data_ = ThemeManager::get_theme_parameters_json_string(theme, false); } send_query(G()->net_query_creator().create(telegram_api::messages_requestSimpleWebView( - flags, std::move(input_user), url, std::move(theme_parameters), string()))); + flags, std::move(input_user), url, std::move(theme_parameters), platform))); } void on_result(BufferSlice packet) final { @@ -499,11 +499,12 @@ void InlineQueriesManager::answer_inline_query( void InlineQueriesManager::get_simple_web_view_url(UserId bot_user_id, string &&url, const td_api::object_ptr &theme, - Promise &&promise) { + string &&platform, Promise &&promise) { TRY_RESULT_PROMISE(promise, input_user, td_->contacts_manager_->get_input_user(bot_user_id)); TRY_RESULT_PROMISE(promise, bot_data, td_->contacts_manager_->get_bot_data(bot_user_id)); - td_->create_handler(std::move(promise))->send(std::move(input_user), url, theme); + td_->create_handler(std::move(promise)) + ->send(std::move(input_user), url, theme, std::move(platform)); } void InlineQueriesManager::send_web_view_data(UserId bot_user_id, string &&button_text, string &&data, diff --git a/td/telegram/InlineQueriesManager.h b/td/telegram/InlineQueriesManager.h index d26755a87..99f9da57a 100644 --- a/td/telegram/InlineQueriesManager.h +++ b/td/telegram/InlineQueriesManager.h @@ -46,7 +46,8 @@ class InlineQueriesManager final : public Actor { Promise &&promise) const; void get_simple_web_view_url(UserId bot_user_id, string &&url, - const td_api::object_ptr &theme, Promise &&promise); + const td_api::object_ptr &theme, string &&platform, + Promise &&promise); void send_web_view_data(UserId bot_user_id, string &&button_text, string &&data, Promise &&promise) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7a201b950..842601ae1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -7398,6 +7398,7 @@ void Td::on_request(uint64 id, td_api::answerInlineQuery &request) { void Td::on_request(uint64 id, td_api::getWebAppUrl &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.url_); + CLEAN_INPUT_STRING(request.application_name_); CREATE_REQUEST_PROMISE(); auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { if (result.is_error()) { @@ -7407,7 +7408,8 @@ void Td::on_request(uint64 id, td_api::getWebAppUrl &request) { } }); inline_queries_manager_->get_simple_web_view_url(UserId(request.bot_user_id_), std::move(request.url_), - std::move(request.theme_), std::move(query_promise)); + std::move(request.theme_), std::move(request.application_name_), + std::move(query_promise)); } void Td::on_request(uint64 id, td_api::sendWebAppData &request) { @@ -7422,10 +7424,11 @@ void Td::on_request(uint64 id, td_api::sendWebAppData &request) { void Td::on_request(uint64 id, td_api::openWebApp &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.url_); + CLEAN_INPUT_STRING(request.application_name_); CREATE_REQUEST_PROMISE(); - attach_menu_manager_->request_web_view(DialogId(request.chat_id_), UserId(request.bot_user_id_), - MessageId(request.reply_to_message_id_), std::move(request.url_), - std::move(request.theme_), std::move(promise)); + attach_menu_manager_->request_web_view( + DialogId(request.chat_id_), UserId(request.bot_user_id_), MessageId(request.reply_to_message_id_), + std::move(request.url_), std::move(request.theme_), std::move(request.application_name_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::closeWebApp &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 72c7eda76..5251f1d51 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3582,7 +3582,7 @@ class CliClient final : public Actor { UserId user_id; string url; get_args(args, user_id, url); - send_request(td_api::make_object(user_id, url, get_theme_parameters())); + send_request(td_api::make_object(user_id, url, get_theme_parameters(), "android")); } else if (op == "swad") { UserId user_id; string button_text; @@ -3595,7 +3595,7 @@ class CliClient final : public Actor { string url; MessageId reply_to_message_id; get_args(args, chat_id, bot_user_id, url, reply_to_message_id); - send_request(td_api::make_object(chat_id, bot_user_id, url, get_theme_parameters(), + send_request(td_api::make_object(chat_id, bot_user_id, url, get_theme_parameters(), "android", reply_to_message_id)); } else if (op == "cwa") { int64 launch_id; From 472fdd248e5a49f7e6b9fa084d8f5de34c179564 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 26 Aug 2022 18:03:56 +0300 Subject: [PATCH 019/200] Remove invalid premium payment options. --- td/telegram/ContactsManager.cpp | 4 +--- td/telegram/Premium.cpp | 3 +-- td/telegram/PremiumGiftOption.cpp | 33 +++++++++++++++++++++++++------ td/telegram/PremiumGiftOption.h | 8 ++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index e73f0e6cf..d6b2806b8 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -10901,9 +10901,7 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u bool supports_video_calls = user->video_calls_available_ && !user->phone_calls_private_; bool has_private_calls = user->phone_calls_private_; bool voice_messages_forbidden = u->is_premium ? user->voice_messages_forbidden_ : false; - auto premium_gift_options = transform(std::move(user->premium_gifts_), [](auto &&premium_gift_option) { - return PremiumGiftOption(std::move(premium_gift_option)); - }); + auto premium_gift_options = get_premium_gift_options(std::move(user->premium_gifts_)); AdministratorRights group_administrator_rights(user->bot_group_admin_rights_, ChannelType::Megagroup); AdministratorRights broadcast_administrator_rights(user->bot_broadcast_admin_rights_, ChannelType::Broadcast); if (user_full->can_be_called != can_be_called || user_full->supports_video_calls != supports_video_calls || diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index 238d3485b..db428fca1 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -156,8 +156,7 @@ class GetPremiumPromoQuery final : public Td::ResultHandler { std::move(animation_object))); } - auto period_options = transform(std::move(promo->period_options_), - [](auto &&period_option) { return PremiumGiftOption(std::move(period_option)); }); + auto period_options = get_premium_gift_options(std::move(promo->period_options_)); auto base_premium_gift_it = std::min_element(period_options.begin(), period_options.end()); auto payment_options = transform(period_options, [&base_premium_gift_it](const auto &option) { return option.get_premium_payment_option_object(*base_premium_gift_it); diff --git a/td/telegram/PremiumGiftOption.cpp b/td/telegram/PremiumGiftOption.cpp index f9be04091..0285a4273 100644 --- a/td/telegram/PremiumGiftOption.cpp +++ b/td/telegram/PremiumGiftOption.cpp @@ -9,6 +9,7 @@ #include "td/telegram/LinkManager.h" #include "td/telegram/Payments.h" +#include "td/utils/algorithm.h" #include "td/utils/common.h" #include "td/utils/logging.h" @@ -22,10 +23,6 @@ PremiumGiftOption::PremiumGiftOption(telegram_api::object_ptramount_) , bot_url_(std::move(option->bot_url_)) , store_product_(std::move(option->store_product_)) { - if (amount_ <= 0 || !check_currency_amount(amount_)) { - LOG(ERROR) << "Receive invalid premium gift option amount " << amount_; - amount_ = static_cast(1) << 40; - } } PremiumGiftOption::PremiumGiftOption(telegram_api::object_ptr &&option) @@ -34,10 +31,18 @@ PremiumGiftOption::PremiumGiftOption(telegram_api::object_ptramount_) , bot_url_(std::move(option->bot_url_)) , store_product_(std::move(option->store_product_)) { +} + +bool PremiumGiftOption::is_valid() const { if (amount_ <= 0 || !check_currency_amount(amount_)) { - LOG(ERROR) << "Receive invalid premium gift option amount " << amount_; - amount_ = static_cast(1) << 40; + LOG(ERROR) << "Receive invalid premium payment option amount " << amount_; + return false; } + if (currency_.size() != 3) { + LOG(ERROR) << "Receive invalid premium payment option currency " << currency_; + return false; + } + return true; } double PremiumGiftOption::get_monthly_price() const { @@ -73,4 +78,20 @@ bool operator!=(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs) { return !(lhs == rhs); } +vector get_premium_gift_options( + vector> &&options) { + auto premium_gift_options = transform( + std::move(options), [](auto &&premium_gift_option) { return PremiumGiftOption(std::move(premium_gift_option)); }); + td::remove_if(premium_gift_options, [](const auto &premium_gift_option) { return !premium_gift_option.is_valid(); }); + return premium_gift_options; +} + +vector get_premium_gift_options( + vector> &&options) { + auto premium_gift_options = transform( + std::move(options), [](auto &&premium_gift_option) { return PremiumGiftOption(std::move(premium_gift_option)); }); + td::remove_if(premium_gift_options, [](const auto &premium_gift_option) { return !premium_gift_option.is_valid(); }); + return premium_gift_options; +} + } // namespace td diff --git a/td/telegram/PremiumGiftOption.h b/td/telegram/PremiumGiftOption.h index 694fb24c8..6ed76e3f6 100644 --- a/td/telegram/PremiumGiftOption.h +++ b/td/telegram/PremiumGiftOption.h @@ -34,6 +34,8 @@ class PremiumGiftOption { td_api::object_ptr get_premium_payment_option_object( const PremiumGiftOption &base_option) const; + bool is_valid() const; + template void store(StorerT &storer) const; @@ -44,4 +46,10 @@ class PremiumGiftOption { bool operator==(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs); bool operator!=(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs); +vector get_premium_gift_options( + vector> &&options); + +vector get_premium_gift_options( + vector> &&options); + } // namespace td From 9b87c2237a4148b954ac34bee5655a4fc7184552 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 26 Aug 2022 18:59:29 +0300 Subject: [PATCH 020/200] Add get_premium_payment_options_object fucntion. --- td/telegram/ContactsManager.cpp | 18 +++++++----------- td/telegram/Premium.cpp | 7 ++----- td/telegram/PremiumGiftOption.cpp | 12 ++++++++++++ td/telegram/PremiumGiftOption.h | 3 +++ 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index d6b2806b8..8032ce632 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -16850,18 +16850,14 @@ tl_object_ptr ContactsManager::get_user_full_info_object(U } bio_object = get_formatted_text_object(bio, true, 0); } - auto base_premium_gift_it = - std::min_element(user_full->premium_gift_options.begin(), user_full->premium_gift_options.end()); - auto premium_gift_options = transform(user_full->premium_gift_options, [&base_premium_gift_it](const auto &option) { - return option.get_premium_payment_option_object(*base_premium_gift_it); - }); auto voice_messages_forbidden = is_premium ? user_full->voice_messages_forbidden : false; - return make_tl_object( - get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->is_blocked, - user_full->can_be_called, user_full->supports_video_calls, user_full->has_private_calls, - !user_full->private_forward_name.empty(), voice_messages_forbidden, - user_full->need_phone_number_privacy_exception, std::move(bio_object), std::move(premium_gift_options), - user_full->common_chat_count, std::move(bot_info)); + return make_tl_object(get_chat_photo_object(td_->file_manager_.get(), user_full->photo), + user_full->is_blocked, user_full->can_be_called, + user_full->supports_video_calls, user_full->has_private_calls, + !user_full->private_forward_name.empty(), voice_messages_forbidden, + user_full->need_phone_number_privacy_exception, std::move(bio_object), + get_premium_payment_options_object(user_full->premium_gift_options), + user_full->common_chat_count, std::move(bot_info)); } td_api::object_ptr ContactsManager::get_update_unknown_basic_group_object(ChatId chat_id) { diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index db428fca1..d42ce777a 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -157,12 +157,9 @@ class GetPremiumPromoQuery final : public Td::ResultHandler { } auto period_options = get_premium_gift_options(std::move(promo->period_options_)); - auto base_premium_gift_it = std::min_element(period_options.begin(), period_options.end()); - auto payment_options = transform(period_options, [&base_premium_gift_it](const auto &option) { - return option.get_premium_payment_option_object(*base_premium_gift_it); - }); promise_.set_value(td_api::make_object(get_formatted_text_object(state, true, 0), - std::move(payment_options), std::move(animations))); + get_premium_payment_options_object(period_options), + std::move(animations))); } void on_error(Status status) final { diff --git a/td/telegram/PremiumGiftOption.cpp b/td/telegram/PremiumGiftOption.cpp index 0285a4273..aa99f944c 100644 --- a/td/telegram/PremiumGiftOption.cpp +++ b/td/telegram/PremiumGiftOption.cpp @@ -13,6 +13,7 @@ #include "td/utils/common.h" #include "td/utils/logging.h" +#include #include namespace td { @@ -94,4 +95,15 @@ vector get_premium_gift_options( return premium_gift_options; } +vector> get_premium_payment_options_object( + const vector &options) { + if (options.empty()) { + return {}; + } + auto base_premium_option_it = std::min_element(options.begin(), options.end()); + return transform(options, [&base_premium_option_it](const auto &option) { + return option.get_premium_payment_option_object(*base_premium_option_it); + }); +} + } // namespace td diff --git a/td/telegram/PremiumGiftOption.h b/td/telegram/PremiumGiftOption.h index 6ed76e3f6..09b8be7d1 100644 --- a/td/telegram/PremiumGiftOption.h +++ b/td/telegram/PremiumGiftOption.h @@ -52,4 +52,7 @@ vector get_premium_gift_options( vector get_premium_gift_options( vector> &&options); +vector> get_premium_payment_options_object( + const vector &options); + } // namespace td From 0ed8f95cec737011a3b7a61274fc03e25386cec1 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 27 Aug 2022 11:19:00 +0300 Subject: [PATCH 021/200] Make distribution of dialog unloads uniform instead of normal. --- td/telegram/MessagesManager.cpp | 15 +++++++++------ td/telegram/MessagesManager.h | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1fcf5e409..6c56348c8 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -11626,9 +11626,12 @@ int32 MessagesManager::get_unload_dialog_delay() const { return narrow_cast(td_->option_manager_->get_option_integer("message_unload_delay", default_unload_delay)); } -int32 MessagesManager::get_next_unload_dialog_delay() const { - auto delay = get_unload_dialog_delay(); - return Random::fast(delay / 4, delay / 2); +double MessagesManager::get_next_unload_dialog_delay(Dialog *d) const { + if (d->unload_dialog_delay_seed == 0) { + d->unload_dialog_delay_seed = Random::fast(1, 1000000000); + } + auto delay = get_unload_dialog_delay() / 4; + return delay + delay * 1e-9 * d->unload_dialog_delay_seed; } void MessagesManager::unload_dialog(DialogId dialog_id) { @@ -11676,7 +11679,7 @@ void MessagesManager::unload_dialog(DialogId dialog_id) { if (has_left_to_unload_messages) { LOG(DEBUG) << "Need to unload more messages in " << dialog_id; - pending_unload_dialog_timeout_.add_timeout_in(d->dialog_id.get(), get_next_unload_dialog_delay()); + pending_unload_dialog_timeout_.add_timeout_in(d->dialog_id.get(), get_next_unload_dialog_delay(d)); } else { d->has_unload_timeout = false; } @@ -21221,7 +21224,7 @@ void MessagesManager::close_dialog(Dialog *d) { if (is_message_unload_enabled()) { CHECK(!d->has_unload_timeout); - pending_unload_dialog_timeout_.set_timeout_in(dialog_id.get(), get_next_unload_dialog_delay()); + pending_unload_dialog_timeout_.set_timeout_in(dialog_id.get(), get_next_unload_dialog_delay(d)); d->has_unload_timeout = true; } @@ -34708,7 +34711,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq if (!d->is_opened && d->messages != nullptr && is_message_unload_enabled() && !d->has_unload_timeout) { LOG(INFO) << "Schedule unload of " << dialog_id; - pending_unload_dialog_timeout_.add_timeout_in(dialog_id.get(), get_next_unload_dialog_delay()); + pending_unload_dialog_timeout_.add_timeout_in(dialog_id.get(), get_next_unload_dialog_delay(d)); d->has_unload_timeout = true; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 781ccfef3..ed1d62b79 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1270,6 +1270,7 @@ class MessagesManager final : public Actor { int32 pending_join_request_count = 0; vector pending_join_request_user_ids; int32 have_full_history_source = 0; + int32 unload_dialog_delay_seed = 0; FolderId folder_id; vector dialog_list_ids; // TODO replace with mask @@ -2088,7 +2089,7 @@ class MessagesManager final : public Actor { int32 get_unload_dialog_delay() const; - int32 get_next_unload_dialog_delay() const; + double get_next_unload_dialog_delay(Dialog *d) const; void unload_dialog(DialogId dialog_id); From ddf51a45dbb5d4f606831f2bc3da3f04d5a69a16 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 27 Aug 2022 16:59:34 +0300 Subject: [PATCH 022/200] Improve output of DialogListId to log. --- td/telegram/DialogListId.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/td/telegram/DialogListId.h b/td/telegram/DialogListId.h index 4f8737929..79bc5960a 100644 --- a/td/telegram/DialogListId.h +++ b/td/telegram/DialogListId.h @@ -120,7 +120,14 @@ struct DialogListIdHash { inline StringBuilder &operator<<(StringBuilder &string_builder, DialogListId dialog_list_id) { if (dialog_list_id.is_folder()) { - return string_builder << "chat list " << dialog_list_id.get_folder_id(); + auto folder_id = dialog_list_id.get_folder_id(); + if (folder_id == FolderId::archive()) { + return string_builder << "Archive chat list"; + } + if (folder_id == FolderId::main()) { + return string_builder << "Main chat list"; + } + return string_builder << "chat list " << folder_id; } if (dialog_list_id.is_filter()) { return string_builder << "chat list " << dialog_list_id.get_filter_id(); From b0f4c45104739f8c1667e1961ec8313a2b3bce9d Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 27 Aug 2022 22:37:09 +0300 Subject: [PATCH 023/200] Return a 404 error in case of invalid load_dialog_list call. --- td/telegram/MessagesManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 6c56348c8..6ec3f57a6 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -16841,6 +16841,7 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo if ((!result.empty() && (!exact_limit || limit == 0)) || force || list.list_last_dialog_date_ == MAX_DIALOG_DATE) { if (limit > 0 && list.list_last_dialog_date_ != MAX_DIALOG_DATE) { + LOG(INFO) << "Preload next " << limit << " chats in " << dialog_list_id; load_dialog_list(list, limit, Promise()); } @@ -16874,7 +16875,7 @@ void MessagesManager::load_dialog_list(DialogList &list, int32 limit, Promise Date: Sat, 27 Aug 2022 23:12:50 +0300 Subject: [PATCH 024/200] Remove unknown pinned secret chats if failed to load them. --- td/telegram/MessagesManager.cpp | 44 ++++++++++++++++++++++++--------- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 6ec3f57a6..ba027fe04 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -15116,13 +15116,8 @@ bool MessagesManager::set_dialog_is_pinned(DialogListId dialog_list_id, Dialog * } LOG(INFO) << "Set " << d->dialog_id << " is pinned in " << dialog_list_id << " to " << is_pinned; - if (dialog_list_id.is_folder() && G()->parameters().use_message_db) { - G()->td_db()->get_binlog_pmc()->set( - PSTRING() << "pinned_dialog_ids" << dialog_list_id.get_folder_id().get(), - implode(transform(list->pinned_dialogs_, - [](auto &pinned_dialog) { return PSTRING() << pinned_dialog.get_dialog_id().get(); }), - ',')); - } + + save_pinned_folder_dialog_ids(*list); if (need_update_dialog_lists) { update_dialog_lists(d, std::move(positions), true, false, "set_dialog_is_pinned"); @@ -15130,6 +15125,17 @@ bool MessagesManager::set_dialog_is_pinned(DialogListId dialog_list_id, Dialog * return true; } +void MessagesManager::save_pinned_folder_dialog_ids(const DialogList &list) const { + if (!list.dialog_list_id.is_folder() || !G()->parameters().use_message_db) { + return; + } + G()->td_db()->get_binlog_pmc()->set( + PSTRING() << "pinned_dialog_ids" << list.dialog_list_id.get_folder_id().get(), + implode(transform(list.pinned_dialogs_, + [](auto &pinned_dialog) { return PSTRING() << pinned_dialog.get_dialog_id().get(); }), + ',')); +} + void MessagesManager::set_dialog_reply_markup(Dialog *d, MessageId message_id) { if (td_->auth_manager_->is_bot()) { return; @@ -16777,8 +16783,9 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo } } - bool need_reload_pinned_dialogs = false; if (!list.pinned_dialogs_.empty() && offset < list.pinned_dialogs_.back() && limit > 0) { + bool need_reload_pinned_dialogs = false; + bool need_remove_unknown_secret_chats = false; for (auto &pinned_dialog : list.pinned_dialogs_) { if (offset < pinned_dialog) { auto dialog_id = pinned_dialog.get_dialog_id(); @@ -16787,6 +16794,8 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo LOG(ERROR) << "Failed to load pinned " << dialog_id << " from " << dialog_list_id; if (dialog_id.get_type() != DialogType::SecretChat) { need_reload_pinned_dialogs = true; + } else { + need_remove_unknown_secret_chats = true; } continue; } @@ -16802,9 +16811,20 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo } } } - } - if (need_reload_pinned_dialogs) { - reload_pinned_dialogs(dialog_list_id, Auto()); + if (need_reload_pinned_dialogs) { + reload_pinned_dialogs(dialog_list_id, Auto()); + } + if (need_remove_unknown_secret_chats) { + td::remove_if(list.pinned_dialogs_, [this, &list](const DialogDate &dialog_date) { + auto dialog_id = dialog_date.get_dialog_id(); + if (dialog_id.get_type() == DialogType::SecretChat && !have_dialog_force(dialog_id, "get_dialogs 2")) { + list.pinned_dialog_id_orders_.erase(dialog_id); + return true; + } + return false; + }); + save_pinned_folder_dialog_ids(list); + } } update_list_last_pinned_dialog_date(list); @@ -37510,7 +37530,7 @@ bool MessagesManager::do_update_list_last_pinned_dialog_date(DialogList &list) c } DialogDate max_dialog_date = MIN_DIALOG_DATE; - for (auto &pinned_dialog : list.pinned_dialogs_) { + for (const auto &pinned_dialog : list.pinned_dialogs_) { if (!have_dialog(pinned_dialog.get_dialog_id())) { break; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index ed1d62b79..fc5bd9b62 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2601,6 +2601,8 @@ class MessagesManager final : public Actor { bool set_dialog_is_pinned(DialogListId dialog_list_id, Dialog *d, bool is_pinned, bool need_update_dialog_lists = true); + void save_pinned_folder_dialog_ids(const DialogList &list) const; + void set_dialog_is_marked_as_unread(Dialog *d, bool is_marked_as_unread); void set_dialog_is_blocked(Dialog *d, bool is_blocked); From 49f8b1e14cd297165661f17c643fbfa295edd416 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 28 Aug 2022 00:49:56 +0300 Subject: [PATCH 025/200] Randomize ping delay for different connections. --- td/mtproto/SessionConnection.cpp | 19 +++++++++++-------- td/mtproto/SessionConnection.h | 26 +++++++++++++------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index d6722f264..eb6b35966 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -720,11 +720,13 @@ void SessionConnection::on_read(size_t size) { } SessionConnection::SessionConnection(Mode mode, unique_ptr raw_connection, AuthData *auth_data) - : raw_connection_(std::move(raw_connection)), auth_data_(auth_data) { + : random_delay_(Random::fast(0, 5000000) * 1e-6) + , state_(Init) + , mode_(mode) + , created_at_(Time::now()) + , raw_connection_(std::move(raw_connection)) + , auth_data_(auth_data) { CHECK(raw_connection_); - state_ = Init; - mode_ = mode; - created_at_ = Time::now(); } PollableFdInfo &SessionConnection::get_poll_info() { @@ -969,10 +971,11 @@ void SessionConnection::flush_packet() { { // LOG(ERROR) << (auth_data_->get_header().empty() ? '-' : '+'); uint64 parent_message_id = 0; - auto storer = PacketStorer( - queries, auth_data_->get_header(), std::move(to_ack), ping_id, ping_disconnect_delay() + 2, max_delay, - max_after, max_wait, future_salt_n, to_get_state_info, to_resend_answer, to_cancel_answer, destroy_auth_key, - auth_data_, &container_id, &get_state_info_id, &resend_answer_id, &ping_message_id, &parent_message_id); + auto storer = PacketStorer(queries, auth_data_->get_header(), std::move(to_ack), ping_id, + static_cast(ping_disconnect_delay() + 2.0), max_delay, max_after, + max_wait, future_salt_n, to_get_state_info, to_resend_answer, + to_cancel_answer, destroy_auth_key, auth_data_, &container_id, + &get_state_info_id, &resend_answer_id, &ping_message_id, &parent_message_id); auto quick_ack_token = use_quick_ack ? parent_message_id : 0; send_crypto(storer, quick_ack_token); diff --git a/td/mtproto/SessionConnection.h b/td/mtproto/SessionConnection.h index 0b2e75555..1ba2d3ba6 100644 --- a/td/mtproto/SessionConnection.h +++ b/td/mtproto/SessionConnection.h @@ -139,32 +139,31 @@ class SessionConnection final bool is_main_ = false; bool was_moved_ = false; - int rtt() const { - return max(2, static_cast(raw_connection_->extra().rtt * 1.5 + 1)); + double rtt() const { + return max(2.0, raw_connection_->extra().rtt * 1.5 + 1); } - int32 read_disconnect_delay() const { - return online_flag_ ? rtt() * 7 / 2 : 135; + double read_disconnect_delay() const { + return online_flag_ ? rtt() * 3.5 : 135 + random_delay_; } - int32 ping_disconnect_delay() const { - return (online_flag_ && is_main_) ? rtt() * 5 / 2 : 135; + double ping_disconnect_delay() const { + return online_flag_ && is_main_ ? rtt() * 2.5 : 135 + random_delay_; } - int32 ping_may_delay() const { - return online_flag_ ? rtt() / 2 : 30; + double ping_may_delay() const { + return online_flag_ ? rtt() * 0.5 : 30 + random_delay_; } - int32 ping_must_delay() const { - return online_flag_ ? rtt() : 60; + double ping_must_delay() const { + return online_flag_ ? rtt() : 60 + random_delay_; } double http_max_wait() const { return 25.0; // 25s. Longer could be closed by proxy } - static constexpr int HTTP_MAX_AFTER = 10; // 0.01s - static constexpr int HTTP_MAX_DELAY = 30; // 0.03s - static constexpr int TEMP_KEY_TIMEOUT = 60 * 60 * 24; // one day + static constexpr int HTTP_MAX_AFTER = 10; // 0.01s + static constexpr int HTTP_MAX_DELAY = 30; // 0.03s vector to_send_; vector to_ack_; @@ -182,6 +181,7 @@ class SessionConnection final // nobody cleans up this map. But it should be really small. FlatHashMap> container_to_service_msg_; + double random_delay_ = 0; double last_read_at_ = 0; double last_ping_at_ = 0; double last_pong_at_ = 0; From 1787574262fc162cc98053ffbbbe03e032e9e8dc Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 28 Aug 2022 22:57:19 +0300 Subject: [PATCH 026/200] Avoid expected logging. --- td/telegram/UpdatesManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 2fd5a3a4f..63cf0f211 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -473,7 +473,7 @@ Promise<> UpdatesManager::set_pts(int32 pts, const char *source) { last_get_difference_pts_ = get_pts(); schedule_get_difference("rare pts getDifference"); } - } else if (pts < get_pts()) { + } else if (pts < get_pts() && (pts > 1 || td_->option_manager_->get_option_integer("session_count") <= 1)) { LOG(ERROR) << "Receive wrong pts = " << pts << " from " << source << ". Current pts = " << get_pts(); } return result; From b4b9ff563f9d209cd808815cfbdb91ef6f021208 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 01:16:29 +0300 Subject: [PATCH 027/200] Fix applying of postponed pts updates after pts repair. --- td/telegram/MessagesManager.cpp | 8 ++++---- td/telegram/UpdatesManager.cpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ba027fe04..7ffbaa485 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6396,8 +6396,8 @@ void MessagesManager::skip_old_pending_pts_update(tl_object_ptr(update.get()); auto full_message_id = get_full_message_id(update_new_message->message_, false); if (update_message_ids_.count(full_message_id) > 0) { - if (new_pts == old_pts) { // otherwise message can be already deleted - // apply sent message anyway + if (new_pts == old_pts || old_pts == std::numeric_limits::max()) { + // apply sent message anyway if it is definitely non-deleted or being skipped because of pts overflow on_get_message(std::move(update_new_message->message_), true, false, false, true, true, "updateNewMessage with an awaited message"); return; @@ -6411,8 +6411,8 @@ void MessagesManager::skip_old_pending_pts_update(tl_object_ptrget_id() == updateSentMessage::ID) { auto update_sent_message = static_cast(update.get()); if (being_sent_messages_.count(update_sent_message->random_id_) > 0) { - if (new_pts == old_pts) { // otherwise message can be already deleted - // apply sent message anyway + if (new_pts == old_pts || old_pts == std::numeric_limits::max()) { + // apply sent message anyway if it is definitely non-deleted or being skipped because of pts overflow on_send_message_success(update_sent_message->random_id_, update_sent_message->message_id_, update_sent_message->date_, update_sent_message->ttl_period_, FileId(), "process old updateSentMessage"); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 63cf0f211..370426168 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1063,7 +1063,10 @@ void UpdatesManager::on_get_updates_state(tl_object_ptrpts_; // restoring right pts CHECK(pending_pts_updates_.empty()); + auto real_running_get_difference = running_get_difference_; + running_get_difference_ = false; process_postponed_pts_updates(); // drop all updates with old pts + running_get_difference_ = real_running_get_difference; pts_manager_.init(state->pts_); last_get_difference_pts_ = get_pts(); last_pts_save_time_ = Time::now() - 2 * MAX_PTS_SAVE_DELAY; From 9f564e48d45b742a6758a7e2a563d98a956092a8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 07:10:50 +0300 Subject: [PATCH 028/200] Improve MessageForwardInfo logging. --- td/telegram/MessagesManager.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index fc5bd9b62..a19726540 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1078,13 +1078,26 @@ class MessagesManager final : public Actor { } friend StringBuilder &operator<<(StringBuilder &string_builder, const MessageForwardInfo &forward_info) { - return string_builder << "MessageForwardInfo[" << (forward_info.is_imported ? "imported " : "") << "sender " - << forward_info.sender_user_id << "(" << forward_info.author_signature << "/" - << forward_info.sender_name << "), psa_type " << forward_info.psa_type << ", source " - << forward_info.sender_dialog_id << ", source " << forward_info.message_id << ", from " - << forward_info.from_dialog_id << ", from " << forward_info.from_message_id << " at " - << forward_info.date << " " - << "]"; + string_builder << "MessageForwardInfo[" << (forward_info.is_imported ? "imported " : "") << "sender " + << forward_info.sender_user_id; + if (!forward_info.author_signature.empty() || !forward_info.sender_name.empty()) { + string_builder << '(' << forward_info.author_signature << '/' << forward_info.sender_name << ')'; + } + if (!forward_info.psa_type.empty()) { + string_builder << ", psa_type " << forward_info.psa_type; + } + if (forward_info.sender_dialog_id.is_valid()) { + string_builder << ", source "; + if (forward_info.message_id.is_valid()) { + string_builder << FullMessageId(forward_info.sender_dialog_id, forward_info.message_id); + } else { + string_builder << forward_info.sender_dialog_id; + } + } + if (forward_info.from_dialog_id.is_valid() || forward_info.from_message_id.is_valid()) { + string_builder << ", from " << FullMessageId(forward_info.from_dialog_id, forward_info.from_message_id); + } + return string_builder << " at " << forward_info.date << ']'; } }; From 1e10ece916c57cebb82263924b06ee4d0c754ab8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 07:38:13 +0300 Subject: [PATCH 029/200] Keep dialog object inside channelDifferenceTooLong for following logging. --- td/telegram/MessagesManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7ffbaa485..c5e0cf437 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -38726,10 +38726,10 @@ void MessagesManager::on_get_channel_difference( case telegram_api::updates_channelDifferenceTooLong::ID: { auto difference = move_tl_object_as(difference_ptr); - tl_object_ptr dialog; + telegram_api::dialog *dialog = nullptr; switch (difference->dialog_->get_id()) { case telegram_api::dialog::ID: - dialog = telegram_api::move_object_as(difference->dialog_); + dialog = static_cast(difference->dialog_.get()); break; case telegram_api::dialogFolder::ID: return after_get_channel_difference(dialog_id, false); From 3c56140995ac2b8f241e697a7cf344001b4f07ab Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 15:35:37 +0300 Subject: [PATCH 030/200] Ignore error 400 in GetDialogsQuery. --- td/telegram/MessagesManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c5e0cf437..23b1f1e97 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -303,6 +303,7 @@ class GetDialogQuery final : public Td::ResultHandler { class GetDialogsQuery final : public Td::ResultHandler { Promise promise_; + bool is_single_ = false; public: explicit GetDialogsQuery(Promise &&promise) : promise_(std::move(promise)) { @@ -311,6 +312,7 @@ class GetDialogsQuery final : public Td::ResultHandler { void send(vector input_dialog_ids) { CHECK(!input_dialog_ids.empty()); CHECK(input_dialog_ids.size() <= 100); + is_single_ = input_dialog_ids.size() == 1; auto input_dialog_peers = InputDialogId::get_input_dialog_peers(input_dialog_ids); CHECK(input_dialog_peers.size() == input_dialog_ids.size()); send_query(G()->net_query_creator().create(telegram_api::messages_getPeerDialogs(std::move(input_dialog_peers)))); @@ -332,6 +334,9 @@ class GetDialogsQuery final : public Td::ResultHandler { } void on_error(Status status) final { + if (is_single_ && status.code() == 400) { + return promise_.set_value(Unit()); + } promise_.set_error(std::move(status)); } }; From 398a996ef8c0cbc361797185956929f67d39c101 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 16:19:47 +0300 Subject: [PATCH 031/200] Use explicit EVP_MD_fetch with OpenSSL 3.0, because EVP_sha* fetch algorithm each time and are extremely slow in OpenSSL 3.0. --- tdutils/td/utils/crypto.cpp | 39 ++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index fd077946b..130f2b83e 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -688,11 +688,24 @@ static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) { LOG_IF(FATAL, res != 1); EVP_MD_CTX_free(ctx); } + +static void init_thread_local_evp_md(const EVP_MD *&evp_md, const char *algorithm) { + evp_md = EVP_MD_fetch(nullptr, algorithm, nullptr); + LOG_IF(FATAL, evp_md == nullptr); + detail::add_thread_local_destructor(create_destructor([&evp_md]() mutable { + EVP_MD_free(const_cast(evp_md)); + evp_md = nullptr; + })); +} #endif void sha1(Slice data, unsigned char output[20]) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - make_digest(data, MutableSlice(output, 20), EVP_sha1()); + static TD_THREAD_LOCAL const EVP_MD *evp_md; + if (unlikely(evp_md == nullptr)) { + init_thread_local_evp_md(evp_md, "sha1"); + } + make_digest(data, MutableSlice(output, 20), evp_md); #else auto result = SHA1(data.ubegin(), data.size(), output); CHECK(result == output); @@ -702,7 +715,11 @@ void sha1(Slice data, unsigned char output[20]) { void sha256(Slice data, MutableSlice output) { CHECK(output.size() >= 32); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - make_digest(data, output, EVP_sha256()); + static TD_THREAD_LOCAL const EVP_MD *evp_md; + if (unlikely(evp_md == nullptr)) { + init_thread_local_evp_md(evp_md, "sha256"); + } + make_digest(data, output, evp_md); #else auto result = SHA256(data.ubegin(), data.size(), output.ubegin()); CHECK(result == output.ubegin()); @@ -712,7 +729,11 @@ void sha256(Slice data, MutableSlice output) { void sha512(Slice data, MutableSlice output) { CHECK(output.size() >= 64); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - make_digest(data, output, EVP_sha512()); + static TD_THREAD_LOCAL const EVP_MD *evp_md; + if (unlikely(evp_md == nullptr)) { + init_thread_local_evp_md(evp_md, "sha512"); + } + make_digest(data, output, evp_md); #else auto result = SHA512(data.ubegin(), data.size(), output.ubegin()); CHECK(result == output.ubegin()); @@ -792,7 +813,11 @@ void Sha256State::init() { } CHECK(!is_inited_); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - int err = EVP_DigestInit_ex(impl_->ctx_, EVP_sha256(), nullptr); + static TD_THREAD_LOCAL const EVP_MD *evp_md; + if (unlikely(evp_md == nullptr)) { + init_thread_local_evp_md(evp_md, "sha256"); + } + int err = EVP_DigestInit_ex(impl_->ctx_, evp_md, nullptr); #else int err = SHA256_Init(&impl_->ctx_); #endif @@ -830,7 +855,11 @@ void Sha256State::extract(MutableSlice output, bool destroy) { void md5(Slice input, MutableSlice output) { CHECK(output.size() >= 16); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - make_digest(input, output, EVP_md5()); + static TD_THREAD_LOCAL const EVP_MD *evp_md; + if (unlikely(evp_md == nullptr)) { + init_thread_local_evp_md(evp_md, "md5"); + } + make_digest(input, output, evp_md); #else auto result = MD5(input.ubegin(), input.size(), output.ubegin()); CHECK(result == output.ubegin()); From ad4638d3c95be1e3e7f29c8673e449ef02672052 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 17:08:00 +0300 Subject: [PATCH 032/200] Add SHA benchmarks. --- benchmark/bench_crypto.cpp | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/benchmark/bench_crypto.cpp b/benchmark/bench_crypto.cpp index fc9cdb5a5..1fe3a2b21 100644 --- a/benchmark/bench_crypto.cpp +++ b/benchmark/bench_crypto.cpp @@ -52,6 +52,66 @@ class SHA1Bench final : public td::Benchmark { }; #endif +class SHA1ShortBench final : public td::Benchmark { + public: + alignas(64) unsigned char data[SHORT_DATA_SIZE]; + + std::string get_description() const final { + return PSTRING() << "SHA1 [" << SHORT_DATA_SIZE << "B]"; + } + + void start_up() final { + std::fill(std::begin(data), std::end(data), static_cast(123)); + } + + void run(int n) final { + unsigned char md[20]; + for (int i = 0; i < n; i++) { + td::sha1(td::Slice(data, SHORT_DATA_SIZE), md); + } + } +}; + +class SHA256ShortBench final : public td::Benchmark { + public: + alignas(64) unsigned char data[SHORT_DATA_SIZE]; + + std::string get_description() const final { + return PSTRING() << "SHA256 [" << SHORT_DATA_SIZE << "B]"; + } + + void start_up() final { + std::fill(std::begin(data), std::end(data), static_cast(123)); + } + + void run(int n) final { + unsigned char md[32]; + for (int i = 0; i < n; i++) { + td::sha256(td::Slice(data, SHORT_DATA_SIZE), td::MutableSlice(md, 32)); + } + } +}; + +class SHA512ShortBench final : public td::Benchmark { + public: + alignas(64) unsigned char data[SHORT_DATA_SIZE]; + + std::string get_description() const final { + return PSTRING() << "SHA512 [" << SHORT_DATA_SIZE << "B]"; + } + + void start_up() final { + std::fill(std::begin(data), std::end(data), static_cast(123)); + } + + void run(int n) final { + unsigned char md[64]; + for (int i = 0; i < n; i++) { + td::sha512(td::Slice(data, SHORT_DATA_SIZE), td::MutableSlice(md, 64)); + } + } +}; + class AesEcbBench final : public td::Benchmark { public: alignas(64) unsigned char data[DATA_SIZE]; @@ -415,6 +475,9 @@ int main() { #if OPENSSL_VERSION_NUMBER <= 0x10100000L td::bench(SHA1Bench()); #endif + td::bench(SHA1ShortBench()); + td::bench(SHA256ShortBench()); + td::bench(SHA512ShortBench()); td::bench(Crc32Bench()); td::bench(Crc64Bench()); } From b1000734186c12060ad1f43c2dd520ba974bc430 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 19:41:24 +0300 Subject: [PATCH 033/200] Add HMAC benchmarks. --- benchmark/bench_crypto.cpp | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/benchmark/bench_crypto.cpp b/benchmark/bench_crypto.cpp index 1fe3a2b21..40d7602d2 100644 --- a/benchmark/bench_crypto.cpp +++ b/benchmark/bench_crypto.cpp @@ -112,6 +112,46 @@ class SHA512ShortBench final : public td::Benchmark { } }; +class HmacSha256ShortBench final : public td::Benchmark { + public: + alignas(64) unsigned char data[SHORT_DATA_SIZE]; + + std::string get_description() const final { + return PSTRING() << "HMAC-SHA256 [" << SHORT_DATA_SIZE << "B]"; + } + + void start_up() final { + std::fill(std::begin(data), std::end(data), static_cast(123)); + } + + void run(int n) final { + unsigned char md[32]; + for (int i = 0; i < n; i++) { + td::hmac_sha256(td::Slice(data, SHORT_DATA_SIZE), td::Slice(data, SHORT_DATA_SIZE), td::MutableSlice(md, 32)); + } + } +}; + +class HmacSha512ShortBench final : public td::Benchmark { + public: + alignas(64) unsigned char data[SHORT_DATA_SIZE]; + + std::string get_description() const final { + return PSTRING() << "HMAC-SHA512 [" << SHORT_DATA_SIZE << "B]"; + } + + void start_up() final { + std::fill(std::begin(data), std::end(data), static_cast(123)); + } + + void run(int n) final { + unsigned char md[32]; + for (int i = 0; i < n; i++) { + td::hmac_sha256(td::Slice(data, SHORT_DATA_SIZE), td::Slice(data, SHORT_DATA_SIZE), td::MutableSlice(md, 32)); + } + } +}; + class AesEcbBench final : public td::Benchmark { public: alignas(64) unsigned char data[DATA_SIZE]; @@ -478,6 +518,8 @@ int main() { td::bench(SHA1ShortBench()); td::bench(SHA256ShortBench()); td::bench(SHA512ShortBench()); + td::bench(HmacSha256ShortBench()); + td::bench(HmacSha512ShortBench()); td::bench(Crc32Bench()); td::bench(Crc64Bench()); } From 5e87cae73d5d9bfbde08d3e585f8cdb052e3ce7c Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 20:41:35 +0300 Subject: [PATCH 034/200] Remove unused Evp::init parameter. --- tdutils/td/utils/crypto.cpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index 130f2b83e..a6062f938 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -328,24 +328,24 @@ class Evp { } void init_encrypt_ecb(Slice key) { - init(Type::Ecb, true, EVP_aes_256_ecb(), key); + init(true, EVP_aes_256_ecb(), key); } void init_decrypt_ecb(Slice key) { - init(Type::Ecb, false, EVP_aes_256_ecb(), key); + init(false, EVP_aes_256_ecb(), key); } void init_encrypt_cbc(Slice key) { - init(Type::Cbc, true, EVP_aes_256_cbc(), key); + init(true, EVP_aes_256_cbc(), key); } void init_decrypt_cbc(Slice key) { - init(Type::Cbc, false, EVP_aes_256_cbc(), key); + init(false, EVP_aes_256_cbc(), key); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L void init_encrypt_ctr(Slice key) { - init(Type::Ctr, true, EVP_aes_256_ctr(), key); + init(true, EVP_aes_256_ctr(), key); } #endif @@ -355,8 +355,6 @@ class Evp { } void encrypt(const uint8 *src, uint8 *dst, int size) { - // CHECK(type_ != Type::Empty && is_encrypt_); - // CHECK(size % AES_BLOCK_SIZE == 0); int len; int res = EVP_EncryptUpdate(ctx_, dst, &len, src, size); LOG_IF(FATAL, res != 1); @@ -364,7 +362,6 @@ class Evp { } void decrypt(const uint8 *src, uint8 *dst, int size) { - // CHECK(type_ != Type::Empty && !is_encrypt_); CHECK(size % AES_BLOCK_SIZE == 0); int len; int res = EVP_DecryptUpdate(ctx_, dst, &len, src, size); @@ -374,13 +371,8 @@ class Evp { private: EVP_CIPHER_CTX *ctx_{nullptr}; - enum class Type : int8 { Empty, Ecb, Cbc, Ctr }; - // Type type_{Type::Empty}; - // bool is_encrypt_ = false; - void init(Type type, bool is_encrypt, const EVP_CIPHER *cipher, Slice key) { - // type_ = type; - // is_encrypt_ = is_encrypt; + void init(bool is_encrypt, const EVP_CIPHER *cipher, Slice key) { int res = EVP_CipherInit_ex(ctx_, cipher, nullptr, key.ubegin(), nullptr, is_encrypt ? 1 : 0); LOG_IF(FATAL, res != 1); EVP_CIPHER_CTX_set_padding(ctx_, 0); From ba2c071324b71e035a5d3bb1f3b59fb0e9bf29ab Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 21:16:12 +0300 Subject: [PATCH 035/200] Use explicit EVP_CIPHER_fetch with OpenSSL 3.0, because EVP_aes_* fetch algorithm each time and are extremely slow in OpenSSL 3.0. --- tdutils/td/utils/crypto.cpp | 65 +++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index a6062f938..0f859acd7 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -328,24 +328,64 @@ class Evp { } void init_encrypt_ecb(Slice key) { - init(true, EVP_aes_256_ecb(), key); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static TD_THREAD_LOCAL const EVP_CIPHER *evp_cipher; + if (unlikely(evp_cipher == nullptr)) { + init_thread_local_evp_cipher(evp_cipher, "AES-256-ECB"); + } +#else + const EVP_CIPHER *evp_cipher = EVP_aes_256_ecb(); +#endif + init(true, evp_cipher, key); } void init_decrypt_ecb(Slice key) { - init(false, EVP_aes_256_ecb(), key); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static TD_THREAD_LOCAL const EVP_CIPHER *evp_cipher; + if (unlikely(evp_cipher == nullptr)) { + init_thread_local_evp_cipher(evp_cipher, "AES-256-ECB"); + } +#else + const EVP_CIPHER *evp_cipher = EVP_aes_256_ecb(); +#endif + init(false, evp_cipher, key); } void init_encrypt_cbc(Slice key) { - init(true, EVP_aes_256_cbc(), key); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static TD_THREAD_LOCAL const EVP_CIPHER *evp_cipher; + if (unlikely(evp_cipher == nullptr)) { + init_thread_local_evp_cipher(evp_cipher, "AES-256-CBC"); + } +#else + const EVP_CIPHER *evp_cipher = EVP_aes_256_cbc(); +#endif + init(true, evp_cipher, key); } void init_decrypt_cbc(Slice key) { - init(false, EVP_aes_256_cbc(), key); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static TD_THREAD_LOCAL const EVP_CIPHER *evp_cipher; + if (unlikely(evp_cipher == nullptr)) { + init_thread_local_evp_cipher(evp_cipher, "AES-256-CBC"); + } +#else + const EVP_CIPHER *evp_cipher = EVP_aes_256_cbc(); +#endif + init(false, evp_cipher, key); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L void init_encrypt_ctr(Slice key) { - init(true, EVP_aes_256_ctr(), key); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static TD_THREAD_LOCAL const EVP_CIPHER *evp_cipher; + if (unlikely(evp_cipher == nullptr)) { + init_thread_local_evp_cipher(evp_cipher, "AES-256-CTR"); + } +#else + const EVP_CIPHER *evp_cipher = EVP_aes_256_ctr(); +#endif + init(true, evp_cipher, key); } #endif @@ -372,11 +412,22 @@ class Evp { private: EVP_CIPHER_CTX *ctx_{nullptr}; - void init(bool is_encrypt, const EVP_CIPHER *cipher, Slice key) { - int res = EVP_CipherInit_ex(ctx_, cipher, nullptr, key.ubegin(), nullptr, is_encrypt ? 1 : 0); + void init(bool is_encrypt, const EVP_CIPHER *evp_cipher, Slice key) { + int res = EVP_CipherInit_ex(ctx_, evp_cipher, nullptr, key.ubegin(), nullptr, is_encrypt ? 1 : 0); LOG_IF(FATAL, res != 1); EVP_CIPHER_CTX_set_padding(ctx_, 0); } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + static void init_thread_local_evp_cipher(const EVP_CIPHER *&evp_cipher, const char *algorithm) { + evp_cipher = EVP_CIPHER_fetch(nullptr, algorithm, nullptr); + LOG_IF(FATAL, evp_cipher == nullptr); + detail::add_thread_local_destructor(create_destructor([&evp_cipher]() mutable { + EVP_CIPHER_free(const_cast(evp_cipher)); + evp_cipher = nullptr; + })); + } +#endif }; struct AesState::Impl { From d110b0f5bc306bae82e90543ef75b8f5d5f28429 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 29 Aug 2022 22:43:36 +0300 Subject: [PATCH 036/200] Add MessagesManager::load_dialog_filter_dialogs function. --- td/telegram/MessagesManager.cpp | 34 ++++++++++++++++++--------------- td/telegram/MessagesManager.h | 3 +++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 23b1f1e97..a925aada8 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -16575,6 +16575,23 @@ bool MessagesManager::load_dialog(DialogId dialog_id, int left_tries, Promise &&input_dialog_ids, Promise &&promise) { + const size_t MAX_SLICE_SIZE = 100; // server side limit + MultiPromiseActorSafe mpas{"GetFilterDialogsOnServerMultiPromiseActor"}; + mpas.add_promise(std::move(promise)); + mpas.set_ignore_errors(true); + auto lock = mpas.get_promise(); + + for (size_t i = 0; i < input_dialog_ids.size(); i += MAX_SLICE_SIZE) { + auto end_i = i + MAX_SLICE_SIZE; + auto end = end_i < input_dialog_ids.size() ? input_dialog_ids.begin() + end_i : input_dialog_ids.end(); + td_->create_handler(mpas.get_promise())->send({input_dialog_ids.begin() + i, end}); + } + + lock.set_value(Unit()); +} + void MessagesManager::load_dialog_filter(DialogFilterId dialog_filter_id, bool force, Promise &&promise) { CHECK(!td_->auth_manager_->is_bot()); if (!dialog_filter_id.is_valid()) { @@ -16617,20 +16634,7 @@ void MessagesManager::load_dialog_filter(const DialogFilter *filter, bool force, } if (!input_dialog_ids.empty() && !force) { - const size_t MAX_SLICE_SIZE = 100; // server side limit - MultiPromiseActorSafe mpas{"GetFilterDialogsOnServerMultiPromiseActor"}; - mpas.add_promise(std::move(promise)); - mpas.set_ignore_errors(true); - auto lock = mpas.get_promise(); - - for (size_t i = 0; i < input_dialog_ids.size(); i += MAX_SLICE_SIZE) { - auto end_i = i + MAX_SLICE_SIZE; - auto end = end_i < input_dialog_ids.size() ? input_dialog_ids.begin() + end_i : input_dialog_ids.end(); - td_->create_handler(mpas.get_promise())->send({input_dialog_ids.begin() + i, end}); - } - - lock.set_value(Unit()); - return; + return load_dialog_filter_dialogs(filter->dialog_filter_id, std::move(input_dialog_ids), std::move(promise)); } promise.set_value(Unit()); @@ -16782,7 +16786,7 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo promise.set_value(Unit()); return result; } else { - td_->create_handler(std::move(promise))->send(std::move(input_dialog_ids)); + load_dialog_filter_dialogs(filter->dialog_filter_id, std::move(input_dialog_ids), std::move(promise)); return {}; } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index a19726540..db0406e30 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2781,6 +2781,9 @@ class MessagesManager final : public Actor { td_api::object_ptr get_chat_filter_object(const DialogFilter *filter) const; + void load_dialog_filter_dialogs(DialogFilterId dialog_filter_id, vector &&input_dialog_ids, + Promise &&promise); + void load_dialog_filter(const DialogFilter *filter, bool force, Promise &&promise); void on_get_recommended_dialog_filters(Result>> result, From 408a6a9d746cf8cff0d5c21e178da29a7499e3dd Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 01:18:20 +0300 Subject: [PATCH 037/200] Remove failed to load chats from chat filters. --- td/telegram/InputDialogId.cpp | 7 +++++ td/telegram/InputDialogId.h | 2 ++ td/telegram/MessagesManager.cpp | 53 +++++++++++++++++++++++++++++++-- td/telegram/MessagesManager.h | 3 ++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/td/telegram/InputDialogId.cpp b/td/telegram/InputDialogId.cpp index 3ffb79873..82bc2646d 100644 --- a/td/telegram/InputDialogId.cpp +++ b/td/telegram/InputDialogId.cpp @@ -10,6 +10,7 @@ #include "td/telegram/ChatId.h" #include "td/telegram/UserId.h" +#include "td/utils/algorithm.h" #include "td/utils/logging.h" namespace td { @@ -143,4 +144,10 @@ bool InputDialogId::contains(const vector &input_dialog_ids, Dial return false; } +bool InputDialogId::remove(vector &input_dialog_ids, DialogId dialog_id) { + return td::remove_if(input_dialog_ids, [dialog_id](InputDialogId input_dialog_id) { + return input_dialog_id.get_dialog_id() == dialog_id; + }); +} + } // namespace td diff --git a/td/telegram/InputDialogId.h b/td/telegram/InputDialogId.h index ac03ad0c3..d669b2bb7 100644 --- a/td/telegram/InputDialogId.h +++ b/td/telegram/InputDialogId.h @@ -40,6 +40,8 @@ class InputDialogId { static bool contains(const vector &input_dialog_ids, DialogId dialog_id); + static bool remove(vector &input_dialog_ids, DialogId dialog_id); + bool operator==(const InputDialogId &other) const { return dialog_id == other.dialog_id && access_hash == other.access_hash; } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index a925aada8..827e9a44a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -16580,18 +16580,67 @@ void MessagesManager::load_dialog_filter_dialogs(DialogFilterId dialog_filter_id const size_t MAX_SLICE_SIZE = 100; // server side limit MultiPromiseActorSafe mpas{"GetFilterDialogsOnServerMultiPromiseActor"}; mpas.add_promise(std::move(promise)); - mpas.set_ignore_errors(true); auto lock = mpas.get_promise(); for (size_t i = 0; i < input_dialog_ids.size(); i += MAX_SLICE_SIZE) { auto end_i = i + MAX_SLICE_SIZE; auto end = end_i < input_dialog_ids.size() ? input_dialog_ids.begin() + end_i : input_dialog_ids.end(); - td_->create_handler(mpas.get_promise())->send({input_dialog_ids.begin() + i, end}); + vector slice_input_dialog_ids = {input_dialog_ids.begin() + i, end}; + auto slice_dialog_ids = transform(slice_input_dialog_ids, + [](InputDialogId input_dialog_id) { return input_dialog_id.get_dialog_id(); }); + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), dialog_filter_id, dialog_ids = std::move(slice_dialog_ids), + promise = mpas.get_promise()](Result &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &MessagesManager::on_load_dialog_filter_dialogs, dialog_filter_id, + std::move(dialog_ids), std::move(promise)); + }); + td_->create_handler(std::move(query_promise))->send(std::move(slice_input_dialog_ids)); } lock.set_value(Unit()); } +void MessagesManager::on_load_dialog_filter_dialogs(DialogFilterId dialog_filter_id, vector &&dialog_ids, + Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + td::remove_if(dialog_ids, + [this](DialogId dialog_id) { return have_dialog_force(dialog_id, "on_load_dialog_filter_dialogs"); }); + if (dialog_ids.empty()) { + LOG(INFO) << "All chats from " << dialog_filter_id << " were loaded"; + return promise.set_value(Unit()); + } + + LOG(INFO) << "Failed to load chats " << dialog_ids << " from " << dialog_filter_id; + + auto old_dialog_filter = get_dialog_filter(dialog_filter_id); + if (old_dialog_filter == nullptr) { + return promise.set_value(Unit()); + } + CHECK(is_update_chat_filters_sent_); + + auto new_dialog_filter = td::make_unique(*old_dialog_filter); + for (auto dialog_id : dialog_ids) { + InputDialogId::remove(new_dialog_filter->pinned_dialog_ids, dialog_id); + InputDialogId::remove(new_dialog_filter->included_dialog_ids, dialog_id); + InputDialogId::remove(new_dialog_filter->excluded_dialog_ids, dialog_id); + } + + if (*new_dialog_filter != *old_dialog_filter) { + LOG(INFO) << "Update " << dialog_filter_id << " from " << *old_dialog_filter << " to " << *new_dialog_filter; + edit_dialog_filter(std::move(new_dialog_filter), "on_load_dialog_filter_dialogs"); + save_dialog_filters(); + send_update_chat_filters(); + + synchronize_dialog_filters(); + } + + promise.set_value(Unit()); +} + void MessagesManager::load_dialog_filter(DialogFilterId dialog_filter_id, bool force, Promise &&promise) { CHECK(!td_->auth_manager_->is_bot()); if (!dialog_filter_id.is_valid()) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index db0406e30..cf4ed9c35 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2784,6 +2784,9 @@ class MessagesManager final : public Actor { void load_dialog_filter_dialogs(DialogFilterId dialog_filter_id, vector &&input_dialog_ids, Promise &&promise); + void on_load_dialog_filter_dialogs(DialogFilterId dialog_filter_id, vector &&dialog_ids, + Promise &&promise); + void load_dialog_filter(const DialogFilter *filter, bool force, Promise &&promise); void on_get_recommended_dialog_filters(Result>> result, From 6fbb4ef09a94dfa5db4ffe847e2a47385c2e9766 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 02:09:00 +0300 Subject: [PATCH 038/200] Use static helpers from InputDialogId. --- td/telegram/InputDialogId.cpp | 4 +++ td/telegram/InputDialogId.h | 2 ++ td/telegram/MessagesManager.cpp | 46 ++++++++++++--------------------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/td/telegram/InputDialogId.cpp b/td/telegram/InputDialogId.cpp index 82bc2646d..9ba53e3dc 100644 --- a/td/telegram/InputDialogId.cpp +++ b/td/telegram/InputDialogId.cpp @@ -71,6 +71,10 @@ vector InputDialogId::get_input_dialog_ids( return result; } +vector InputDialogId::get_dialog_ids(const vector &input_dialog_ids) { + return transform(input_dialog_ids, [](InputDialogId input_dialog_id) { return input_dialog_id.get_dialog_id(); }); +} + vector> InputDialogId::get_input_dialog_peers( const vector &input_dialog_ids) { vector> result; diff --git a/td/telegram/InputDialogId.h b/td/telegram/InputDialogId.h index d669b2bb7..ed3a87968 100644 --- a/td/telegram/InputDialogId.h +++ b/td/telegram/InputDialogId.h @@ -30,6 +30,8 @@ class InputDialogId { static vector get_input_dialog_ids(const vector> &input_peers, FlatHashSet *added_dialog_ids = nullptr); + static vector get_dialog_ids(const vector &input_dialog_ids); + static vector> get_input_dialog_peers( const vector &input_dialog_ids); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 827e9a44a..d06d945ce 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -15033,12 +15033,8 @@ bool MessagesManager::is_dialog_pinned(DialogListId dialog_list_id, DialogId dia } if (dialog_list_id.is_filter()) { const auto *filter = get_dialog_filter(dialog_list_id.get_filter_id()); - if (filter != nullptr) { - for (const auto &input_dialog_id : filter->pinned_dialog_ids) { - if (input_dialog_id.get_dialog_id() == dialog_id) { - return true; - } - } + if (filter != nullptr && InputDialogId::contains(filter->pinned_dialog_ids, dialog_id)) { + return true; } } return false; @@ -16586,17 +16582,15 @@ void MessagesManager::load_dialog_filter_dialogs(DialogFilterId dialog_filter_id auto end_i = i + MAX_SLICE_SIZE; auto end = end_i < input_dialog_ids.size() ? input_dialog_ids.begin() + end_i : input_dialog_ids.end(); vector slice_input_dialog_ids = {input_dialog_ids.begin() + i, end}; - auto slice_dialog_ids = transform(slice_input_dialog_ids, - [](InputDialogId input_dialog_id) { return input_dialog_id.get_dialog_id(); }); - auto query_promise = - PromiseCreator::lambda([actor_id = actor_id(this), dialog_filter_id, dialog_ids = std::move(slice_dialog_ids), - promise = mpas.get_promise()](Result &&result) mutable { - if (result.is_error()) { - return promise.set_error(result.move_as_error()); - } - send_closure(actor_id, &MessagesManager::on_load_dialog_filter_dialogs, dialog_filter_id, - std::move(dialog_ids), std::move(promise)); - }); + auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), dialog_filter_id, + dialog_ids = InputDialogId::get_dialog_ids(slice_input_dialog_ids), + promise = mpas.get_promise()](Result &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &MessagesManager::on_load_dialog_filter_dialogs, dialog_filter_id, std::move(dialog_ids), + std::move(promise)); + }); td_->create_handler(std::move(query_promise))->send(std::move(slice_input_dialog_ids)); } @@ -17255,7 +17249,7 @@ vector MessagesManager::get_pinned_dialog_ids(DialogListId dialog_list if (filter == nullptr) { return {}; } - return transform(filter->pinned_dialog_ids, [](auto &input_dialog) { return input_dialog.get_dialog_id(); }); + return InputDialogId::get_dialog_ids(filter->pinned_dialog_ids); } auto *list = get_dialog_list(dialog_list_id); @@ -20069,16 +20063,13 @@ Status MessagesManager::toggle_dialog_is_pinned(DialogListId dialog_list_id, Dia auto old_dialog_filter = get_dialog_filter(dialog_filter_id); CHECK(old_dialog_filter != nullptr); auto new_dialog_filter = make_unique(*old_dialog_filter); - auto is_changed_dialog = [dialog_id](InputDialogId input_dialog_id) { - return dialog_id == input_dialog_id.get_dialog_id(); - }; if (is_pinned) { new_dialog_filter->pinned_dialog_ids.insert(new_dialog_filter->pinned_dialog_ids.begin(), get_input_dialog_id(dialog_id)); - td::remove_if(new_dialog_filter->included_dialog_ids, is_changed_dialog); - td::remove_if(new_dialog_filter->excluded_dialog_ids, is_changed_dialog); + InputDialogId::remove(new_dialog_filter->included_dialog_ids, dialog_id); + InputDialogId::remove(new_dialog_filter->excluded_dialog_ids, dialog_id); } else { - bool is_removed = td::remove_if(new_dialog_filter->pinned_dialog_ids, is_changed_dialog); + bool is_removed = InputDialogId::remove(new_dialog_filter->pinned_dialog_ids, dialog_id); CHECK(is_removed); new_dialog_filter->included_dialog_ids.push_back(get_input_dialog_id(dialog_id)); } @@ -33451,9 +33442,7 @@ vector MessagesManager::get_dialog_lists_to_add_dialog(DialogId di auto new_dialog_filter = make_unique(*dialog_filter); new_dialog_filter->included_dialog_ids.push_back(get_input_dialog_id(dialog_id)); - td::remove_if(new_dialog_filter->excluded_dialog_ids, [dialog_id](InputDialogId input_dialog_id) { - return dialog_id == input_dialog_id.get_dialog_id(); - }); + InputDialogId::remove(new_dialog_filter->excluded_dialog_ids, dialog_id); if (new_dialog_filter->check_limits().is_ok()) { result.push_back(DialogListId(dialog_filter_id)); @@ -33495,8 +33484,7 @@ void MessagesManager::add_dialog_to_list(DialogId dialog_id, DialogListId dialog auto new_dialog_filter = make_unique(*old_dialog_filter); new_dialog_filter->included_dialog_ids.push_back(get_input_dialog_id(dialog_id)); - td::remove_if(new_dialog_filter->excluded_dialog_ids, - [dialog_id](InputDialogId input_dialog_id) { return dialog_id == input_dialog_id.get_dialog_id(); }); + InputDialogId::remove(new_dialog_filter->excluded_dialog_ids, dialog_id); auto status = new_dialog_filter->check_limits(); if (status.is_error()) { From 560dd914b3a2777bfb1e82ba19a02037eb13f127 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 08:12:14 +0300 Subject: [PATCH 039/200] Unify names of functions, returning list of td_api objects. --- td/telegram/WebPageBlock.cpp | 22 +++++++++++----------- td/telegram/WebPageBlock.h | 2 +- td/telegram/WebPagesManager.cpp | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/td/telegram/WebPageBlock.cpp b/td/telegram/WebPageBlock.cpp index 229c00bd1..bdf2ab925 100644 --- a/td/telegram/WebPageBlock.cpp +++ b/td/telegram/WebPageBlock.cpp @@ -53,7 +53,7 @@ struct GetWebPageBlockObjectContext { std::unordered_map anchors_; // anchor -> text }; -static vector> get_page_block_objects( +static vector> get_page_blocks_object( const vector> &page_blocks, GetWebPageBlockObjectContext *context) { return transform(page_blocks, [context](const unique_ptr &page_block) { return page_block->get_page_block_object(context); @@ -61,7 +61,7 @@ static vector> get_page_block_objects( } class RichText { - static vector> get_rich_text_objects(const vector &rich_texts, + static vector> get_rich_texts_object(const vector &rich_texts, GetWebPageBlockObjectContext *context) { return transform(rich_texts, [context](const RichText &rich_text) { return rich_text.get_rich_text_object(context); }); @@ -152,7 +152,7 @@ class RichText { case RichText::Type::EmailAddress: return make_tl_object(texts[0].get_rich_text_object(context), content); case RichText::Type::Concatenation: - return make_tl_object(get_rich_text_objects(texts, context)); + return make_tl_object(get_rich_texts_object(texts, context)); case RichText::Type::Subscript: return make_tl_object(texts[0].get_rich_text_object(context)); case RichText::Type::Superscript: @@ -832,7 +832,7 @@ class WebPageBlockList final : public WebPageBlock { Context *context) { // if label is empty, then Bullet U+2022 is used as a label return td_api::make_object(item.label.empty() ? "\xE2\x80\xA2" : item.label, - get_page_block_objects(item.page_blocks, context)); + get_page_blocks_object(item.page_blocks, context)); } public: @@ -1291,7 +1291,7 @@ class WebPageBlockEmbeddedPost final : public WebPageBlock { td_api::object_ptr get_page_block_object(Context *context) const final { return make_tl_object( url, author, get_photo_object(context->td_->file_manager_.get(), author_photo), date, - get_page_block_objects(page_blocks, context), caption.get_page_block_caption_object(context)); + get_page_blocks_object(page_blocks, context), caption.get_page_block_caption_object(context)); } template @@ -1339,7 +1339,7 @@ class WebPageBlockCollage final : public WebPageBlock { } td_api::object_ptr get_page_block_object(Context *context) const final { - return make_tl_object(get_page_block_objects(page_blocks, context), + return make_tl_object(get_page_blocks_object(page_blocks, context), caption.get_page_block_caption_object(context)); } @@ -1380,7 +1380,7 @@ class WebPageBlockSlideshow final : public WebPageBlock { } td_api::object_ptr get_page_block_object(Context *context) const final { - return make_tl_object(get_page_block_objects(page_blocks, context), + return make_tl_object(get_page_blocks_object(page_blocks, context), caption.get_page_block_caption_object(context)); } @@ -1591,7 +1591,7 @@ class WebPageBlockDetails final : public WebPageBlock { td_api::object_ptr get_page_block_object(Context *context) const final { return make_tl_object(header.get_rich_text_object(context), - get_page_block_objects(page_blocks, context), is_open); + get_page_blocks_object(page_blocks, context), is_open); } template @@ -2386,19 +2386,19 @@ vector> get_web_page_blocks( return result; } -vector> get_page_block_objects( +vector> get_page_blocks_object( const vector> &page_blocks, Td *td, Slice base_url) { GetWebPageBlockObjectContext context; context.td_ = td; context.base_url_ = base_url; - auto blocks = get_page_block_objects(page_blocks, &context); + auto blocks = get_page_blocks_object(page_blocks, &context); if (context.anchors_.empty() || !context.has_anchor_urls_) { return blocks; } context.is_first_pass_ = false; context.anchors_.emplace(Slice(), nullptr); // back to top - return get_page_block_objects(page_blocks, &context); + return get_page_blocks_object(page_blocks, &context); } } // namespace td diff --git a/td/telegram/WebPageBlock.h b/td/telegram/WebPageBlock.h index 64247231d..81e5f4701 100644 --- a/td/telegram/WebPageBlock.h +++ b/td/telegram/WebPageBlock.h @@ -101,7 +101,7 @@ vector> get_web_page_blocks( const FlatHashMap &documents, const FlatHashMap> &photos, const FlatHashMap &videos, const FlatHashMap &voice_notes); -vector> get_page_block_objects( +vector> get_page_blocks_object( const vector> &page_blocks, Td *td, Slice base_url); } // namespace td diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 9cb565dc5..522dea0b8 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -1311,7 +1311,7 @@ tl_object_ptr WebPagesManager::get_web_page_instant_ auto feedback_link = td_api::make_object( "previews", PSTRING() << "webpage" << web_page_id.get(), true); return td_api::make_object( - get_page_block_objects(web_page_instant_view->page_blocks, td_, web_page_instant_view->url), + get_page_blocks_object(web_page_instant_view->page_blocks, td_, web_page_instant_view->url), web_page_instant_view->view_count, web_page_instant_view->is_v2 ? 2 : 1, web_page_instant_view->is_rtl, web_page_instant_view->is_full, std::move(feedback_link)); } From 0b8e1430563e1fea158487891caf65c9997b41c1 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 11:45:27 +0300 Subject: [PATCH 040/200] Add class ChatAvailableReactions. --- CMakeLists.txt | 2 + td/generate/scheme/td_api.tl | 23 ++++--- td/telegram/AvailableReaction.cpp | 22 ++----- td/telegram/AvailableReaction.h | 5 +- td/telegram/ChatReactions.cpp | 99 +++++++++++++++++++++++++++++++ td/telegram/ChatReactions.h | 78 ++++++++++++++++++++++++ td/telegram/DialogEventLog.cpp | 7 ++- td/telegram/MessagesManager.cpp | 49 +++++++++------ td/telegram/MessagesManager.h | 13 ++-- td/telegram/Td.cpp | 3 - td/telegram/cli.cpp | 12 +++- 11 files changed, 258 insertions(+), 55 deletions(-) create mode 100644 td/telegram/ChatReactions.cpp create mode 100644 td/telegram/ChatReactions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 24c365497..e266ca3c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ set(TDLIB_SOURCE td/telegram/CallManager.cpp td/telegram/CallbackQueriesManager.cpp td/telegram/ChannelParticipantFilter.cpp + td/telegram/ChatReactions.cpp td/telegram/ClientActor.cpp td/telegram/ConfigManager.cpp td/telegram/ConnectionState.cpp @@ -505,6 +506,7 @@ set(TDLIB_SOURCE td/telegram/ChannelParticipantFilter.h td/telegram/ChannelType.h td/telegram/ChatId.h + td/telegram/ChatReactions.h td/telegram/ClientActor.h td/telegram/ConfigManager.h td/telegram/ConnectionState.h diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index dea413588..88c76f6b8 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1069,6 +1069,15 @@ chatSourcePublicServiceAnnouncement type:string text:string = ChatSource; chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition; +//@class ChatAvailableReactions @description Describes reactions available in the chat + +//@description All reactions are available in the chat +chatAvailableReactionsAll = ChatAvailableReactions; + +//@description Only specific reactions are available in the chat @reactions The list of reactions +chatAvailableReactionsSome reactions:vector = ChatAvailableReactions; + + //@description Describes a video chat //@group_call_id Group call identifier of an active video chat; 0 if none. Full information about the video chat can be received through the method getGroupCall //@has_participants True, if the video chat has participants @@ -1099,7 +1108,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa //@unread_mention_count Number of unread messages with a mention/reply in the chat //@unread_reaction_count Number of messages with unread reactions in the chat //@notification_settings Notification settings for the chat -//@available_reactions List of reactions, available in the chat +//@available_reactions Types of reaction, available in the chat //@message_ttl Current message Time To Live setting (self-destruct timer) for the chat; 0 if not defined. TTL is counted from the time message or its content is viewed in secret chats and from the send date in other chats //@theme_name If non-empty, name of a theme, set for the chat //@action_bar Information about actions which must be possible to do through the chat action bar; may be null @@ -1108,7 +1117,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa //@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat //@draft_message A draft of a message in the chat; may be null //@client_data Application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used -chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector message_sender_id:MessageSender has_protected_content:Bool is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:vector message_ttl:int32 theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; +chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector message_sender_id:MessageSender has_protected_content:Bool is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:ChatAvailableReactions message_ttl:int32 theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; //@description Represents a list of chats @total_count Approximate total number of chats found @chat_ids List of chat identifiers chats total_count:int32 chat_ids:vector = Chats; @@ -2832,7 +2841,7 @@ chatEventMemberPromoted user_id:int53 old_status:ChatMemberStatus new_status:Cha chatEventMemberRestricted member_id:MessageSender old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction; //@description The chat available reactions were changed @old_available_reactions Previous chat available reactions @new_available_reactions New chat available reactions -chatEventAvailableReactionsChanged old_available_reactions:vector new_available_reactions:vector = ChatEventAction; +chatEventAvailableReactionsChanged old_available_reactions:ChatAvailableReactions new_available_reactions:ChatAvailableReactions = ChatEventAction; //@description The chat description was changed @old_description Previous chat description @new_description New chat description chatEventDescriptionChanged old_description:string new_description:string = ChatEventAction; @@ -4247,8 +4256,8 @@ updateChatReadOutbox chat_id:int53 last_read_outbox_message_id:int53 = Update; //@description The chat action bar was changed @chat_id Chat identifier @action_bar The new value of the action bar; may be null updateChatActionBar chat_id:int53 action_bar:ChatActionBar = Update; -//@description The chat available reactions were changed @chat_id Chat identifier @available_reactions The new list of reactions, available in the chat -updateChatAvailableReactions chat_id:int53 available_reactions:vector = Update; +//@description The chat available reactions were changed @chat_id Chat identifier @available_reactions The new reactions, available in the chat +updateChatAvailableReactions chat_id:int53 available_reactions:ChatAvailableReactions = Update; //@description A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update mustn't be applied @chat_id Chat identifier @draft_message The new draft message; may be null @positions The new chat positions in the chat lists updateChatDraftMessage chat_id:int53 draft_message:draftMessage positions:vector = Update; @@ -5434,8 +5443,8 @@ toggleChatIsMarkedAsUnread chat_id:int53 is_marked_as_unread:Bool = Ok; //@description Changes the value of the default disable_notification parameter, used when a message is sent to a chat @chat_id Chat identifier @default_disable_notification New value of default_disable_notification toggleChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Ok; -//@description Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires can_change_info administrator right @chat_id Identifier of the chat @available_reactions New list of reactions, available in the chat. All reactions must be active -setChatAvailableReactions chat_id:int53 available_reactions:vector = Ok; +//@description Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires can_change_info administrator right @chat_id Identifier of the chat @available_reactions Reactions available in the chat. All emoji reactions must be active +setChatAvailableReactions chat_id:int53 available_reactions:ChatAvailableReactions = Ok; //@description Changes application-specific data associated with a chat @chat_id Chat identifier @client_data New value of client_data setChatClientData chat_id:int53 client_data:string = Ok; diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index 045a15903..1b0304dae 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -22,32 +22,22 @@ AvailableReactionType get_reaction_type(const vector &availab return AvailableReactionType::Unavailable; } -vector get_active_reactions(const vector &available_reactions, - const vector &active_reactions) { +ChatReactions get_active_reactions(const ChatReactions &available_reactions, + const vector &active_reactions) { if (available_reactions.empty()) { // fast path return available_reactions; } - if (available_reactions.size() == active_reactions.size()) { - size_t i; - for (i = 0; i < available_reactions.size(); i++) { - if (available_reactions[i] != active_reactions[i].reaction_) { - break; - } - } - if (i == available_reactions.size()) { - // fast path - return available_reactions; - } - } + CHECK(!available_reactions.allow_all_); + CHECK(!available_reactions.allow_custom_); vector result; for (const auto &active_reaction : active_reactions) { - if (td::contains(available_reactions, active_reaction.reaction_)) { + if (td::contains(available_reactions.reactions_, active_reaction.reaction_)) { result.push_back(active_reaction.reaction_); } } - return result; + return ChatReactions(std::move(result)); } bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs) { diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h index a5a56e3b7..becd0c782 100644 --- a/td/telegram/AvailableReaction.h +++ b/td/telegram/AvailableReaction.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/ChatReactions.h" #include "td/telegram/td_api.h" #include "td/utils/common.h" @@ -29,7 +30,7 @@ enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); -vector get_active_reactions(const vector &available_reactions, - const vector &active_reactions); +ChatReactions get_active_reactions(const ChatReactions &available_reactions, + const vector &active_reactions); } // namespace td diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp new file mode 100644 index 000000000..8e9e4d87d --- /dev/null +++ b/td/telegram/ChatReactions.cpp @@ -0,0 +1,99 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/ChatReactions.h" + +#include "td/telegram/MessageReaction.h" + +#include "td/utils/algorithm.h" + +namespace td { + +ChatReactions::ChatReactions(telegram_api::object_ptr &&chat_reactions_ptr) { + if (chat_reactions_ptr == nullptr) { + return; + } + switch (chat_reactions_ptr->get_id()) { + case telegram_api::chatReactionsNone::ID: + break; + case telegram_api::chatReactionsAll::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + allow_all_ = true; + allow_custom_ = chat_reactions->allow_custom_; + break; + } + case telegram_api::chatReactionsSome::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + reactions_ = + transform(chat_reactions->reactions_, [](const telegram_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + break; + } + default: + UNREACHABLE(); + } +} + +ChatReactions::ChatReactions(td_api::object_ptr &&chat_reactions_ptr, + bool allow_custom) { + if (chat_reactions_ptr == nullptr) { + return; + } + switch (chat_reactions_ptr->get_id()) { + case td_api::chatAvailableReactionsAll::ID: + allow_all_ = true; + allow_custom_ = allow_custom; + break; + case td_api::chatAvailableReactionsSome::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + reactions_ = transform(chat_reactions->reactions_, [](const td_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + break; + } + default: + UNREACHABLE(); + } +} + +td_api::object_ptr ChatReactions::get_chat_available_reactions_object() const { + if (allow_all_) { + return td_api::make_object(); + } + return td_api::make_object(transform(reactions_, get_reaction_type_object)); +} + +telegram_api::object_ptr ChatReactions::get_input_chat_reactions() const { + if (allow_all_) { + int32 flags = 0; + if (allow_custom_) { + flags |= telegram_api::chatReactionsAll::ALLOW_CUSTOM_MASK; + } + return telegram_api::make_object(flags, false /*ignored*/); + } + if (!reactions_.empty()) { + return telegram_api::make_object(transform(reactions_, get_input_reaction)); + } + return telegram_api::make_object(); +} + +bool operator==(const ChatReactions &lhs, const ChatReactions &rhs) { + // don't compare allow_custom_ + return lhs.reactions_ == rhs.reactions_ && lhs.allow_all_ == rhs.allow_all_; +} + +StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &reactions) { + if (reactions.allow_all_) { + if (reactions.allow_custom_) { + return string_builder << "AllReactions"; + } + return string_builder << "AllRegularReactions"; + } + return string_builder << '[' << reactions.reactions_ << ']'; +} + +} // namespace td diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h new file mode 100644 index 000000000..5a52c22b5 --- /dev/null +++ b/td/telegram/ChatReactions.h @@ -0,0 +1,78 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +struct ChatReactions { + vector reactions_; + bool allow_all_ = false; // implies empty reactions + bool allow_custom_ = false; // implies allow_all + + ChatReactions() = default; + + explicit ChatReactions(vector &&reactions) : reactions_(std::move(reactions)) { + } + + explicit ChatReactions(telegram_api::object_ptr &&chat_reactions_ptr); + + ChatReactions(td_api::object_ptr &&chat_reactions_ptr, bool allow_custom); + + ChatReactions(bool allow_all, bool allow_custom) : allow_all_(allow_all), allow_custom_(allow_custom) { + } + + telegram_api::object_ptr get_input_chat_reactions() const; + + td_api::object_ptr get_chat_available_reactions_object() const; + + bool empty() const { + return reactions_.empty() && !allow_all_; + } + + template + void store(StorerT &storer) const { + bool has_reactions = !reactions_.empty(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(allow_all_); + STORE_FLAG(allow_custom_); + STORE_FLAG(has_reactions); + END_STORE_FLAGS(); + if (has_reactions) { + td::store(reactions_, storer); + } + } + + template + void parse(ParserT &parser) { + bool has_reactions; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(allow_all_); + PARSE_FLAG(allow_custom_); + PARSE_FLAG(has_reactions); + END_PARSE_FLAGS(); + if (has_reactions) { + td::parse(reactions_, parser); + } + } +}; + +bool operator==(const ChatReactions &lhs, const ChatReactions &rhs); + +inline bool operator!=(const ChatReactions &lhs, const ChatReactions &rhs) { + return !(lhs == rhs); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &reactions); + +} // namespace td diff --git a/td/telegram/DialogEventLog.cpp b/td/telegram/DialogEventLog.cpp index 76763f1f4..ff7c8928f 100644 --- a/td/telegram/DialogEventLog.cpp +++ b/td/telegram/DialogEventLog.cpp @@ -7,6 +7,7 @@ #include "td/telegram/DialogEventLog.h" #include "td/telegram/ChannelId.h" +#include "td/telegram/ChatReactions.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DialogInviteLink.h" #include "td/telegram/DialogLocation.h" @@ -346,7 +347,11 @@ static td_api::object_ptr get_chat_event_action_object( } case telegram_api::channelAdminLogEventActionChangeAvailableReactions::ID: { auto action = move_tl_object_as(action_ptr); - return nullptr; + ChatReactions old_available_reactions(std::move(action->prev_value_)); + ChatReactions new_available_reactions(std::move(action->new_value_)); + return td_api::make_object( + old_available_reactions.get_chat_available_reactions_object(), + new_available_reactions.get_chat_available_reactions_object()); } default: UNREACHABLE(); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d06d945ce..7966a0850 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1427,14 +1427,14 @@ class SetChatAvailableReactionsQuery final : public Td::ResultHandler { explicit SetChatAvailableReactionsQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(DialogId dialog_id, vector available_reactions) { + void send(DialogId dialog_id, const ChatReactions &available_reactions) { dialog_id_ = dialog_id; auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { return on_error(Status::Error(400, "Can't access the chat")); } send_query(G()->net_query_creator().create(telegram_api::messages_setChatAvailableReactions( - std::move(input_peer), make_tl_object()))); + std::move(input_peer), available_reactions.get_input_chat_reactions()))); } void on_result(BufferSlice packet) final { @@ -5208,9 +5208,10 @@ void MessagesManager::Dialog::store(StorerT &storer) const { bool has_pending_join_requests = pending_join_request_count != 0; bool has_action_bar = action_bar != nullptr; bool has_default_send_message_as_dialog_id = default_send_message_as_dialog_id.is_valid(); - bool has_available_reactions = !available_reactions.empty(); + bool has_legacy_available_reactions = false; bool has_available_reactions_generation = available_reactions_generation != 0; bool has_have_full_history_source = have_full_history && have_full_history_source != 0; + bool has_available_reactions = !available_reactions.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(has_draft_message); STORE_FLAG(has_last_database_message); @@ -5287,10 +5288,11 @@ void MessagesManager::Dialog::store(StorerT &storer) const { STORE_FLAG(has_action_bar); STORE_FLAG(has_default_send_message_as_dialog_id); STORE_FLAG(need_drop_default_send_message_as_dialog_id); - STORE_FLAG(has_available_reactions); + STORE_FLAG(has_legacy_available_reactions); STORE_FLAG(is_available_reactions_inited); STORE_FLAG(has_available_reactions_generation); STORE_FLAG(has_have_full_history_source); + STORE_FLAG(has_available_reactions); END_STORE_FLAGS(); } @@ -5448,9 +5450,10 @@ void MessagesManager::Dialog::parse(ParserT &parser) { bool action_bar_can_invite_members = false; bool has_action_bar = false; bool has_default_send_message_as_dialog_id = false; - bool has_available_reactions = false; + bool has_legacy_available_reactions = false; bool has_available_reactions_generation = false; bool has_have_full_history_source = false; + bool has_available_reactions = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_draft_message); PARSE_FLAG(has_last_database_message); @@ -5542,10 +5545,11 @@ void MessagesManager::Dialog::parse(ParserT &parser) { PARSE_FLAG(has_action_bar); PARSE_FLAG(has_default_send_message_as_dialog_id); PARSE_FLAG(need_drop_default_send_message_as_dialog_id); - PARSE_FLAG(has_available_reactions); + PARSE_FLAG(has_legacy_available_reactions); PARSE_FLAG(is_available_reactions_inited); PARSE_FLAG(has_available_reactions_generation); PARSE_FLAG(has_have_full_history_source); + PARSE_FLAG(has_available_reactions); END_PARSE_FLAGS(); } else { need_repair_action_bar = false; @@ -5696,6 +5700,10 @@ void MessagesManager::Dialog::parse(ParserT &parser) { } if (has_available_reactions) { parse(available_reactions, parser); + } else if (has_legacy_available_reactions) { + vector legacy_available_reactions; + parse(legacy_available_reactions, parser); + available_reactions = ChatReactions(std::move(legacy_available_reactions)); } if (has_available_reactions_generation) { parse(available_reactions_generation, parser); @@ -8130,11 +8138,10 @@ void MessagesManager::on_update_dialog_available_reactions( return; } - vector legacy_available_reactions; - set_dialog_available_reactions(d, std::move(legacy_available_reactions)); + set_dialog_available_reactions(d, ChatReactions(std::move(available_reactions))); } -void MessagesManager::set_dialog_available_reactions(Dialog *d, vector &&available_reactions) { +void MessagesManager::set_dialog_available_reactions(Dialog *d, ChatReactions &&available_reactions) { CHECK(!td_->auth_manager_->is_bot()); CHECK(d != nullptr); switch (d->dialog_id.get_type()) { @@ -8276,15 +8283,15 @@ void MessagesManager::set_active_reactions(vector active_reac }); } -vector MessagesManager::get_active_reactions(const vector &available_reactions) const { +ChatReactions MessagesManager::get_active_reactions(const ChatReactions &available_reactions) const { return ::td::get_active_reactions(available_reactions, active_reactions_); } -vector MessagesManager::get_dialog_active_reactions(const Dialog *d) const { +ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) const { CHECK(d != nullptr); switch (d->dialog_id.get_type()) { case DialogType::User: - return transform(active_reactions_, [](auto &reaction) { return reaction.reaction_; }); + return ChatReactions(true, true); case DialogType::Chat: case DialogType::Channel: return get_active_reactions(d->available_reactions); @@ -8310,7 +8317,7 @@ vector MessagesManager::get_message_active_reactions(const Dialog *d, co return vector(); } } - return get_dialog_active_reactions(d); + return get_dialog_active_reactions(d).reactions_; } bool MessagesManager::need_poll_dialog_message_reactions(const Dialog *d) { @@ -21432,6 +21439,7 @@ td_api::object_ptr MessagesManager::get_chat_object(const Dialog * auto can_delete = can_delete_dialog(d); // TODO hide/show draft message when can_send_message(dialog_id) changes auto draft_message = can_send_message(d->dialog_id).is_ok() ? get_draft_message_object(d->draft_message) : nullptr; + auto available_reactions = get_dialog_active_reactions(d).get_chat_available_reactions_object(); return make_tl_object( d->dialog_id.get(), get_chat_type_object(d->dialog_id), get_dialog_title(d->dialog_id), get_chat_photo_info_object(td_->file_manager_.get(), get_dialog_photo(d->dialog_id)), @@ -21443,7 +21451,7 @@ td_api::object_ptr MessagesManager::get_chat_object(const Dialog * can_report_dialog(d->dialog_id), d->notification_settings.silent_send_message, d->server_unread_count + d->local_unread_count, d->last_read_inbox_message_id.get(), d->last_read_outbox_message_id.get(), d->unread_mention_count, d->unread_reaction_count, - get_chat_notification_settings_object(&d->notification_settings), get_dialog_active_reactions(d), + get_chat_notification_settings_object(&d->notification_settings), std::move(available_reactions), d->message_ttl.get_message_ttl_object(), get_dialog_theme_name(d), get_chat_action_bar_object(d), get_video_chat_object(d), get_chat_join_requests_info_object(d), d->reply_markup_message_id.get(), std::move(draft_message), d->client_data); @@ -31047,9 +31055,10 @@ void MessagesManager::send_update_chat_available_reactions(const Dialog *d) { CHECK(d != nullptr); LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_available_reactions"; + auto available_reactions = get_dialog_active_reactions(d).get_chat_available_reactions_object(); send_closure( G()->td(), &Td::send_update, - td_api::make_object(d->dialog_id.get(), get_dialog_active_reactions(d))); + td_api::make_object(d->dialog_id.get(), std::move(available_reactions))); } void MessagesManager::send_update_secret_chats_with_user_theme(const Dialog *d) const { @@ -33735,15 +33744,17 @@ void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, td_->create_handler(std::move(promise))->send(dialog_id, new_title); } -void MessagesManager::set_dialog_available_reactions(DialogId dialog_id, vector available_reactions, - Promise &&promise) { +void MessagesManager::set_dialog_available_reactions( + DialogId dialog_id, td_api::object_ptr &&available_reactions_ptr, + Promise &&promise) { Dialog *d = get_dialog_force(dialog_id, "set_dialog_available_reactions"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat not found")); } + ChatReactions available_reactions(std::move(available_reactions_ptr), !is_broadcast_channel(dialog_id)); auto active_reactions = get_active_reactions(available_reactions); - if (active_reactions.size() != available_reactions.size()) { + if (active_reactions.reactions_.size() != available_reactions.reactions_.size()) { return promise.set_error(Status::Error(400, "Invalid reactions specified")); } available_reactions = std::move(active_reactions); @@ -33776,7 +33787,7 @@ void MessagesManager::set_dialog_available_reactions(DialogId dialog_id, vector< bool is_changed = d->available_reactions != available_reactions; - set_dialog_available_reactions(d, vector(available_reactions)); + set_dialog_available_reactions(d, ChatReactions(available_reactions)); if (!is_changed) { return promise.set_value(Unit()); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index cf4ed9c35..92a04675c 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -10,6 +10,7 @@ #include "td/telegram/AffectedHistory.h" #include "td/telegram/AvailableReaction.h" #include "td/telegram/ChannelId.h" +#include "td/telegram/ChatReactions.h" #include "td/telegram/DialogAction.h" #include "td/telegram/DialogDate.h" #include "td/telegram/DialogDb.h" @@ -539,7 +540,9 @@ class MessagesManager final : public Actor { void set_active_reactions(vector active_reactions); - void set_dialog_available_reactions(DialogId dialog_id, vector available_reactions, Promise &&promise); + void set_dialog_available_reactions(DialogId dialog_id, + td_api::object_ptr &&available_reactions_ptr, + Promise &&promise); void set_dialog_permissions(DialogId dialog_id, const td_api::object_ptr &permissions, Promise &&promise); @@ -1265,7 +1268,7 @@ class MessagesManager final : public Actor { MessageId last_pinned_message_id; MessageId reply_markup_message_id; DialogNotificationSettings notification_settings; - vector available_reactions; + ChatReactions available_reactions; uint32 available_reactions_generation = 0; MessageTtl message_ttl; unique_ptr draft_message; @@ -2683,15 +2686,15 @@ class MessagesManager final : public Actor { void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); - void set_dialog_available_reactions(Dialog *d, vector &&available_reactions); + void set_dialog_available_reactions(Dialog *d, ChatReactions &&available_reactions); void set_dialog_next_available_reactions_generation(Dialog *d, uint32 generation); void hide_dialog_message_reactions(Dialog *d); - vector get_active_reactions(const vector &available_reactions) const; + ChatReactions get_active_reactions(const ChatReactions &available_reactions) const; - vector get_dialog_active_reactions(const Dialog *d) const; + ChatReactions get_dialog_active_reactions(const Dialog *d) const; vector get_message_active_reactions(const Dialog *d, const Message *m) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 842601ae1..04fe52167 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6092,9 +6092,6 @@ void Td::on_request(uint64 id, const td_api::toggleBotIsAddedToAttachmentMenu &r } void Td::on_request(uint64 id, td_api::setChatAvailableReactions &request) { - for (auto &reaction : request.available_reactions_) { - CLEAN_INPUT_STRING(reaction); - } CREATE_OK_REQUEST_PROMISE(); messages_manager_->set_dialog_available_reactions(DialogId(request.chat_id_), std::move(request.available_reactions_), std::move(promise)); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5251f1d51..ca4790c73 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -724,7 +724,7 @@ class CliClient final : public Actor { return td_api::make_object(to_double(latitude), to_double(longitude), to_double(accuracy)); } - td_api::object_ptr as_reaction_type(Slice type) const { + static td_api::object_ptr as_reaction_type(Slice type) { type = trim(type); if (type.empty()) { return nullptr; @@ -4523,7 +4523,15 @@ class CliClient final : public Actor { ChatId chat_id; string available_reactions; get_args(args, chat_id, available_reactions); - send_request(td_api::make_object(chat_id, autosplit_str(available_reactions))); + td_api::object_ptr chat_available_reactions; + if (available_reactions == "all") { + chat_available_reactions = td_api::make_object(); + } else if (!available_reactions.empty()) { + auto reactions = transform(autosplit_str(available_reactions), as_reaction_type); + chat_available_reactions = td_api::make_object(std::move(reactions)); + } + send_request( + td_api::make_object(chat_id, std::move(chat_available_reactions))); } else if (op == "scd") { ChatId chat_id; string description; From 9fc456f434a89b5cd4a0ccd658716fc0befbe7e6 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 12:03:26 +0300 Subject: [PATCH 041/200] Use SafePromise in CallManager. --- td/telegram/CallManager.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/td/telegram/CallManager.cpp b/td/telegram/CallManager.cpp index 702655775..0e4452102 100644 --- a/td/telegram/CallManager.cpp +++ b/td/telegram/CallManager.cpp @@ -66,8 +66,9 @@ void CallManager::create_call(UserId user_id, tl_object_ptr(std::move(promise), Status::Error(400, "Call not found")); send_closure(actor, &CallActor::create_call, user_id, std::move(input_user), std::move(protocol), is_video, - std::move(promise)); + std::move(safe_promise)); } void CallManager::accept_call(CallId call_id, CallProtocol &&protocol, Promise promise) { @@ -75,7 +76,8 @@ void CallManager::accept_call(CallId call_id, CallProtocol &&protocol, Promise(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::accept_call, std::move(protocol), std::move(safe_promise)); } void CallManager::send_call_signaling_data(CallId call_id, string &&data, Promise promise) { @@ -83,7 +85,8 @@ void CallManager::send_call_signaling_data(CallId call_id, string &&data, Promis if (actor.empty()) { return promise.set_error(Status::Error(400, "Call not found")); } - send_closure(actor, &CallActor::send_call_signaling_data, std::move(data), std::move(promise)); + auto safe_promise = SafePromise(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::send_call_signaling_data, std::move(data), std::move(safe_promise)); } void CallManager::discard_call(CallId call_id, bool is_disconnected, int32 duration, bool is_video, int64 connection_id, @@ -92,7 +95,9 @@ void CallManager::discard_call(CallId call_id, bool is_disconnected, int32 durat if (actor.empty()) { return promise.set_error(Status::Error(400, "Call not found")); } - send_closure(actor, &CallActor::discard_call, is_disconnected, duration, is_video, connection_id, std::move(promise)); + auto safe_promise = SafePromise(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::discard_call, is_disconnected, duration, is_video, connection_id, + std::move(safe_promise)); } void CallManager::rate_call(CallId call_id, int32 rating, string comment, @@ -101,7 +106,8 @@ void CallManager::rate_call(CallId call_id, int32 rating, string comment, if (actor.empty()) { return promise.set_error(Status::Error(400, "Call not found")); } - send_closure(actor, &CallActor::rate_call, rating, std::move(comment), std::move(problems), std::move(promise)); + auto safe_promise = SafePromise(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::rate_call, rating, std::move(comment), std::move(problems), std::move(safe_promise)); } void CallManager::send_call_debug_information(CallId call_id, string data, Promise promise) { @@ -109,7 +115,8 @@ void CallManager::send_call_debug_information(CallId call_id, string data, Promi if (actor.empty()) { return promise.set_error(Status::Error(400, "Call not found")); } - send_closure(actor, &CallActor::send_call_debug_information, std::move(data), std::move(promise)); + auto safe_promise = SafePromise(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::send_call_debug_information, std::move(data), std::move(safe_promise)); } void CallManager::send_call_log(CallId call_id, td_api::object_ptr log_file, Promise promise) { @@ -117,7 +124,8 @@ void CallManager::send_call_log(CallId call_id, td_api::object_ptr(std::move(promise), Status::Error(400, "Call not found")); + send_closure(actor, &CallActor::send_call_log, std::move(log_file), std::move(safe_promise)); } CallId CallManager::create_call_actor() { From 031e2246ecd890fdd0d72f54ae16fda656a2c0cb Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 12:05:38 +0300 Subject: [PATCH 042/200] Add logging for too long file GC. --- td/telegram/files/FileGcWorker.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/td/telegram/files/FileGcWorker.cpp b/td/telegram/files/FileGcWorker.cpp index 0156c4d75..cefdeba4b 100644 --- a/td/telegram/files/FileGcWorker.cpp +++ b/td/telegram/files/FileGcWorker.cpp @@ -30,7 +30,7 @@ int VERBOSITY_NAME(file_gc) = VERBOSITY_NAME(INFO); void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector files, Promise promise) { auto begin_time = Time::now(); - VLOG(file_gc) << "Start files gc with " << parameters; + VLOG(file_gc) << "Start files GC with " << parameters; // quite stupid implementations // needs a lot of memory // may write something more clever, but i will need at least 2 passes over the files @@ -88,7 +88,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vectorfile_manager(), &FileManager::on_file_unlink, FullLocalFileLocation(info.file_type, info.path, info.mtime_nsec)); }; @@ -117,7 +117,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector(info.mtime_nsec) * 1e-9 > now - parameters.immunity_delay_) { - // new files are immune to gc + // new files are immune to GC time_immunity_ignored_cnt++; new_stats.add_copy(info); return true; @@ -177,7 +177,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector 1.0) { + LOG(WARNING) << "Finish file GC: " << tag("time", end_time - begin_time) << tag("total", file_cnt) + << tag("removed", remove_by_atime_cnt + remove_by_count_cnt + remove_by_size_cnt) + << tag("total_size", format::as_size(total_size)) + << tag("total_removed_size", format::as_size(total_removed_size)); + } promise.set_value({std::move(new_stats), std::move(removed_stats)}); } From 077eba4ca2e8d83001e7cadd56a499d5cec9aa88 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 14:32:12 +0300 Subject: [PATCH 043/200] Send auth.logOut even there is no authorization. --- td/telegram/AuthManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 99fb0cf5b..bc790af89 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -390,7 +390,9 @@ void AuthManager::log_out(uint64 query_id) { } void AuthManager::send_log_out_query() { - auto query = G()->net_query_creator().create(telegram_api::auth_logOut()); + // we can lose authorization while logging out, but still may need to re-send the request, + // so we pretend that it doesn't require authorization + auto query = G()->net_query_creator().create_unauth(telegram_api::auth_logOut()); query->set_priority(1); start_net_query(NetQueryType::LogOut, std::move(query)); } From 52b973af351b5fe3d2c79764bf4412c92e2e4f4d Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 16:02:25 +0300 Subject: [PATCH 044/200] Add class EmojiStatus. --- CMakeLists.txt | 1 + td/telegram/ContactsManager.cpp | 59 +++++++++++-------------- td/telegram/ContactsManager.h | 11 ++--- td/telegram/EmojiStatus.h | 77 +++++++++++++++++++++++++++++++++ td/telegram/Td.cpp | 3 +- 5 files changed, 111 insertions(+), 40 deletions(-) create mode 100644 td/telegram/EmojiStatus.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e266ca3c2..d879a73f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -539,6 +539,7 @@ set(TDLIB_SOURCE td/telegram/DownloadManager.h td/telegram/DownloadManagerCallback.h td/telegram/DraftMessage.h + td/telegram/EmojiStatus.h td/telegram/EncryptedFile.h td/telegram/FileReferenceManager.h td/telegram/files/FileBitmask.h diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 8032ce632..5b9a5fb1f 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -680,15 +680,9 @@ class UpdateEmojiStatusQuery final : public Td::ResultHandler { explicit UpdateEmojiStatusQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(int64 custom_emoji_id) { - auto emoji_status = [custom_emoji_id]() -> telegram_api::object_ptr { - if (custom_emoji_id == 0) { - return make_tl_object(); - } - return make_tl_object(custom_emoji_id); - }(); - send_query( - G()->net_query_creator().create(telegram_api::account_updateEmojiStatus(std::move(emoji_status)), {{"me"}})); + void send(EmojiStatus emoji_status) { + send_query(G()->net_query_creator().create( + telegram_api::account_updateEmojiStatus(emoji_status.get_input_emoji_status()), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -3661,7 +3655,7 @@ void ContactsManager::User::store(StorerT &storer) const { bool has_cache_version = cache_version != 0; bool has_is_contact = true; bool has_restriction_reasons = !restriction_reasons.empty(); - bool has_emoji_status = emoji_status != 0; + bool has_emoji_status = !emoji_status.is_empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_received); STORE_FLAG(is_verified); @@ -6605,27 +6599,26 @@ void ContactsManager::set_username(const string &username, Promise &&promi td_->create_handler(std::move(promise))->send(username); } -void ContactsManager::set_emoji_status(int64 custom_emoji_id, Promise &&promise) { +void ContactsManager::set_emoji_status(EmojiStatus emoji_status, Promise &&promise) { if (!td_->option_manager_->get_option_boolean("is_premium")) { return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users")); } auto query_promise = PromiseCreator::lambda( - [actor_id = actor_id(this), custom_emoji_id, promise = std::move(promise)](Result result) mutable { + [actor_id = actor_id(this), emoji_status, promise = std::move(promise)](Result result) mutable { if (result.is_ok()) { - send_closure(actor_id, &ContactsManager::on_set_emoji_status, custom_emoji_id, std::move(promise)); + send_closure(actor_id, &ContactsManager::on_set_emoji_status, emoji_status, std::move(promise)); } else { promise.set_error(result.move_as_error()); } }); - td_->create_handler(std::move(query_promise))->send(custom_emoji_id); + td_->create_handler(std::move(query_promise))->send(emoji_status); } -void ContactsManager::on_set_emoji_status(int64 custom_emoji_id, Promise &&promise) { +void ContactsManager::on_set_emoji_status(EmojiStatus emoji_status, Promise &&promise) { auto user_id = get_my_id(); User *u = get_user(user_id); - if (u != nullptr && u->emoji_status != custom_emoji_id) { - u->emoji_status = custom_emoji_id; - u->is_changed = true; + if (u != nullptr) { + on_update_user_emoji_status(u, user_id, emoji_status); update_user(u, user_id); } promise.set_value(Unit()); @@ -8768,10 +8761,7 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, bool has_bot_info_version = (flags & USER_FLAG_HAS_BOT_INFO_VERSION) != 0; bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0; bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0; - int64 emoji_status = 0; - if (user->emoji_status_ != nullptr && user->emoji_status_->get_id() == telegram_api::emojiStatus::ID) { - emoji_status = static_cast(user->emoji_status_.get())->document_id_; - } + EmojiStatus emoji_status(std::move(user->emoji_status_)); LOG_IF(ERROR, !can_join_groups && !is_bot) << "Receive not bot " << user_id << " which can't join groups from " << source; @@ -8804,11 +8794,12 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; if (u->emoji_status != emoji_status) { - if ((u->is_premium ? u->emoji_status : 0) != (is_premium ? emoji_status : 0)) { + if ((u->is_premium ? u->emoji_status : EmojiStatus()) != (is_premium ? emoji_status : EmojiStatus())) { u->is_changed = true; + } else { + u->need_save_to_database = true; } u->emoji_status = emoji_status; - u->need_save_to_database = true; } if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support || is_bot != u->is_bot || can_join_groups != u->can_join_groups || @@ -11760,7 +11751,7 @@ void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo & } void ContactsManager::on_update_user_emoji_status(UserId user_id, - tl_object_ptr &&emoji_status_ptr) { + tl_object_ptr &&emoji_status) { if (!user_id.is_valid()) { LOG(ERROR) << "Receive invalid " << user_id; return; @@ -11768,22 +11759,22 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, User *u = get_user_force(user_id); if (u != nullptr) { - int64 emoji_status = 0; - if (emoji_status_ptr != nullptr && emoji_status_ptr->get_id() == telegram_api::emojiStatus::ID) { - emoji_status = static_cast(emoji_status_ptr.get())->document_id_; - } - on_update_user_emoji_status(u, user_id, emoji_status); + on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(emoji_status))); update_user(u, user_id); } else { LOG(INFO) << "Ignore update user emoji status about unknown " << user_id; } } -void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, int64 emoji_status) { +void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; LOG(DEBUG) << "Emoji status has changed for " << user_id; - u->is_changed = true; + if (u->is_premium) { + u->is_changed = true; + } else { + u->need_save_to_database = true; + } } } @@ -16786,10 +16777,10 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } - int64 emoji_status = u->is_premium ? u->emoji_status : 0; + int64 premium_badge = u->is_premium ? u->emoji_status.get_premium_badge_object() : 0; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), - get_profile_photo_object(td_->file_manager_.get(), u->photo), emoji_status, u->is_contact, u->is_mutual_contact, + get_profile_photo_object(td_->file_manager_.get(), u->photo), premium_badge, u->is_contact, u->is_mutual_contact, u->is_verified, u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, u->is_received, std::move(type), u->language_code, u->attach_menu_enabled); } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index cc1d9cd81..243193f2e 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -19,6 +19,7 @@ #include "td/telegram/DialogLocation.h" #include "td/telegram/DialogParticipant.h" #include "td/telegram/DialogParticipantFilter.h" +#include "td/telegram/EmojiStatus.h" #include "td/telegram/files/FileId.h" #include "td/telegram/files/FileSourceId.h" #include "td/telegram/FolderId.h" @@ -178,7 +179,7 @@ class ContactsManager final : public Actor { void on_update_user_name(UserId user_id, string &&first_name, string &&last_name, string &&username); void on_update_user_phone_number(UserId user_id, string &&phone_number); void on_update_user_photo(UserId user_id, tl_object_ptr &&photo_ptr); - void on_update_user_emoji_status(UserId user_id, tl_object_ptr &&emoji_status_ptr); + void on_update_user_emoji_status(UserId user_id, tl_object_ptr &&emoji_status); void on_update_user_online(UserId user_id, tl_object_ptr &&status); void on_update_user_local_was_online(UserId user_id, int32 local_was_online); void on_update_user_is_blocked(UserId user_id, bool is_blocked); @@ -344,7 +345,7 @@ class ContactsManager final : public Actor { void set_username(const string &username, Promise &&promise); - void set_emoji_status(int64 suctom_emoji_id, Promise &&promise); + void set_emoji_status(EmojiStatus emoji_status, Promise &&promise); void set_chat_description(ChatId chat_id, const string &description, Promise &&promise); @@ -644,7 +645,7 @@ class ContactsManager final : public Actor { string username; string phone_number; int64 access_hash = -1; - int64 emoji_status = 0; + EmojiStatus emoji_status; ProfilePhoto photo; @@ -1251,13 +1252,13 @@ class ContactsManager final : public Actor { static bool is_valid_username(const string &username); - void on_set_emoji_status(int64 custom_emoji_id, Promise &&promise); + void on_set_emoji_status(EmojiStatus emoji_status, Promise &&promise); void on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name, string &&username); void on_update_user_phone_number(User *u, UserId user_id, string &&phone_number); void on_update_user_photo(User *u, UserId user_id, tl_object_ptr &&photo, const char *source); - void on_update_user_emoji_status(User *u, UserId user_id, int64 emoji_status); + void on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status); void on_update_user_is_contact(User *u, UserId user_id, bool is_contact, bool is_mutual_contact); void on_update_user_online(User *u, UserId user_id, tl_object_ptr &&status); void on_update_user_local_was_online(User *u, UserId user_id, int32 local_was_online); diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h new file mode 100644 index 000000000..e29588ca0 --- /dev/null +++ b/td/telegram/EmojiStatus.h @@ -0,0 +1,77 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +class EmojiStatus { + int64 custom_emoji_id_ = 0; + + friend bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs); + + friend StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &contact); + + public: + EmojiStatus() = default; + + explicit EmojiStatus(int64 custom_emoji_id) : custom_emoji_id_(custom_emoji_id) { + } + + explicit EmojiStatus(tl_object_ptr &&emoji_status) { + if (emoji_status != nullptr && emoji_status->get_id() == telegram_api::emojiStatus::ID) { + custom_emoji_id_ = static_cast(emoji_status.get())->document_id_; + } + } + + tl_object_ptr get_input_emoji_status() const { + if (is_empty()) { + return make_tl_object(); + } + return make_tl_object(custom_emoji_id_); + } + + int64 get_premium_badge_object() const { + return custom_emoji_id_; + } + + bool is_empty() const { + return custom_emoji_id_ == 0; + } + + template + void store(StorerT &storer) const { + td::store(custom_emoji_id_, storer); + } + + template + void parse(ParserT &parser) { + td::parse(custom_emoji_id_, parser); + } +}; + +inline bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs) { + return lhs.custom_emoji_id_ == rhs.custom_emoji_id_; +} + +inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { + return !(lhs == rhs); +} + +inline StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { + if (emoji_status.is_empty()) { + return string_builder << "DefaultProfileBadge"; + } + return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; +} + +} // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 04fe52167..ea4162e57 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -41,6 +41,7 @@ #include "td/telegram/DocumentsManager.h" #include "td/telegram/DownloadManager.h" #include "td/telegram/DownloadManagerCallback.h" +#include "td/telegram/EmojiStatus.h" #include "td/telegram/FileReferenceManager.h" #include "td/telegram/files/FileGcParameters.h" #include "td/telegram/files/FileId.h" @@ -6729,7 +6730,7 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { void Td::on_request(uint64 id, const td_api::setPremiumBadge &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_emoji_status(request.custom_emoji_id_, std::move(promise)); + contacts_manager_->set_emoji_status(EmojiStatus(request.custom_emoji_id_), std::move(promise)); } void Td::on_request(uint64 id, td_api::setCommands &request) { From c73fa3ed72955457f67c480846e124bdc11fb5bf Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 16:48:26 +0300 Subject: [PATCH 045/200] Add td_api::premiumStatus. --- td/generate/scheme/td_api.tl | 11 +++++++---- td/telegram/ContactsManager.cpp | 13 +++++++------ td/telegram/EmojiStatus.h | 11 ++++++++--- td/telegram/Td.cpp | 4 ++-- td/telegram/Td.h | 2 +- td/telegram/cli.cpp | 6 ++++-- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 88c76f6b8..f6dd5aa46 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -475,6 +475,9 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa //@payment_link An internal link to be opened for buying Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available premiumPaymentOption currency:string amount:int53 discount_percentage:int32 month_count:int32 store_product_id:string payment_link:InternalLinkType = PremiumPaymentOption; +//@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format +premiumStatus custom_emoji_id:int64 = PremiumStatus; + //@description Represents a user //@id User identifier @@ -484,7 +487,7 @@ premiumPaymentOption currency:string amount:int53 discount_percentage:int32 mont //@phone_number Phone number of the user //@status Current online status of the user //@profile_photo Profile photo of the user; may be null -//@premium_badge_custom_emoji_id Identifier of the custom emoji to be shown instead of the Telegram Premium badge; 0 if none. For Telegram Premium users only +//@premium_status Premium status to be shown instead of the default Telegram Premium badge; may be null. For Telegram Premium users only //@is_contact The user is a contact of the current user //@is_mutual_contact The user is a contact of the current user and the current user is a contact of the user //@is_verified True, if the user is verified @@ -497,7 +500,7 @@ premiumPaymentOption currency:string amount:int53 discount_percentage:int32 mont //@type Type of the user //@language_code IETF language tag of the user's language; only available to bots //@added_to_attachment_menu True, if the user added the current bot to attachment menu; only available to bots -user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto premium_badge_custom_emoji_id:int64 is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; +user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto premium_status:premiumStatus is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; //@description Contains information about a bot @@ -6075,8 +6078,8 @@ setBio bio:string = Ok; //@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username setUsername username:string = Ok; -//@description Changes the premium badge of the current user; for Telegram Premium users only @custom_emoji_id Identifier of the custom emoji to use as premium badge; pass 0 to switch to default badge. The custom emoji must have stickerFormatTgs -setPremiumBadge custom_emoji_id:int64 = Ok; +//@description Changes the premium status of the current user; for Telegram Premium users only @premium_status New premium status; pass null to switch to the default badge +setPremiumStatus premium_status:premiumStatus = Ok; //@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user setLocation location:location = Ok; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 5b9a5fb1f..3b7db0941 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -16745,8 +16745,8 @@ td_api::object_ptr ContactsManager::get_user_status_object(U td_api::object_ptr ContactsManager::get_update_unknown_user_object(UserId user_id) { return td_api::make_object(td_api::make_object( - user_id.get(), "", "", "", "", td_api::make_object(), nullptr, 0, false, false, false, - false, false, "", false, false, false, td_api::make_object(), "", false)); + user_id.get(), "", "", "", "", td_api::make_object(), nullptr, nullptr, false, false, + false, false, false, "", false, false, false, td_api::make_object(), "", false)); } int64 ContactsManager::get_user_id_object(UserId user_id, const char *source) const { @@ -16777,12 +16777,13 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } - int64 premium_badge = u->is_premium ? u->emoji_status.get_premium_badge_object() : 0; + auto premium_status = u->is_premium ? u->emoji_status.get_premium_status_object() : nullptr; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), - get_profile_photo_object(td_->file_manager_.get(), u->photo), premium_badge, u->is_contact, u->is_mutual_contact, - u->is_verified, u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), - u->is_scam, u->is_fake, u->is_received, std::move(type), u->language_code, u->attach_menu_enabled); + get_profile_photo_object(td_->file_manager_.get(), u->photo), std::move(premium_status), u->is_contact, + u->is_mutual_contact, u->is_verified, u->is_premium, u->is_support, + get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, u->is_received, + std::move(type), u->language_code, u->attach_menu_enabled); } vector ContactsManager::get_user_ids_object(const vector &user_ids, const char *source) const { diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index e29588ca0..f91257273 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" #include "td/utils/common.h" @@ -24,7 +25,8 @@ class EmojiStatus { public: EmojiStatus() = default; - explicit EmojiStatus(int64 custom_emoji_id) : custom_emoji_id_(custom_emoji_id) { + explicit EmojiStatus(const td_api::object_ptr &premium_status) + : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { } explicit EmojiStatus(tl_object_ptr &&emoji_status) { @@ -40,8 +42,11 @@ class EmojiStatus { return make_tl_object(custom_emoji_id_); } - int64 get_premium_badge_object() const { - return custom_emoji_id_; + td_api::object_ptr get_premium_status_object() const { + if (is_empty()) { + return nullptr; + } + return td_api::make_object(custom_emoji_id_); } bool is_empty() const { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index ea4162e57..14d18a7eb 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6727,10 +6727,10 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { contacts_manager_->set_username(request.username_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::setPremiumBadge &request) { +void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_emoji_status(EmojiStatus(request.custom_emoji_id_), std::move(promise)); + contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_), std::move(promise)); } void Td::on_request(uint64 id, td_api::setCommands &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index bdda812a9..8efb02d9f 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1012,7 +1012,7 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setUsername &request); - void on_request(uint64 id, const td_api::setPremiumBadge &request); + void on_request(uint64 id, const td_api::setPremiumStatus &request); void on_request(uint64 id, td_api::setCommands &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ca4790c73..8970c8ca0 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4473,8 +4473,10 @@ class CliClient final : public Actor { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); } else if (op == "sun") { send_request(td_api::make_object(args)); - } else if (op == "spb") { - send_request(td_api::make_object(to_integer(args))); + } else if (op == "sps") { + auto premium_status = + args.empty() ? nullptr : td_api::make_object(to_integer(args)); + send_request(td_api::make_object(std::move(premium_status))); } else if (op == "ccun") { ChatId chat_id; string username; From cefcf9e0184003f6cccc778e6cda170a87a80e48 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 17:23:46 +0300 Subject: [PATCH 046/200] Add EmojiStatus.cpp. --- CMakeLists.txt | 1 + td/telegram/EmojiStatus.cpp | 42 +++++++++++++++++++++++++++++++++++++ td/telegram/EmojiStatus.h | 31 +++++---------------------- 3 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 td/telegram/EmojiStatus.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d879a73f1..d027bfed9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ set(TDLIB_SOURCE td/telegram/DownloadManager.cpp td/telegram/DownloadManagerCallback.cpp td/telegram/DraftMessage.cpp + td/telegram/EmojiStatus.cpp td/telegram/FileReferenceManager.cpp td/telegram/files/FileBitmask.cpp td/telegram/files/FileDb.cpp diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp new file mode 100644 index 000000000..0cb8f2d64 --- /dev/null +++ b/td/telegram/EmojiStatus.cpp @@ -0,0 +1,42 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/EmojiStatus.h" + +namespace td { + +EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) + : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { +} + +EmojiStatus::EmojiStatus(tl_object_ptr &&emoji_status) { + if (emoji_status != nullptr && emoji_status->get_id() == telegram_api::emojiStatus::ID) { + custom_emoji_id_ = static_cast(emoji_status.get())->document_id_; + } +} + +tl_object_ptr EmojiStatus::get_input_emoji_status() const { + if (is_empty()) { + return make_tl_object(); + } + return make_tl_object(custom_emoji_id_); +} + +td_api::object_ptr EmojiStatus::get_premium_status_object() const { + if (is_empty()) { + return nullptr; + } + return td_api::make_object(custom_emoji_id_); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { + if (emoji_status.is_empty()) { + return string_builder << "DefaultProfileBadge"; + } + return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; +} + +} // namespace td diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index f91257273..7f8134c55 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -25,29 +25,13 @@ class EmojiStatus { public: EmojiStatus() = default; - explicit EmojiStatus(const td_api::object_ptr &premium_status) - : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { - } + explicit EmojiStatus(const td_api::object_ptr &premium_status); - explicit EmojiStatus(tl_object_ptr &&emoji_status) { - if (emoji_status != nullptr && emoji_status->get_id() == telegram_api::emojiStatus::ID) { - custom_emoji_id_ = static_cast(emoji_status.get())->document_id_; - } - } + explicit EmojiStatus(tl_object_ptr &&emoji_status); - tl_object_ptr get_input_emoji_status() const { - if (is_empty()) { - return make_tl_object(); - } - return make_tl_object(custom_emoji_id_); - } + tl_object_ptr get_input_emoji_status() const; - td_api::object_ptr get_premium_status_object() const { - if (is_empty()) { - return nullptr; - } - return td_api::make_object(custom_emoji_id_); - } + td_api::object_ptr get_premium_status_object() const; bool is_empty() const { return custom_emoji_id_ == 0; @@ -72,11 +56,6 @@ inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { return !(lhs == rhs); } -inline StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { - if (emoji_status.is_empty()) { - return string_builder << "DefaultProfileBadge"; - } - return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; -} +StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status); } // namespace td From 31ec06a134e58e59141f379a2876bfbc302ed5d8 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 18:03:57 +0300 Subject: [PATCH 047/200] Add td_api::getDefaultPremiumStatuses. --- td/generate/scheme/td_api.tl | 7 +++++ td/telegram/EmojiStatus.cpp | 51 ++++++++++++++++++++++++++++++++++ td/telegram/EmojiStatus.h | 5 ++++ td/telegram/Td.cpp | 6 ++++ td/telegram/Td.h | 2 ++ td/telegram/UpdatesManager.cpp | 2 ++ td/telegram/cli.cpp | 2 ++ 7 files changed, 75 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index f6dd5aa46..2919c5ddf 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -478,6 +478,9 @@ premiumPaymentOption currency:string amount:int53 discount_percentage:int32 mont //@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format premiumStatus custom_emoji_id:int64 = PremiumStatus; +//@description Contains a list of premium statuses @premium_statuses The list of premium statuses +premiumStatuses premium_statuses:vector = PremiumStatuses; + //@description Represents a user //@id User identifier @@ -5572,6 +5575,10 @@ getAttachmentMenuBot bot_user_id:int53 = AttachmentMenuBot; toggleBotIsAddedToAttachmentMenu bot_user_id:int53 is_added:Bool = Ok; +//@description Returns default premium statuses +getDefaultPremiumStatuses = PremiumStatuses; + + //@description Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates //@file_id Identifier of the file to download //@priority Priority of the download (1-32). The higher the priority, the earlier the file will be downloaded. If the priorities of two files are equal, then the last one for which downloadFile/addFileToDownloads was called will be downloaded first diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 0cb8f2d64..fba750879 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -6,8 +6,55 @@ // #include "td/telegram/EmojiStatus.h" +#include "td/telegram/Global.h" +#include "td/telegram/Td.h" + +#include "td/utils/buffer.h" +#include "td/utils/Status.h" + namespace td { +class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetDefaultEmojiStatusesQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::account_getDefaultEmojiStatuses(hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto emoji_statuses_ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetDefaultEmojiStatusesQuery: " << to_string(emoji_statuses_ptr); + + auto result = td_api::make_object(); + if (emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatuses::ID) { + auto emoji_statuses = move_tl_object_as(emoji_statuses_ptr); + for (auto &status : emoji_statuses->statuses_) { + EmojiStatus emoji_status(std::move(status)); + if (emoji_status.is_empty()) { + LOG(ERROR) << "Receive empty default emoji status"; + continue; + } + result->premium_statuses_.push_back(emoji_status.get_premium_status_object()); + } + } + promise_.set_value(std::move(result)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { } @@ -39,4 +86,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoj return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; } +void get_default_emoji_statuses(Td *td, Promise> &&promise) { + td->create_handler(std::move(promise))->send(0); +} + } // namespace td diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 7f8134c55..c7d76ff46 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -10,11 +10,14 @@ #include "td/telegram/telegram_api.h" #include "td/utils/common.h" +#include "td/utils/Promise.h" #include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" namespace td { +class Td; + class EmojiStatus { int64 custom_emoji_id_ = 0; @@ -58,4 +61,6 @@ inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status); +void get_default_emoji_statuses(Td *td, Promise> &&promise); + } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 14d18a7eb..7cc800255 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6733,6 +6733,12 @@ void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + get_default_emoji_statuses(this, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 8efb02d9f..f508aa9e1 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1014,6 +1014,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::setPremiumStatus &request); + void on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request); + void on_request(uint64 id, td_api::setCommands &request); void on_request(uint64 id, td_api::deleteCommands &request); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 370426168..57d397606 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -20,6 +20,7 @@ #include "td/telegram/DialogInviteLink.h" #include "td/telegram/DialogParticipant.h" #include "td/telegram/DownloadManager.h" +#include "td/telegram/EmojiStatus.h" #include "td/telegram/FolderId.h" #include "td/telegram/Global.h" #include "td/telegram/GroupCallManager.h" @@ -1700,6 +1701,7 @@ void UpdatesManager::try_reload_data() { td_->animations_manager_->get_saved_animations(Auto()); td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::HasUsername, Auto()); td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::IsLocationBased, Auto()); + get_default_emoji_statuses(td_, Auto()); td_->notification_settings_manager_->reload_saved_ringtones(Auto()); td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Private, Auto()); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8970c8ca0..c1c281706 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4477,6 +4477,8 @@ class CliClient final : public Actor { auto premium_status = args.empty() ? nullptr : td_api::make_object(to_integer(args)); send_request(td_api::make_object(std::move(premium_status))); + } else if (op == "gdps") { + send_request(td_api::make_object()); } else if (op == "ccun") { ChatId chat_id; string username; From 8c9911c7c6f3c5303efd6e47f671037d2e1ccc0e Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 30 Aug 2022 18:15:12 +0300 Subject: [PATCH 048/200] Fix check for empty chosen reactions. --- td/telegram/AvailableReaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index 1b0304dae..91c4bcc2a 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -24,7 +24,7 @@ AvailableReactionType get_reaction_type(const vector &availab ChatReactions get_active_reactions(const ChatReactions &available_reactions, const vector &active_reactions) { - if (available_reactions.empty()) { + if (available_reactions.reactions_.empty()) { // fast path return available_reactions; } From c65af3ac6ea00f88064350204790082bfe4028d8 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 11:11:37 +0300 Subject: [PATCH 049/200] Improve field name. --- td/telegram/LanguagePackManager.cpp | 1 - td/telegram/MessagesManager.cpp | 6 +++--- td/telegram/MessagesManager.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/td/telegram/LanguagePackManager.cpp b/td/telegram/LanguagePackManager.cpp index 19122457d..cef868df9 100644 --- a/td/telegram/LanguagePackManager.cpp +++ b/td/telegram/LanguagePackManager.cpp @@ -7,7 +7,6 @@ #include "td/telegram/LanguagePackManager.h" #include "td/telegram/Global.h" -#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/misc.h" #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/Td.h" diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7966a0850..d3cb5b91b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -17793,7 +17793,7 @@ std::pair> MessagesManager::get_common_dialogs(UserId us if (it != found_common_dialogs_.end() && !it->second.dialog_ids.empty()) { int32 total_count = it->second.total_count; vector &common_dialog_ids = it->second.dialog_ids; - bool use_cache = (!it->second.is_outdated && it->second.received_date >= Time::now() - 3600) || force || + bool use_cache = (!it->second.is_outdated && it->second.receive_time >= Time::now() - 3600) || force || offset_chat_id != 0 || common_dialog_ids.size() >= static_cast(MAX_GET_DIALOGS); // use cache if it is up-to-date, or we required to use it or we can't update it if (use_cache) { @@ -17841,8 +17841,8 @@ void MessagesManager::on_get_common_dialogs(UserId user_id, int64 offset_chat_id // drop outdated cache if possible common_dialogs = CommonDialogs(); } - if (common_dialogs.received_date == 0) { - common_dialogs.received_date = Time::now(); + if (common_dialogs.receive_time == 0) { + common_dialogs.receive_time = Time::now(); } common_dialogs.is_outdated = false; auto &result = common_dialogs.dialog_ids; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 92a04675c..f0f74aaa0 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -3512,7 +3512,7 @@ class MessagesManager final : public Actor { struct CommonDialogs { vector dialog_ids; - double received_date = 0; + double receive_time = 0; int32 total_count = 0; bool is_outdated = false; }; From 947a92e94c550322a83a84220c8f8efe465f1350 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 11:59:37 +0300 Subject: [PATCH 050/200] Save default premium statuses to binlog. --- td/telegram/EmojiStatus.cpp | 92 ++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 12 deletions(-) diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index fba750879..9e50e9f30 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -7,13 +7,75 @@ #include "td/telegram/EmojiStatus.h" #include "td/telegram/Global.h" +#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/Td.h" +#include "td/telegram/TdDb.h" +#include "td/utils/algorithm.h" #include "td/utils/buffer.h" #include "td/utils/Status.h" namespace td { +struct EmojiStatuses { + int64 hash_ = 0; + vector emoji_statuses_; + + td_api::object_ptr get_premium_statuses_object() const { + auto premium_statuses = transform(emoji_statuses_, [](const EmojiStatus &emoji_status) { + CHECK(!emoji_status.is_empty()); + return emoji_status.get_premium_status_object(); + }); + + return td_api::make_object(std::move(premium_statuses)); + } + + EmojiStatuses() = default; + + explicit EmojiStatuses(tl_object_ptr &&emoji_statuses) { + CHECK(emoji_statuses != nullptr); + hash_ = emoji_statuses->hash_; + for (auto &status : emoji_statuses->statuses_) { + EmojiStatus emoji_status(std::move(status)); + if (emoji_status.is_empty()) { + LOG(ERROR) << "Receive empty emoji status"; + continue; + } + emoji_statuses_.push_back(emoji_status); + } + } + + template + void store(StorerT &storer) const { + td::store(hash_, storer); + td::store(emoji_statuses_, storer); + } + + template + void parse(ParserT &parser) { + td::parse(hash_, parser); + td::parse(emoji_statuses_, parser); + } +}; + +static const string &get_default_emoji_statuses_database_key() { + static string key = "def_emoji_statuses"; + return key; +} + +static EmojiStatuses load_emoji_statuses(const string &key) { + EmojiStatuses result; + auto log_event_string = G()->td_db()->get_binlog_pmc()->get(key); + if (!log_event_string.empty()) { + log_event_parse(result, log_event_string).ensure(); + } + return result; +} + +static void save_emoji_statuses(const string &key, const EmojiStatuses &emoji_statuses) { + G()->td_db()->get_binlog_pmc()->set(key, log_event_store(emoji_statuses).as_slice().str()); +} + class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { Promise> promise_; @@ -35,19 +97,20 @@ class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { auto emoji_statuses_ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetDefaultEmojiStatusesQuery: " << to_string(emoji_statuses_ptr); - auto result = td_api::make_object(); - if (emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatuses::ID) { - auto emoji_statuses = move_tl_object_as(emoji_statuses_ptr); - for (auto &status : emoji_statuses->statuses_) { - EmojiStatus emoji_status(std::move(status)); - if (emoji_status.is_empty()) { - LOG(ERROR) << "Receive empty default emoji status"; - continue; - } - result->premium_statuses_.push_back(emoji_status.get_premium_status_object()); + if (emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatusesNotModified::ID) { + if (promise_) { + promise_.set_error(Status::Error(500, "Receive wrong server response")); } + return; + } + + CHECK(emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatuses::ID); + EmojiStatuses emoji_statuses(move_tl_object_as(emoji_statuses_ptr)); + save_emoji_statuses(get_default_emoji_statuses_database_key(), emoji_statuses); + + if (promise_) { + promise_.set_value(emoji_statuses.get_premium_statuses_object()); } - promise_.set_value(std::move(result)); } void on_error(Status status) final { @@ -87,7 +150,12 @@ StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoj } void get_default_emoji_statuses(Td *td, Promise> &&promise) { - td->create_handler(std::move(promise))->send(0); + auto statuses = load_emoji_statuses(get_default_emoji_statuses_database_key()); + if (statuses.hash_ != 0 && promise) { + promise.set_value(statuses.get_premium_statuses_object()); + promise = Promise>(); + } + td->create_handler(std::move(promise))->send(statuses.hash_); } } // namespace td From c627f5987d6ecf98862ccd7ed8b2f134a8594628 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 15:47:51 +0300 Subject: [PATCH 051/200] Add getRecentPremiumStatuses. --- td/generate/scheme/td_api.tl | 3 ++ td/telegram/EmojiStatus.cpp | 60 ++++++++++++++++++++++++++++++++++-- td/telegram/EmojiStatus.h | 2 ++ td/telegram/Td.cpp | 6 ++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2919c5ddf..348c1a5cb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5578,6 +5578,9 @@ toggleBotIsAddedToAttachmentMenu bot_user_id:int53 is_added:Bool = Ok; //@description Returns default premium statuses getDefaultPremiumStatuses = PremiumStatuses; +//@description Returns recent premium statuses +getRecentPremiumStatuses = PremiumStatuses; + //@description Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates //@file_id Identifier of the file to download diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 9e50e9f30..561eb552b 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -18,7 +18,7 @@ namespace td { struct EmojiStatuses { - int64 hash_ = 0; + int64 hash_ = -1; vector emoji_statuses_; td_api::object_ptr get_premium_statuses_object() const { @@ -63,6 +63,11 @@ static const string &get_default_emoji_statuses_database_key() { return key; } +static const string &get_recent_emoji_statuses_database_key() { + static string key = "rec_emoji_statuses"; + return key; +} + static EmojiStatuses load_emoji_statuses(const string &key) { EmojiStatuses result; auto log_event_string = G()->td_db()->get_binlog_pmc()->get(key); @@ -118,6 +123,48 @@ class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { } }; +class GetRecentEmojiStatusesQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetRecentEmojiStatusesQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::account_getRecentEmojiStatuses(hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto emoji_statuses_ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetRecentEmojiStatusesQuery: " << to_string(emoji_statuses_ptr); + + if (emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatusesNotModified::ID) { + if (promise_) { + promise_.set_error(Status::Error(500, "Receive wrong server response")); + } + return; + } + + CHECK(emoji_statuses_ptr->get_id() == telegram_api::account_emojiStatuses::ID); + EmojiStatuses emoji_statuses(move_tl_object_as(emoji_statuses_ptr)); + save_emoji_statuses(get_recent_emoji_statuses_database_key(), emoji_statuses); + + if (promise_) { + promise_.set_value(emoji_statuses.get_premium_statuses_object()); + } + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { } @@ -151,11 +198,20 @@ StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoj void get_default_emoji_statuses(Td *td, Promise> &&promise) { auto statuses = load_emoji_statuses(get_default_emoji_statuses_database_key()); - if (statuses.hash_ != 0 && promise) { + if (statuses.hash_ != -1 && promise) { promise.set_value(statuses.get_premium_statuses_object()); promise = Promise>(); } td->create_handler(std::move(promise))->send(statuses.hash_); } +void get_recent_emoji_statuses(Td *td, Promise> &&promise) { + auto statuses = load_emoji_statuses(get_recent_emoji_statuses_database_key()); + if (statuses.hash_ != -1 && promise) { + promise.set_value(statuses.get_premium_statuses_object()); + promise = Promise>(); + } + td->create_handler(std::move(promise))->send(statuses.hash_); +} + } // namespace td diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index c7d76ff46..9193a1970 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -63,4 +63,6 @@ StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoj void get_default_emoji_statuses(Td *td, Promise> &&promise); +void get_recent_emoji_statuses(Td *td, Promise> &&promise); + } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7cc800255..253a7e4b0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6739,6 +6739,12 @@ void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) get_default_emoji_statuses(this, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getRecentPremiumStatuses &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + get_recent_emoji_statuses(this, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index f508aa9e1..b4f87b7bd 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1016,6 +1016,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request); + void on_request(uint64 id, const td_api::getRecentPremiumStatuses &request); + void on_request(uint64 id, td_api::setCommands &request); void on_request(uint64 id, td_api::deleteCommands &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index c1c281706..6536748e6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4479,6 +4479,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(std::move(premium_status))); } else if (op == "gdps") { send_request(td_api::make_object()); + } else if (op == "grps") { + send_request(td_api::make_object()); } else if (op == "ccun") { ChatId chat_id; string username; From 93d870bfc6765d1a09ba67e7948c08b489862ff5 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 16:41:13 +0300 Subject: [PATCH 052/200] Add td_api::clearRecentPremiumStatuses. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/EmojiStatus.cpp | 39 +++++++++++++++++++++++++++++++++--- td/telegram/EmojiStatus.h | 2 ++ td/telegram/Td.cpp | 6 ++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 348c1a5cb..8332d1517 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5581,6 +5581,9 @@ getDefaultPremiumStatuses = PremiumStatuses; //@description Returns recent premium statuses getRecentPremiumStatuses = PremiumStatuses; +//@description Clears recent premium statuses +clearRecentPremiumStatuses = Ok; + //@description Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates //@file_id Identifier of the file to download diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 561eb552b..3973a7312 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -18,7 +18,7 @@ namespace td { struct EmojiStatuses { - int64 hash_ = -1; + int64 hash_ = 0; vector emoji_statuses_; td_api::object_ptr get_premium_statuses_object() const { @@ -73,6 +73,8 @@ static EmojiStatuses load_emoji_statuses(const string &key) { auto log_event_string = G()->td_db()->get_binlog_pmc()->get(key); if (!log_event_string.empty()) { log_event_parse(result, log_event_string).ensure(); + } else { + result.hash_ = -1; } return result; } @@ -90,7 +92,7 @@ class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { } void send(int64 hash) { - send_query(G()->net_query_creator().create(telegram_api::account_getDefaultEmojiStatuses(hash))); + send_query(G()->net_query_creator().create(telegram_api::account_getDefaultEmojiStatuses(hash), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -132,7 +134,7 @@ class GetRecentEmojiStatusesQuery final : public Td::ResultHandler { } void send(int64 hash) { - send_query(G()->net_query_creator().create(telegram_api::account_getRecentEmojiStatuses(hash))); + send_query(G()->net_query_creator().create(telegram_api::account_getRecentEmojiStatuses(hash), {{"me"}})); } void on_result(BufferSlice packet) final { @@ -165,6 +167,32 @@ class GetRecentEmojiStatusesQuery final : public Td::ResultHandler { } }; +class ClearRecentEmojiStatusesQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit ClearRecentEmojiStatusesQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create(telegram_api::account_clearRecentEmojiStatuses(), {{"me"}})); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + save_emoji_statuses(get_recent_emoji_statuses_database_key(), EmojiStatuses()); + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { } @@ -214,4 +242,9 @@ void get_recent_emoji_statuses(Td *td, Promisecreate_handler(std::move(promise))->send(statuses.hash_); } +void clear_recent_emoji_statuses(Td *td, Promise &&promise) { + save_emoji_statuses(get_recent_emoji_statuses_database_key(), EmojiStatuses()); + td->create_handler(std::move(promise))->send(); +} + } // namespace td diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 9193a1970..c0e728599 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -65,4 +65,6 @@ void get_default_emoji_statuses(Td *td, Promise> &&promise); +void clear_recent_emoji_statuses(Td *td, Promise &&promise); + } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 253a7e4b0..f5d45f873 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6745,6 +6745,12 @@ void Td::on_request(uint64 id, const td_api::getRecentPremiumStatuses &request) get_recent_emoji_statuses(this, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::clearRecentPremiumStatuses &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + clear_recent_emoji_statuses(this, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setCommands &request) { CHECK_IS_BOT(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b4f87b7bd..d629f5557 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1018,6 +1018,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getRecentPremiumStatuses &request); + void on_request(uint64 id, const td_api::clearRecentPremiumStatuses &request); + void on_request(uint64 id, td_api::setCommands &request); void on_request(uint64 id, td_api::deleteCommands &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 6536748e6..e7ec0c4e1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4481,6 +4481,8 @@ class CliClient final : public Actor { send_request(td_api::make_object()); } else if (op == "grps") { send_request(td_api::make_object()); + } else if (op == "crps") { + send_request(td_api::make_object()); } else if (op == "ccun") { ChatId chat_id; string username; From 6f940b5e9b451d431897092f336589259362958b Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 16:56:40 +0300 Subject: [PATCH 053/200] Support updateRecentEmojiStatuses. --- td/telegram/UpdatesManager.cpp | 9 +++++---- td/telegram/UpdatesManager.h | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 57d397606..534c7f79f 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3179,6 +3179,11 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + get_recent_emoji_statuses(td_, Auto()); + promise.set_value(Unit()); +} + void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { td_->messages_manager_->on_update_dialog_is_blocked(DialogId(update->peer_id_), update->blocked_); promise.set_value(Unit()); @@ -3585,10 +3590,6 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - promise.set_value(Unit()); -} - void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { promise.set_value(Unit()); } diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 2e50c771a..8ed898a9a 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -421,6 +421,7 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); + void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); @@ -537,8 +538,6 @@ class UpdatesManager final : public Actor { // unsupported updates - void on_update(tl_object_ptr update, Promise &&promise); - void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); From 1890d4568039c920bb02b6bb2983a9bd7b7b544d Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 17:46:03 +0300 Subject: [PATCH 054/200] Locally update recent premium statuses when changing the status. --- td/telegram/ContactsManager.cpp | 1 + td/telegram/EmojiStatus.cpp | 16 ++++++++++++++++ td/telegram/EmojiStatus.h | 2 ++ td/telegram/misc.h | 2 +- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 3b7db0941..bdc7ebdcb 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6603,6 +6603,7 @@ void ContactsManager::set_emoji_status(EmojiStatus emoji_status, Promise & if (!td_->option_manager_->get_option_boolean("is_premium")) { return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users")); } + add_recent_emoji_status(emoji_status); auto query_promise = PromiseCreator::lambda( [actor_id = actor_id(this), emoji_status, promise = std::move(promise)](Result result) mutable { if (result.is_ok()) { diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 3973a7312..b97e3b4a8 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -242,6 +242,22 @@ void get_recent_emoji_statuses(Td *td, Promisecreate_handler(std::move(promise))->send(statuses.hash_); } +void add_recent_emoji_status(EmojiStatus emoji_status) { + if (emoji_status.is_empty()) { + return; + } + + auto statuses = load_emoji_statuses(get_recent_emoji_statuses_database_key()); + if (!statuses.emoji_statuses_.empty() && statuses.emoji_statuses_[0] == emoji_status) { + return; + } + + statuses.hash_ = 0; + td::remove(statuses.emoji_statuses_, emoji_status); + statuses.emoji_statuses_.insert(statuses.emoji_statuses_.begin(), emoji_status); + save_emoji_statuses(get_recent_emoji_statuses_database_key(), statuses); +} + void clear_recent_emoji_statuses(Td *td, Promise &&promise) { save_emoji_statuses(get_recent_emoji_statuses_database_key(), EmojiStatuses()); td->create_handler(std::move(promise))->send(); diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index c0e728599..34d52106b 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -65,6 +65,8 @@ void get_default_emoji_statuses(Td *td, Promise> &&promise); +void add_recent_emoji_status(EmojiStatus emoji_status); + void clear_recent_emoji_statuses(Td *td, Promise &&promise); } // namespace td diff --git a/td/telegram/misc.h b/td/telegram/misc.h index f9b6de664..57c62d165 100644 --- a/td/telegram/misc.h +++ b/td/telegram/misc.h @@ -31,7 +31,7 @@ string strip_empty_characters(string str, size_t max_length, bool strip_rtlo = f // checks if string is empty after strip_empty_characters bool is_empty_string(const string &str) TD_WARN_UNUSED_RESULT; -// calculates hash of list of uint32 +// calculates hash of list of uint64 int64 get_vector_hash(const vector &numbers) TD_WARN_UNUSED_RESULT; // returns emoji corresponding to the specified number From 4370e88352443356cd31a0e20ea25dbd93367e39 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 19:03:26 +0300 Subject: [PATCH 055/200] Add "themed_premium_statuses_sticker_set_id" option. --- td/generate/scheme/td_api.tl | 2 +- td/telegram/ConfigManager.cpp | 11 ++++++++--- td/telegram/ContactsManager.cpp | 1 + td/telegram/JsonValue.cpp | 9 +++++++++ td/telegram/JsonValue.h | 2 ++ td/telegram/OptionManager.cpp | 5 +++++ 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8332d1517..0fe97154b 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -475,7 +475,7 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa //@payment_link An internal link to be opened for buying Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available premiumPaymentOption currency:string amount:int53 discount_percentage:int32 month_count:int32 store_product_id:string payment_link:InternalLinkType = PremiumPaymentOption; -//@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format +//@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format. If the custom emoji belongs to the sticker set GetOption("themed_premium_statuses_sticker_set_id"), then it's color must be changed to the color of the Telegram Premium badge premiumStatus custom_emoji_id:int64 = PremiumStatus; //@description Contains a list of premium statuses @premium_statuses The list of premium statuses diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 76f03a304..2789d65d9 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1478,10 +1478,10 @@ void ConfigManager::process_app_config(tl_object_ptr &c string animation_search_emojis; vector suggested_actions; bool can_archive_and_mute_new_chats_from_unknown_users = false; - int64 chat_read_mark_expire_period = 0; - int64 chat_read_mark_size_threshold = 0; + int32 chat_read_mark_expire_period = 0; + int32 chat_read_mark_size_threshold = 0; double animated_emoji_zoom = 0.0; - int64 reactions_uniq_max = 0; + int32 reactions_uniq_max = 0; vector premium_features; auto &premium_limit_keys = get_premium_limit_keys(); string premium_bot_username; @@ -1801,6 +1801,11 @@ void ConfigManager::process_app_config(tl_object_ptr &c stickers_normal_by_emoji_per_premium_num = get_json_value_int(std::move(key_value->value_), key); continue; } + if (key == "default_emoji_statuses_stickerset_id") { + auto setting_value = get_json_value_long(std::move(key_value->value_), key); + G()->set_option_integer("themed_premium_statuses_sticker_set_id", setting_value); + continue; + } new_values.push_back(std::move(key_value)); } diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index bdc7ebdcb..7669a8d3f 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -700,6 +700,7 @@ class UpdateEmojiStatusQuery final : public Td::ResultHandler { } void on_error(Status status) final { + get_recent_emoji_statuses(td_, Auto()); promise_.set_error(std::move(status)); } }; diff --git a/td/telegram/JsonValue.cpp b/td/telegram/JsonValue.cpp index 52f8712c5..db67dd50b 100644 --- a/td/telegram/JsonValue.cpp +++ b/td/telegram/JsonValue.cpp @@ -217,6 +217,15 @@ int32 get_json_value_int(telegram_api::object_ptr &&jso return 0; } +int64 get_json_value_long(telegram_api::object_ptr &&json_value, Slice name) { + CHECK(json_value != nullptr); + if (json_value->get_id() == telegram_api::jsonString::ID) { + return to_integer(static_cast(json_value.get())->value_); + } + LOG(ERROR) << "Expected Long as " << name << ", but found " << to_string(json_value); + return 0; +} + double get_json_value_double(telegram_api::object_ptr &&json_value, Slice name) { CHECK(json_value != nullptr); if (json_value->get_id() == telegram_api::jsonNumber::ID) { diff --git a/td/telegram/JsonValue.h b/td/telegram/JsonValue.h index d3231b868..a84aa3215 100644 --- a/td/telegram/JsonValue.h +++ b/td/telegram/JsonValue.h @@ -30,6 +30,8 @@ bool get_json_value_bool(telegram_api::object_ptr &&jso int32 get_json_value_int(telegram_api::object_ptr &&json_value, Slice name); +int64 get_json_value_long(telegram_api::object_ptr &&json_value, Slice name); + double get_json_value_double(telegram_api::object_ptr &&json_value, Slice name); string get_json_value_string(telegram_api::object_ptr &&json_value, Slice name); diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index fd9b36536..226e02ab0 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -102,6 +102,11 @@ OptionManager::OptionManager(Td *td) if (!have_option("chat_filter_chosen_chat_count_max")) { set_option_integer("chat_filter_chosen_chat_count_max", G()->is_test_dc() ? 5 : 100); } + if (!have_option("themed_premium_statuses_sticker_set_id")) { + auto sticker_set_id = + G()->is_test_dc() ? static_cast(2964141614563343) : static_cast(773947703670341676); + set_option_integer("themed_premium_statuses_sticker_set_id", sticker_set_id); + } } OptionManager::~OptionManager() = default; From 16c50a34637e117177b3bc123feea348f743f4e2 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 31 Aug 2022 19:52:56 +0300 Subject: [PATCH 056/200] Add limit on the number of recent emoji statuses. --- td/telegram/EmojiStatus.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index b97e3b4a8..ee54329a6 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -255,6 +255,10 @@ void add_recent_emoji_status(EmojiStatus emoji_status) { statuses.hash_ = 0; td::remove(statuses.emoji_statuses_, emoji_status); statuses.emoji_statuses_.insert(statuses.emoji_statuses_.begin(), emoji_status); + constexpr size_t MAX_RECENT_EMOJI_STATUSES = 50; // server-side limit + if (statuses.emoji_statuses_.size() > MAX_RECENT_EMOJI_STATUSES) { + statuses.emoji_statuses_.resize(MAX_RECENT_EMOJI_STATUSES); + } save_emoji_statuses(get_recent_emoji_statuses_database_key(), statuses); } From 5d7a36a26236b5e74bbd14fb23211186d92af932 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 1 Sep 2022 20:33:41 +0300 Subject: [PATCH 057/200] Make updates about change of premium status more robust. --- td/telegram/ContactsManager.cpp | 22 ++++++++++++---------- td/telegram/ContactsManager.h | 2 ++ td/telegram/EmojiStatus.cpp | 4 ++++ td/telegram/EmojiStatus.h | 2 ++ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 7669a8d3f..468c97f72 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8796,12 +8796,8 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; if (u->emoji_status != emoji_status) { - if ((u->is_premium ? u->emoji_status : EmojiStatus()) != (is_premium ? emoji_status : EmojiStatus())) { - u->is_changed = true; - } else { - u->need_save_to_database = true; - } u->emoji_status = emoji_status; + u->is_emoji_status_changed = true; } if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support || is_bot != u->is_bot || can_join_groups != u->can_join_groups || @@ -10333,6 +10329,16 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } u->is_phone_number_changed = false; } + if (u->is_emoji_status_changed) { + auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium); + if (effective_custom_emoji_id != u->last_sent_emoji_status) { + u->last_sent_emoji_status = effective_custom_emoji_id; + u->is_changed = true; + } else { + u->need_save_to_database = true; + } + u->is_emoji_status_changed = false; + } if (u->is_status_changed && user_id != get_my_id()) { auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached(); if (left_time >= 0 && left_time < 30 * 86400) { @@ -11771,12 +11777,8 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; + u->is_emoji_status_changed = true; LOG(DEBUG) << "Emoji status has changed for " << user_id; - if (u->is_premium) { - u->is_changed = true; - } else { - u->need_save_to_database = true; - } } } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 243193f2e..533980644 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -646,6 +646,7 @@ class ContactsManager final : public Actor { string phone_number; int64 access_hash = -1; EmojiStatus emoji_status; + int64 last_sent_emoji_status = 0; ProfilePhoto photo; @@ -692,6 +693,7 @@ class ContactsManager final : public Actor { bool is_username_changed = true; bool is_photo_changed = true; bool is_phone_number_changed = true; + bool is_emoji_status_changed = true; bool is_is_contact_changed = true; bool is_is_deleted_changed = true; bool is_changed = true; // have new changes that need to be sent to the client and database diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index ee54329a6..8bdea56be 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -217,6 +217,10 @@ td_api::object_ptr EmojiStatus::get_premium_status_object return td_api::make_object(custom_emoji_id_); } +int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium) const { + return is_premium ? 0 : custom_emoji_id_; +} + StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { if (emoji_status.is_empty()) { return string_builder << "DefaultProfileBadge"; diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 34d52106b..7bd558e8a 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -36,6 +36,8 @@ class EmojiStatus { td_api::object_ptr get_premium_status_object() const; + int64 get_effective_custom_emoji_id(bool is_premium) const; + bool is_empty() const { return custom_emoji_id_ == 0; } From df53830161f72aead30ec56ca668f26654cde711 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 1 Sep 2022 22:04:33 +0300 Subject: [PATCH 058/200] Add parameter setPremiumStatus.duration. --- td/generate/scheme/td_api.tl | 6 ++-- td/telegram/ContactsManager.cpp | 40 +++++++++++------------ td/telegram/ContactsManager.h | 1 - td/telegram/EmojiStatus.cpp | 56 ++++++++++++++++++++++++++++----- td/telegram/EmojiStatus.h | 21 +++++++++++-- td/telegram/Td.cpp | 2 +- td/telegram/cli.cpp | 10 ++++-- 7 files changed, 99 insertions(+), 37 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0fe97154b..db7101ddb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6091,8 +6091,10 @@ setBio bio:string = Ok; //@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username setUsername username:string = Ok; -//@description Changes the premium status of the current user; for Telegram Premium users only @premium_status New premium status; pass null to switch to the default badge -setPremiumStatus premium_status:premiumStatus = Ok; +//@description Changes the premium status of the current user; for Telegram Premium users only +//@premium_status New premium status; pass null to switch to the default badge +//@duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually +setPremiumStatus premium_status:premiumStatus duration:int32 = Ok; //@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user setLocation location:location = Ok; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 468c97f72..417f421d3 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8797,19 +8797,17 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; - u->is_emoji_status_changed = true; } - if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support || - is_bot != u->is_bot || can_join_groups != u->can_join_groups || - can_read_all_group_messages != u->can_read_all_group_messages || restriction_reasons != u->restriction_reasons || - is_scam != u->is_scam || is_fake != u->is_fake || is_inline_bot != u->is_inline_bot || - inline_query_placeholder != u->inline_query_placeholder || need_location_bot != u->need_location_bot || - can_be_added_to_attach_menu != u->can_be_added_to_attach_menu || attach_menu_enabled != u->attach_menu_enabled) { + if (is_verified != u->is_verified || is_support != u->is_support || is_bot != u->is_bot || + can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages || + restriction_reasons != u->restriction_reasons || is_scam != u->is_scam || is_fake != u->is_fake || + is_inline_bot != u->is_inline_bot || inline_query_placeholder != u->inline_query_placeholder || + need_location_bot != u->need_location_bot || can_be_added_to_attach_menu != u->can_be_added_to_attach_menu || + attach_menu_enabled != u->attach_menu_enabled) { LOG_IF(ERROR, is_bot != u->is_bot && !is_deleted && !u->is_deleted && u->is_received) << "User.is_bot has changed for " << user_id << "/" << u->username << " from " << source << " from " << u->is_bot << " to " << is_bot; u->is_verified = is_verified; - u->is_premium = is_premium; u->is_support = is_support; u->is_bot = is_bot; u->can_join_groups = can_join_groups; @@ -8826,6 +8824,10 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, LOG(DEBUG) << "Info has changed for " << user_id; u->is_changed = true; } + if (is_premium != u->is_premium) { + u->is_premium = is_premium; + u->is_changed = true; + } if (u->bot_info_version != bot_info_version) { u->bot_info_version = bot_info_version; @@ -10329,16 +10331,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } u->is_phone_number_changed = false; } - if (u->is_emoji_status_changed) { - auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium); - if (effective_custom_emoji_id != u->last_sent_emoji_status) { - u->last_sent_emoji_status = effective_custom_emoji_id; - u->is_changed = true; - } else { - u->need_save_to_database = true; - } - u->is_emoji_status_changed = false; - } if (u->is_status_changed && user_id != get_my_id()) { auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached(); if (left_time >= 0 && left_time < 30 * 86400) { @@ -10358,6 +10350,15 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } } + auto unix_time = G()->unix_time(); + auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium, unix_time); + if (effective_custom_emoji_id != u->last_sent_emoji_status) { + u->last_sent_emoji_status = effective_custom_emoji_id; + u->is_changed = true; + } else { + u->need_save_to_database = true; + } + if (u->is_deleted) { td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>()); } @@ -11777,7 +11778,6 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; - u->is_emoji_status_changed = true; LOG(DEBUG) << "Emoji status has changed for " << user_id; } } @@ -16781,7 +16781,7 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } - auto premium_status = u->is_premium ? u->emoji_status.get_premium_status_object() : nullptr; + auto premium_status = u->last_sent_emoji_status != 0 ? u->emoji_status.get_premium_status_object() : nullptr; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), get_profile_photo_object(td_->file_manager_.get(), u->photo), std::move(premium_status), u->is_contact, diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 533980644..7a24b1181 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -693,7 +693,6 @@ class ContactsManager final : public Actor { bool is_username_changed = true; bool is_photo_changed = true; bool is_phone_number_changed = true; - bool is_emoji_status_changed = true; bool is_is_contact_changed = true; bool is_is_deleted_changed = true; bool is_changed = true; // have new changes that need to be sent to the client and database diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 8bdea56be..0ec888f63 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -193,13 +193,42 @@ class ClearRecentEmojiStatusesQuery final : public Td::ResultHandler { } }; -EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) - : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { +EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status, int32 duration) { + if (premium_status == nullptr) { + return; + } + + custom_emoji_id_ = premium_status->custom_emoji_id_; + if (duration != 0) { + int32 current_time = G()->unix_time(); + if (duration >= std::numeric_limits::max() - current_time) { + until_date_ = std::numeric_limits::max(); + } else { + until_date_ = current_time + duration; + } + } } EmojiStatus::EmojiStatus(tl_object_ptr &&emoji_status) { - if (emoji_status != nullptr && emoji_status->get_id() == telegram_api::emojiStatus::ID) { - custom_emoji_id_ = static_cast(emoji_status.get())->document_id_; + if (emoji_status == nullptr) { + return; + } + switch (emoji_status->get_id()) { + case telegram_api::emojiStatusEmpty::ID: + break; + case telegram_api::emojiStatus::ID: { + auto status = static_cast(emoji_status.get()); + custom_emoji_id_ = status->document_id_; + break; + } + case telegram_api::emojiStatusUntil::ID: { + auto status = static_cast(emoji_status.get()); + custom_emoji_id_ = status->document_id_; + until_date_ = status->until_; + break; + } + default: + UNREACHABLE(); } } @@ -207,6 +236,9 @@ tl_object_ptr EmojiStatus::get_input_emoji_status() c if (is_empty()) { return make_tl_object(); } + if (until_date_ != 0) { + return make_tl_object(custom_emoji_id_, until_date_); + } return make_tl_object(custom_emoji_id_); } @@ -217,15 +249,25 @@ td_api::object_ptr EmojiStatus::get_premium_status_object return td_api::make_object(custom_emoji_id_); } -int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium) const { - return is_premium ? 0 : custom_emoji_id_; +int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const { + if (!is_premium) { + return 0; + } + if (until_date_ != 0 && until_date_ <= unix_time) { + return 0; + } + return custom_emoji_id_; } StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { if (emoji_status.is_empty()) { return string_builder << "DefaultProfileBadge"; } - return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; + string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; + if (emoji_status.until_date_ != 0) { + string_builder << " until " << emoji_status.until_date_; + } + return string_builder; } void get_default_emoji_statuses(Td *td, Promise> &&promise) { diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 7bd558e8a..5288f9695 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -20,6 +20,7 @@ class Td; class EmojiStatus { int64 custom_emoji_id_ = 0; + int32 until_date_ = 0; friend bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs); @@ -28,7 +29,7 @@ class EmojiStatus { public: EmojiStatus() = default; - explicit EmojiStatus(const td_api::object_ptr &premium_status); + EmojiStatus(const td_api::object_ptr &premium_status, int32 duration); explicit EmojiStatus(tl_object_ptr &&emoji_status); @@ -36,7 +37,7 @@ class EmojiStatus { td_api::object_ptr get_premium_status_object() const; - int64 get_effective_custom_emoji_id(bool is_premium) const; + int64 get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const; bool is_empty() const { return custom_emoji_id_ == 0; @@ -44,17 +45,31 @@ class EmojiStatus { template void store(StorerT &storer) const { + bool has_until_date = until_date_ != 0; + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_until_date); + END_STORE_FLAGS(); td::store(custom_emoji_id_, storer); + if (has_until_date) { + td::store(until_date_, storer); + } } template void parse(ParserT &parser) { + bool has_until_date; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_until_date); + END_PARSE_FLAGS(); td::parse(custom_emoji_id_, parser); + if (has_until_date) { + td::parse(until_date_, parser); + } } }; inline bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs) { - return lhs.custom_emoji_id_ == rhs.custom_emoji_id_; + return lhs.custom_emoji_id_ == rhs.custom_emoji_id_ && lhs.until_date_ == rhs.until_date_; } inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f5d45f873..b924640bf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6730,7 +6730,7 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_), std::move(promise)); + contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_, request.duration_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e7ec0c4e1..3038ad46f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4473,10 +4473,14 @@ class CliClient final : public Actor { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); } else if (op == "sun") { send_request(td_api::make_object(args)); + } else if (op == "spse") { + send_request(td_api::make_object(nullptr, 0)); } else if (op == "sps") { - auto premium_status = - args.empty() ? nullptr : td_api::make_object(to_integer(args)); - send_request(td_api::make_object(std::move(premium_status))); + int64 custom_emoji_id; + int32 until_date; + get_args(args, custom_emoji_id, until_date); + send_request(td_api::make_object( + td_api::make_object(custom_emoji_id), until_date)); } else if (op == "gdps") { send_request(td_api::make_object()); } else if (op == "grps") { From 085ac48a9f64f27c96de7c8c013b164e75bd9929 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 1 Sep 2022 22:26:04 +0300 Subject: [PATCH 059/200] Send updateUser when premium status expires. --- td/telegram/ContactsManager.cpp | 34 +++++++++++++++++++++++++++++++++ td/telegram/ContactsManager.h | 5 +++++ td/telegram/EmojiStatus.h | 4 ++++ 3 files changed, 43 insertions(+) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 417f421d3..a49637d54 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3416,6 +3416,9 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent user_online_timeout_.set_callback(on_user_online_timeout_callback); user_online_timeout_.set_callback_data(static_cast(this)); + user_emoji_status_timeout_.set_callback(on_user_emoji_status_timeout_callback); + user_emoji_status_timeout_.set_callback_data(static_cast(this)); + channel_unban_timeout_.set_callback(on_channel_unban_timeout_callback); channel_unban_timeout_.set_callback_data(static_cast(this)); @@ -3505,6 +3508,28 @@ void ContactsManager::on_user_online_timeout(UserId user_id) { update_user_online_member_count(u); } +void ContactsManager::on_user_emoji_status_timeout_callback(void *contacts_manager_ptr, int64 user_id_long) { + if (G()->close_flag()) { + return; + } + + auto contacts_manager = static_cast(contacts_manager_ptr); + send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_user_emoji_status_timeout, + UserId(user_id_long)); +} + +void ContactsManager::on_user_emoji_status_timeout(UserId user_id) { + if (G()->close_flag()) { + return; + } + + auto u = get_user(user_id); + CHECK(u != nullptr); + CHECK(u->is_update_user_sent); + + update_user(u, user_id); +} + void ContactsManager::on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long) { if (G()->close_flag()) { return; @@ -10353,11 +10378,20 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo auto unix_time = G()->unix_time(); auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium, unix_time); if (effective_custom_emoji_id != u->last_sent_emoji_status) { + user_emoji_status_timeout_.cancel_timeout(user_id.get()); u->last_sent_emoji_status = effective_custom_emoji_id; u->is_changed = true; } else { u->need_save_to_database = true; } + if (u->last_sent_emoji_status != 0) { + auto until_date = u->emoji_status.get_until_date(); + auto left_time = until_date - unix_time; + if (left_time >= 0 && left_time < 30 * 86400) { + LOG(DEBUG) << "Set premium status timeout for " << user_id << " in " << left_time; + user_emoji_status_timeout_.set_timeout_in(user_id.get(), left_time); + } + } if (u->is_deleted) { td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>()); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 7a24b1181..537665621 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -1676,6 +1676,8 @@ class ContactsManager final : public Actor { static void on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long); + static void on_user_emoji_status_timeout_callback(void *contacts_manager_ptr, int64 user_id_long); + static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long); static void on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long); @@ -1688,6 +1690,8 @@ class ContactsManager final : public Actor { void on_user_online_timeout(UserId user_id); + void on_user_emoji_status_timeout(UserId user_id); + void on_channel_unban_timeout(ChannelId channel_id); void on_user_nearby_timeout(UserId user_id); @@ -1861,6 +1865,7 @@ class ContactsManager final : public Actor { vector unimported_contact_invites_; // result of change_imported_contacts MultiTimeout user_online_timeout_{"UserOnlineTimeout"}; + MultiTimeout user_emoji_status_timeout_{"UserEmojiStatusTimeout"}; MultiTimeout channel_unban_timeout_{"ChannelUnbanTimeout"}; MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"}; MultiTimeout slow_mode_delay_timeout_{"SlowModeDelayTimeout"}; diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 5288f9695..3dc5e1d74 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -43,6 +43,10 @@ class EmojiStatus { return custom_emoji_id_ == 0; } + int32 get_until_date() const { + return until_date_; + } + template void store(StorerT &storer) const { bool has_until_date = until_date_ != 0; From 0974a8c17e58403938b76367cfc88e0a88a9ba0c Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 13:16:55 +0300 Subject: [PATCH 060/200] Fix adding of a premium status to recent. --- td/telegram/ContactsManager.cpp | 12 ++++++------ td/telegram/EmojiStatus.cpp | 1 + td/telegram/EmojiStatus.h | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index a49637d54..22bdf40c4 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8771,6 +8771,7 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, on_update_user_name(u, user_id, std::move(user->first_name_), std::move(user->last_name_), std::move(user->username_)); } + on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(user->emoji_status_))); bool is_verified = (flags & USER_FLAG_IS_VERIFIED) != 0; bool is_premium = (flags & USER_FLAG_IS_PREMIUM) != 0; @@ -8788,7 +8789,6 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, bool has_bot_info_version = (flags & USER_FLAG_HAS_BOT_INFO_VERSION) != 0; bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0; bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0; - EmojiStatus emoji_status(std::move(user->emoji_status_)); LOG_IF(ERROR, !can_join_groups && !is_bot) << "Receive not bot " << user_id << " which can't join groups from " << source; @@ -8820,9 +8820,6 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, << "Receive not bot " << user_id << " which has bot info version from " << source; int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; - if (u->emoji_status != emoji_status) { - u->emoji_status = emoji_status; - } if (is_verified != u->is_verified || is_support != u->is_support || is_bot != u->is_bot || can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages || restriction_reasons != u->restriction_reasons || is_scam != u->is_scam || is_fake != u->is_fake || @@ -10378,7 +10375,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo auto unix_time = G()->unix_time(); auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium, unix_time); if (effective_custom_emoji_id != u->last_sent_emoji_status) { - user_emoji_status_timeout_.cancel_timeout(user_id.get()); u->last_sent_emoji_status = effective_custom_emoji_id; u->is_changed = true; } else { @@ -10390,7 +10386,11 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo if (left_time >= 0 && left_time < 30 * 86400) { LOG(DEBUG) << "Set premium status timeout for " << user_id << " in " << left_time; user_emoji_status_timeout_.set_timeout_in(user_id.get(), left_time); + } else { + user_emoji_status_timeout_.cancel_timeout(user_id.get()); } + } else { + user_emoji_status_timeout_.cancel_timeout(user_id.get()); } if (u->is_deleted) { @@ -11811,8 +11811,8 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { + LOG(DEBUG) << "Change emoji status of " << user_id << " from " << u->emoji_status << " to " << emoji_status; u->emoji_status = emoji_status; - LOG(DEBUG) << "Emoji status has changed for " << user_id; } } diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 0ec888f63..c418b8fae 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -293,6 +293,7 @@ void add_recent_emoji_status(EmojiStatus emoji_status) { return; } + emoji_status.clear_until_date(); auto statuses = load_emoji_statuses(get_recent_emoji_statuses_database_key()); if (!statuses.emoji_statuses_.empty() && statuses.emoji_statuses_[0] == emoji_status) { return; diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 3dc5e1d74..3a0c7e8d5 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -47,6 +47,10 @@ class EmojiStatus { return until_date_; } + void clear_until_date() { + until_date_ = 0; + } + template void store(StorerT &storer) const { bool has_until_date = until_date_ != 0; From e212d9c62a52e143ca39f6dbe1f7ed146fd0cc77 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 13:48:06 +0300 Subject: [PATCH 061/200] Improve logging. --- td/telegram/ContactsManager.cpp | 4 ++-- td/telegram/EmojiStatus.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 22bdf40c4..248634f6d 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -11805,13 +11805,13 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(emoji_status))); update_user(u, user_id); } else { - LOG(INFO) << "Ignore update user emoji status about unknown " << user_id; + LOG(INFO) << "Ignore update user premium status about unknown " << user_id; } } void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { - LOG(DEBUG) << "Change emoji status of " << user_id << " from " << u->emoji_status << " to " << emoji_status; + LOG(DEBUG) << "Change premium status of " << user_id << " from " << u->emoji_status << " to " << emoji_status; u->emoji_status = emoji_status; } } diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index c418b8fae..7d936f2ab 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -38,9 +38,13 @@ struct EmojiStatuses { for (auto &status : emoji_statuses->statuses_) { EmojiStatus emoji_status(std::move(status)); if (emoji_status.is_empty()) { - LOG(ERROR) << "Receive empty emoji status"; + LOG(ERROR) << "Receive empty premium status"; continue; } + if (emoji_status.get_until_date() != 0) { + LOG(ERROR) << "Receive temporary premium status"; + emoji_status.clear_until_date(); + } emoji_statuses_.push_back(emoji_status); } } From 899ceecab171743da2fed746b0654b4250d6ca84 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 13:59:49 +0300 Subject: [PATCH 062/200] Support new special sticker set types. --- td/telegram/SpecialStickerSetType.cpp | 20 ++++++++++++++++++ td/telegram/SpecialStickerSetType.h | 4 ++++ td/telegram/StickersManager.cpp | 29 ++++++++++++++++++++++----- td/telegram/UpdatesManager.cpp | 2 ++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/td/telegram/SpecialStickerSetType.cpp b/td/telegram/SpecialStickerSetType.cpp index 4b8c9d413..106a8079c 100644 --- a/td/telegram/SpecialStickerSetType.cpp +++ b/td/telegram/SpecialStickerSetType.cpp @@ -29,6 +29,14 @@ SpecialStickerSetType SpecialStickerSetType::premium_gifts() { return SpecialStickerSetType("premium_gifts_sticker_set"); } +SpecialStickerSetType SpecialStickerSetType::generic_animations() { + return SpecialStickerSetType("generic_animations_sticker_set"); +} + +SpecialStickerSetType SpecialStickerSetType::default_statuses() { + return SpecialStickerSetType("default_statuses_sticker_set"); +} + SpecialStickerSetType::SpecialStickerSetType( const telegram_api::object_ptr &input_sticker_set) { CHECK(input_sticker_set != nullptr); @@ -45,6 +53,12 @@ SpecialStickerSetType::SpecialStickerSetType( case telegram_api::inputStickerSetPremiumGifts::ID: *this = premium_gifts(); break; + case telegram_api::inputStickerSetEmojiGenericAnimations::ID: + *this = generic_animations(); + break; + case telegram_api::inputStickerSetEmojiDefaultStatuses::ID: + *this = default_statuses(); + break; default: UNREACHABLE(); break; @@ -69,6 +83,12 @@ telegram_api::object_ptr SpecialStickerSetType::g if (*this == premium_gifts()) { return telegram_api::make_object(); } + if (*this == generic_animations()) { + return telegram_api::make_object(); + } + if (*this == default_statuses()) { + return telegram_api::make_object(); + } auto emoji = get_dice_emoji(); if (!emoji.empty()) { return telegram_api::make_object(emoji); diff --git a/td/telegram/SpecialStickerSetType.h b/td/telegram/SpecialStickerSetType.h index 3bd34a93e..7f80f7a71 100644 --- a/td/telegram/SpecialStickerSetType.h +++ b/td/telegram/SpecialStickerSetType.h @@ -31,6 +31,10 @@ class SpecialStickerSetType { static SpecialStickerSetType premium_gifts(); + static SpecialStickerSetType generic_animations(); + + static SpecialStickerSetType default_statuses(); + string get_dice_emoji() const; bool is_empty() const { diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 0d3e245f9..4f9f1b756 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1417,7 +1417,6 @@ void StickersManager::init() { is_inited_ = true; { - // add animated emoji sticker set auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_emoji()); if (G()->is_test_dc()) { init_special_sticker_set(sticker_set, 1258816259751954, 4879754868529595811, "emojies"); @@ -1427,13 +1426,21 @@ void StickersManager::init() { load_special_sticker_set_info_from_binlog(sticker_set); } if (!G()->is_test_dc()) { - // add animated emoji click sticker set auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_emoji_click()); load_special_sticker_set_info_from_binlog(sticker_set); } - // add premium gifts sticker set - auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::premium_gifts()); - load_special_sticker_set_info_from_binlog(sticker_set); + { + auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::premium_gifts()); + load_special_sticker_set_info_from_binlog(sticker_set); + } + { + auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::generic_animations()); + load_special_sticker_set_info_from_binlog(sticker_set); + } + { + auto &sticker_set = add_special_sticker_set(SpecialStickerSetType::default_statuses()); + load_special_sticker_set_info_from_binlog(sticker_set); + } dice_emojis_str_ = td_->option_manager_->get_option_string("dice_emojis", "🎲\x01🎯\x01🏀\x01⚽\x01⚽️\x01🎰\x01🎳"); @@ -1656,6 +1663,12 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t try_update_premium_gift_messages(); return; } + if (type == SpecialStickerSetType::generic_animations()) { + return; + } + if (type == SpecialStickerSetType::default_statuses()) { + return; + } CHECK(special_sticker_set.id_.is_valid()); auto sticker_set = get_sticker_set(special_sticker_set.id_); @@ -2739,6 +2752,8 @@ StickerSetId StickersManager::get_sticker_set_id(const tl_object_ptrstickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji()); td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::animated_emoji_click()); td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::premium_gifts()); + td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::generic_animations()); + td_->stickers_manager_->reload_special_sticker_set_by_type(SpecialStickerSetType::default_statuses()); schedule_data_reload(); } From 2eba57276a110e331e335f7027f6649578b4c8e0 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 15:02:37 +0300 Subject: [PATCH 063/200] Add td_api::getThemedPremiumStatuses. --- td/generate/scheme/td_api.tl | 7 ++++-- td/telegram/StickersManager.cpp | 39 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 4 ++++ td/telegram/Td.cpp | 6 +++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index db7101ddb..085ba5990 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5575,12 +5575,15 @@ getAttachmentMenuBot bot_user_id:int53 = AttachmentMenuBot; toggleBotIsAddedToAttachmentMenu bot_user_id:int53 is_added:Bool = Ok; -//@description Returns default premium statuses -getDefaultPremiumStatuses = PremiumStatuses; +//@description Returns up to 8 themed premium statuses, which color must be changed to the color of the Telegram Premium badge +getThemedPremiumStatuses = PremiumStatuses; //@description Returns recent premium statuses getRecentPremiumStatuses = PremiumStatuses; +//@description Returns default premium statuses +getDefaultPremiumStatuses = PremiumStatuses; + //@description Clears recent premium statuses clearRecentPremiumStatuses = Ok; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 4f9f1b756..dee278e02 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1667,6 +1667,7 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t return; } if (type == SpecialStickerSetType::default_statuses()) { + set_promises(pending_get_default_statuses_queries_); return; } @@ -5457,6 +5458,44 @@ void StickersManager::get_all_animated_emojis(bool is_recursive, promise.set_value(td_api::make_object(std::move(emojis))); } +void StickersManager::get_default_emoji_statuses(bool is_recursive, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::default_statuses()); + auto sticker_set = get_sticker_set(special_sticker_set.id_); + if (sticker_set == nullptr || !sticker_set->was_loaded_) { + if (is_recursive) { + return promise.set_value(td_api::make_object()); + } + + pending_get_default_statuses_queries_.push_back(PromiseCreator::lambda( + [actor_id = actor_id(this), promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + send_closure(actor_id, &StickersManager::get_default_emoji_statuses, true, std::move(promise)); + } + })); + load_special_sticker_set(special_sticker_set); + return; + } + + vector> statuses; + for (auto sticker_id : sticker_set->sticker_ids_) { + auto custom_emoji_id = get_custom_emoji_id(sticker_id); + if (custom_emoji_id == 0) { + LOG(ERROR) << "Ignore wrong sticker " << sticker_id; + continue; + } + statuses.emplace_back(td_api::make_object(custom_emoji_id)); + if (statuses.size() >= 8) { + break; + } + } + promise.set_value(td_api::make_object(std::move(statuses))); +} + void StickersManager::load_custom_emoji_sticker_from_database(int64 custom_emoji_id, Promise &&promise) { CHECK(custom_emoji_id != 0); auto &queries = custom_emoji_load_queries_[custom_emoji_id]; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 0e21a8faa..7b539d15b 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -103,6 +103,8 @@ class StickersManager final : public Actor { void get_all_animated_emojis(bool is_recursive, Promise> &&promise); + void get_default_emoji_statuses(bool is_recursive, Promise> &&promise); + void get_custom_emoji_stickers(vector &&document_ids, bool use_database, Promise> &&promise); @@ -967,6 +969,8 @@ class StickersManager final : public Actor { vector> pending_get_animated_emoji_queries_; vector> pending_get_premium_gift_option_sticker_queries_; + vector> pending_get_default_statuses_queries_; + double next_click_animated_emoji_message_time_ = 0; double next_update_animated_emoji_clicked_time_ = 0; vector pending_get_animated_emoji_click_stickers_; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b924640bf..46543219e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6733,6 +6733,12 @@ void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_, request.duration_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getThemedPremiumStatuses &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + stickers_manager_->get_default_emoji_statuses(false, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index d629f5557..7eabb8a6b 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1014,6 +1014,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::setPremiumStatus &request); + void on_request(uint64 id, const td_api::getThemedPremiumStatuses &request); + void on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request); void on_request(uint64 id, const td_api::getRecentPremiumStatuses &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 3038ad46f..ac5eb4629 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4481,6 +4481,8 @@ class CliClient final : public Actor { get_args(args, custom_emoji_id, until_date); send_request(td_api::make_object( td_api::make_object(custom_emoji_id), until_date)); + } else if (op == "gtps") { + send_request(td_api::make_object()); } else if (op == "gdps") { send_request(td_api::make_object()); } else if (op == "grps") { From 03af40bc08b571dd0e21317147f03f40c86cc026 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 15:39:07 +0300 Subject: [PATCH 064/200] Don't add themed premium statuses to recent. --- td/telegram/ContactsManager.cpp | 2 +- td/telegram/EmojiStatus.cpp | 8 +++++++- td/telegram/EmojiStatus.h | 18 +++++++++++++++--- td/telegram/StickersManager.cpp | 14 ++++++++++++++ td/telegram/StickersManager.h | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 248634f6d..078dafd32 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6629,7 +6629,7 @@ void ContactsManager::set_emoji_status(EmojiStatus emoji_status, Promise & if (!td_->option_manager_->get_option_boolean("is_premium")) { return promise.set_error(Status::Error(400, "The method is available only for Telegram Premium users")); } - add_recent_emoji_status(emoji_status); + add_recent_emoji_status(td_, emoji_status); auto query_promise = PromiseCreator::lambda( [actor_id = actor_id(this), emoji_status, promise = std::move(promise)](Result result) mutable { if (result.is_ok()) { diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 7d936f2ab..01c4f6bd5 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -8,6 +8,7 @@ #include "td/telegram/Global.h" #include "td/telegram/logevent/LogEvent.h" +#include "td/telegram/StickersManager.h" #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" @@ -292,11 +293,16 @@ void get_recent_emoji_statuses(Td *td, Promisecreate_handler(std::move(promise))->send(statuses.hash_); } -void add_recent_emoji_status(EmojiStatus emoji_status) { +void add_recent_emoji_status(Td *td, EmojiStatus emoji_status) { if (emoji_status.is_empty()) { return; } + if (td->stickers_manager_->is_default_emoji_status(emoji_status.get_custom_emoji_id())) { + LOG(INFO) << "Skip adding themed premium status to recents"; + return; + } + emoji_status.clear_until_date(); auto statuses = load_emoji_statuses(get_recent_emoji_statuses_database_key()); if (!statuses.emoji_statuses_.empty() && statuses.emoji_statuses_[0] == emoji_status) { diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 3a0c7e8d5..cd40dea1e 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -43,6 +43,10 @@ class EmojiStatus { return custom_emoji_id_ == 0; } + int64 get_custom_emoji_id() const { + return custom_emoji_id_; + } + int32 get_until_date() const { return until_date_; } @@ -53,11 +57,15 @@ class EmojiStatus { template void store(StorerT &storer) const { + bool has_custom_emoji_id = custom_emoji_id_ != 0; bool has_until_date = until_date_ != 0; BEGIN_STORE_FLAGS(); + STORE_FLAG(has_custom_emoji_id); STORE_FLAG(has_until_date); END_STORE_FLAGS(); - td::store(custom_emoji_id_, storer); + if (has_custom_emoji_id) { + td::store(custom_emoji_id_, storer); + } if (has_until_date) { td::store(until_date_, storer); } @@ -65,11 +73,15 @@ class EmojiStatus { template void parse(ParserT &parser) { + bool has_custom_emoji_id; bool has_until_date; BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_custom_emoji_id); PARSE_FLAG(has_until_date); END_PARSE_FLAGS(); - td::parse(custom_emoji_id_, parser); + if (has_custom_emoji_id) { + td::parse(custom_emoji_id_, parser); + } if (has_until_date) { td::parse(until_date_, parser); } @@ -90,7 +102,7 @@ void get_default_emoji_statuses(Td *td, Promise> &&promise); -void add_recent_emoji_status(EmojiStatus emoji_status); +void add_recent_emoji_status(Td *td, EmojiStatus emoji_status); void clear_recent_emoji_statuses(Td *td, Promise &&promise); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index dee278e02..427bdfec3 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -5496,6 +5496,20 @@ void StickersManager::get_default_emoji_statuses(bool is_recursive, promise.set_value(td_api::make_object(std::move(statuses))); } +bool StickersManager::is_default_emoji_status(int64 custom_emoji_id) { + auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::default_statuses()); + auto sticker_set = get_sticker_set(special_sticker_set.id_); + if (sticker_set == nullptr || !sticker_set->was_loaded_) { + return false; + } + for (auto sticker_id : sticker_set->sticker_ids_) { + if (get_custom_emoji_id(sticker_id) == custom_emoji_id) { + return true; + } + } + return false; +} + void StickersManager::load_custom_emoji_sticker_from_database(int64 custom_emoji_id, Promise &&promise) { CHECK(custom_emoji_id != 0); auto &queries = custom_emoji_load_queries_[custom_emoji_id]; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 7b539d15b..977333d8b 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -105,6 +105,8 @@ class StickersManager final : public Actor { void get_default_emoji_statuses(bool is_recursive, Promise> &&promise); + bool is_default_emoji_status(int64 custom_emoji_id); + void get_custom_emoji_stickers(vector &&document_ids, bool use_database, Promise> &&promise); From e59573073508be15ea40ac07588348f1aa7b0229 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 16:34:05 +0300 Subject: [PATCH 065/200] Support t.me subdomains. --- td/telegram/LinkManager.cpp | 24 ++++++++++++++++++------ test/link.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 6886df6ec..20f644252 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -885,6 +885,24 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { return result; } + auto host = url_decode(http_url.host_, false); + to_lower_inplace(host); + if (ends_with(host, ".t.me") && host.size() >= 9 && host.find('.') == host.size() - 5) { + Slice subdomain(&host[0], host.size() - 5); + if (is_valid_username(subdomain) && subdomain != "addemoji" && subdomain != "addstickers" && + subdomain != "addtheme" && subdomain != "auth" && subdomain != "confirmphone" && subdomain != "invoice" && + subdomain != "joinchat" && subdomain != "login" && subdomain != "proxy" && subdomain != "setlanguage" && + subdomain != "share" && subdomain != "socks") { + result.is_internal_ = true; + result.is_tg_ = false; + result.query_ = PSTRING() << '/' << subdomain << http_url.query_; + return result; + } + } + if (begins_with(host, "www.")) { + host = host.substr(4); + } + vector t_me_urls{Slice("t.me"), Slice("telegram.me"), Slice("telegram.dog")}; if (Scheduler::context() != nullptr) { // for tests only string cur_t_me_url = G()->get_option_string("t_me_url"); @@ -897,12 +915,6 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { } } - auto host = url_decode(http_url.host_, false); - to_lower_inplace(host); - if (begins_with(host, "www.")) { - host = host.substr(4); - } - for (auto t_me_url : t_me_urls) { if (host == t_me_url) { result.is_internal_ = true; diff --git a/test/link.cpp b/test/link.cpp index eab877481..b81774f31 100644 --- a/test/link.cpp +++ b/test/link.cpp @@ -921,4 +921,29 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg://settings/filters", settings()); parse_internal_link("tg://settings/language", language_settings()); parse_internal_link("tg://settings/privacy", privacy_and_security_settings()); + + parse_internal_link("username.t.me////0/a//s/as?start=", bot_start("username", "")); + parse_internal_link("username.t.me?start=as", bot_start("username", "as")); + parse_internal_link("username.t.me", public_chat("username")); + parse_internal_link("aAAb.t.me/12345?single", message("tg:resolve?domain=aaab&post=12345&single")); + parse_internal_link("telegram.t.me/195", message("tg:resolve?domain=telegram&post=195")); + parse_internal_link("shares.t.me", public_chat("shares")); + + parse_internal_link("c.t.me/12345?single", nullptr); + parse_internal_link("aaa.t.me/12345?single", nullptr); + parse_internal_link("aaa_.t.me/12345?single", nullptr); + parse_internal_link("0aaa.t.me/12345?single", nullptr); + parse_internal_link("_aaa.t.me/12345?single", nullptr); + parse_internal_link("addemoji.t.me", nullptr); + parse_internal_link("addstickers.t.me", nullptr); + parse_internal_link("addtheme.t.me", nullptr); + parse_internal_link("auth.t.me", nullptr); + parse_internal_link("confirmphone.t.me", nullptr); + parse_internal_link("invoice.t.me", nullptr); + parse_internal_link("joinchat.t.me", nullptr); + parse_internal_link("login.t.me", nullptr); + parse_internal_link("proxy.t.me", nullptr); + parse_internal_link("setlanguage.t.me", nullptr); + parse_internal_link("share.t.me", nullptr); + parse_internal_link("socks.t.me", nullptr); } From 71b7eaa4a503db00b072198c99361c9297ef42e3 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 17:04:09 +0300 Subject: [PATCH 066/200] Improve logging. --- td/telegram/MessageReaction.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index a51488a54..32496f23f 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -492,7 +492,6 @@ unique_ptr MessageReactions::get_message_reactions( result->is_min_ = reactions->min_; FlatHashSet reaction_strings; - FlatHashSet recent_choosers; for (auto &reaction_count : reactions->results_) { auto reaction_str = get_message_reaction_string(reaction_count->reaction_); if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT || @@ -506,6 +505,7 @@ unique_ptr MessageReactions::get_message_reactions( continue; } + FlatHashSet recent_choosers; vector recent_chooser_dialog_ids; vector> recent_chooser_min_channels; for (auto &peer_reaction : reactions->recent_reactions_) { @@ -513,11 +513,11 @@ unique_ptr MessageReactions::get_message_reactions( if (peer_reaction_str == reaction_str) { DialogId dialog_id(peer_reaction->peer_id_); if (!dialog_id.is_valid()) { - LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser"; + LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser for reaction " << reaction_str; continue; } if (!recent_choosers.insert(dialog_id).second) { - LOG(ERROR) << "Receive duplicate " << dialog_id << " as a recent chooser"; + LOG(ERROR) << "Receive duplicate " << dialog_id << " as a recent chooser for reaction " << reaction_str; continue; } if (!td->messages_manager_->have_dialog_info(dialog_id)) { From 20332b5afb34e624209ac314e315326fc9ac609a Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 17:30:15 +0300 Subject: [PATCH 067/200] Check and fix all received reactions. --- td/telegram/MessagesManager.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d3cb5b91b..bddd44bb0 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -14482,6 +14482,16 @@ std::pair> MessagesManager::creat ttl = max(ttl, get_message_content_duration(message_info.content.get(), td_) + 1); } + if (message_id.is_scheduled()) { + if (message_info.reply_info != nullptr) { + LOG(ERROR) << "Receive " << message_id << " in " << dialog_id << " with reply info"; + message_info.reply_info = nullptr; + } + if (message_info.reactions != nullptr) { + LOG(ERROR) << "Receive " << message_id << " in " << dialog_id << " with reactions"; + message_info.reactions = nullptr; + } + } int32 view_count = message_info.view_count; if (view_count < 0) { LOG(ERROR) << "Wrong view_count = " << view_count << " received in " << message_id << " in " << dialog_id; @@ -14502,6 +14512,10 @@ std::pair> MessagesManager::creat } auto reactions = MessageReactions::get_message_reactions(td_, std::move(message_info.reactions), td_->auth_manager_->is_bot()); + if (reactions != nullptr) { + reactions->sort_reactions(active_reaction_pos_); + reactions->fix_chosen_reaction(get_my_dialog_id()); + } bool has_forward_info = message_info.forward_header != nullptr; @@ -14543,6 +14557,7 @@ std::pair> MessagesManager::creat message->is_from_scheduled = is_from_scheduled; message->is_pinned = is_pinned; message->noforwards = noforwards; + message->interaction_info_update_date = G()->unix_time(); message->view_count = view_count; message->forward_count = forward_count; message->reply_info = std::move(reply_info); From e3da366e2bc9d67ff775895cc9ed190a15a26720 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 17:34:28 +0300 Subject: [PATCH 068/200] Fix chosen reaction detection. --- td/telegram/MessageReaction.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 32496f23f..ebf8f3464 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -552,7 +552,8 @@ unique_ptr MessageReactions::get_message_reactions( } } - result->reactions_.emplace_back(std::move(reaction_str), reaction_count->count_, reaction_count->chosen_order_ != 0, + bool is_chosen = (reaction_count->flags_ & telegram_api::reactionCount::CHOSEN_ORDER_MASK) != 0; + result->reactions_.emplace_back(std::move(reaction_str), reaction_count->count_, is_chosen, std::move(recent_chooser_dialog_ids), std::move(recent_chooser_min_channels)); } return result; From c92f741a83c95dc5ea38e32edd75da2363c699a1 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 18:18:18 +0300 Subject: [PATCH 069/200] Add get_sticker_type function. --- td/telegram/StickerType.cpp | 10 ++++++++++ td/telegram/StickerType.h | 2 ++ td/telegram/StickersManager.hpp | 15 ++------------- td/telegram/UpdatesManager.cpp | 14 ++------------ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/td/telegram/StickerType.cpp b/td/telegram/StickerType.cpp index f635242b1..4b17753ba 100644 --- a/td/telegram/StickerType.cpp +++ b/td/telegram/StickerType.cpp @@ -8,6 +8,16 @@ namespace td { +StickerType get_sticker_type(bool is_mask, bool is_custom_emoji) { + if (is_custom_emoji) { + return StickerType::CustomEmoji; + } + if (is_mask) { + return StickerType::Mask; + } + return StickerType::Regular; +} + StickerType get_sticker_type(const td_api::object_ptr &type) { if (type == nullptr) { return StickerType::Regular; diff --git a/td/telegram/StickerType.h b/td/telegram/StickerType.h index 46fa08796..d4e2f18d1 100644 --- a/td/telegram/StickerType.h +++ b/td/telegram/StickerType.h @@ -18,6 +18,8 @@ enum class StickerType : int32 { Regular, Mask, CustomEmoji }; static constexpr int32 MAX_STICKER_TYPE = 3; +StickerType get_sticker_type(bool is_mask, bool is_custom_emoji); + StickerType get_sticker_type(const td_api::object_ptr &type); td_api::object_ptr get_sticker_type_object(StickerType sticker_type); diff --git a/td/telegram/StickersManager.hpp b/td/telegram/StickersManager.hpp index 14b78eb61..b425488ff 100644 --- a/td/telegram/StickersManager.hpp +++ b/td/telegram/StickersManager.hpp @@ -113,13 +113,7 @@ FileId StickersManager::parse_sticker(bool in_sticker_set, ParserT &parser) { } else { sticker->format_ = StickerFormat::Webp; } - if (is_emoji) { - sticker->type_ = StickerType::CustomEmoji; - } else if (is_mask) { - sticker->type_ = StickerType::Mask; - } else { - sticker->type_ = StickerType::Regular; - } + sticker->type_ = ::td::get_sticker_type(is_mask, is_emoji); if (in_sticker_set_stored != in_sticker_set) { Slice data = parser.template fetch_string_raw(parser.get_left_len()); for (auto c : data) { @@ -299,12 +293,7 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser } else { sticker_format = StickerFormat::Webp; } - StickerType sticker_type = StickerType::Regular; - if (is_emojis) { - sticker_type = StickerType::CustomEmoji; - } else if (is_masks) { - sticker_type = StickerType::Mask; - } + auto sticker_type = ::td::get_sticker_type(is_masks, is_emojis); if (sticker_set->is_inited_) { string title; diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index bbefbfa88..2b8b25db7 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3368,23 +3368,13 @@ void UpdatesManager::on_update(tl_object_ptr } void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - StickerType sticker_type = StickerType::Regular; - if (update->emojis_) { - sticker_type = StickerType::CustomEmoji; - } else if (update->masks_) { - sticker_type = StickerType::Mask; - } + auto sticker_type = get_sticker_type(update->masks_, update->emojis_); td_->stickers_manager_->on_update_sticker_sets(sticker_type); promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - StickerType sticker_type = StickerType::Regular; - if (update->emojis_) { - sticker_type = StickerType::CustomEmoji; - } else if (update->masks_) { - sticker_type = StickerType::Mask; - } + auto sticker_type = get_sticker_type(update->masks_, update->emojis_); td_->stickers_manager_->on_update_sticker_sets_order(sticker_type, StickersManager::convert_sticker_set_ids(update->order_)); promise.set_value(Unit()); From 8e5f33e699498519b7e9be38cb43ce97ccbefa76 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 18:35:57 +0300 Subject: [PATCH 070/200] Process updateMoveStickerSetToTop update. --- td/telegram/StickersManager.cpp | 33 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 4 ++++ td/telegram/UpdatesManager.cpp | 10 ++++++---- td/telegram/UpdatesManager.h | 3 +-- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 427bdfec3..1d9b6fe53 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -6740,6 +6740,39 @@ void StickersManager::on_update_sticker_sets_order(StickerType sticker_type, } } +// -1 - sticker set can't be moved to top, 0 - order wasn't changed, 1 - sticker set was moved to top +int StickersManager::move_installed_sticker_set_to_top(StickerType sticker_type, StickerSetId sticker_set_id) { + auto type = static_cast(sticker_type); + if (!are_installed_sticker_sets_loaded_[type]) { + return -1; + } + + vector ¤t_sticker_set_ids = installed_sticker_set_ids_[type]; + auto it = std::find(current_sticker_set_ids.begin(), current_sticker_set_ids.end(), sticker_set_id); + if (it == current_sticker_set_ids.end()) { + return -1; + } + if (sticker_set_id == current_sticker_set_ids[0]) { + CHECK(it == current_sticker_set_ids.begin()); + return 0; + } + + std::rotate(current_sticker_set_ids.begin(), it, it + 1); + + need_update_installed_sticker_sets_[type] = true; + return 1; +} + +void StickersManager::on_update_move_sticker_set_to_top(StickerType sticker_type, StickerSetId sticker_set_id) { + int result = move_installed_sticker_set_to_top(sticker_type, sticker_set_id); + if (result < 0) { + return reload_installed_sticker_sets(sticker_type, true); + } + if (result > 0) { + send_update_installed_sticker_sets(); + } +} + void StickersManager::reorder_installed_sticker_sets(StickerType sticker_type, const vector &sticker_set_ids, Promise &&promise) { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 977333d8b..7b7d209b5 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -213,6 +213,8 @@ class StickersManager final : public Actor { void on_update_sticker_sets_order(StickerType sticker_type, const vector &sticker_set_ids); + void on_update_move_sticker_set_to_top(StickerType sticker_type, StickerSetId sticker_set_id); + std::pair> get_archived_sticker_sets(StickerType sticker_type, StickerSetId offset_sticker_set_id, int32 limit, bool force, Promise &&promise); @@ -599,6 +601,8 @@ class StickersManager final : public Actor { int apply_installed_sticker_sets_order(StickerType sticker_type, const vector &sticker_set_ids); + int move_installed_sticker_set_to_top(StickerType sticker_type, StickerSetId sticker_set_id); + void on_update_sticker_set(StickerSet *sticker_set, bool is_installed, bool is_archived, bool is_changed, bool from_database = false); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 2b8b25db7..98c9f61da 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -3380,6 +3380,12 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + auto sticker_type = get_sticker_type(update->masks_, update->emojis_); + td_->stickers_manager_->on_update_move_sticker_set_to_top(sticker_type, StickerSetId(update->stickerset_)); + promise.set_value(Unit()); +} + void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { td_->stickers_manager_->reload_featured_sticker_sets(StickerType::Regular, true); @@ -3586,8 +3592,4 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - promise.set_value(Unit()); -} - } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 8ed898a9a..8535fd6f4 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -491,6 +491,7 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); + void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); @@ -539,8 +540,6 @@ class UpdatesManager final : public Actor { // unsupported updates void on_update(tl_object_ptr update, Promise &&promise); - - void on_update(tl_object_ptr update, Promise &&promise); }; } // namespace td From c662b81a3dc07b7630b2db8f13b1f8645d9d93fe Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 2 Sep 2022 18:59:15 +0300 Subject: [PATCH 071/200] Return ChatReactions from MessagesManager::get_message_active_reactions. --- td/telegram/MessagesManager.cpp | 11 ++++++----- td/telegram/MessagesManager.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index bddd44bb0..eb22c7437 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8303,21 +8303,21 @@ ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) cons } } -vector MessagesManager::get_message_active_reactions(const Dialog *d, const Message *m) const { +ChatReactions MessagesManager::get_message_active_reactions(const Dialog *d, const Message *m) const { CHECK(d != nullptr); CHECK(m != nullptr); if (is_service_message_content(m->content->get_type()) || m->ttl > 0) { - return vector(); + return ChatReactions(); } if (is_discussion_message(d->dialog_id, m)) { d = get_dialog(m->forward_info->from_dialog_id); if (d == nullptr) { LOG(ERROR) << "Failed to find linked " << m->forward_info->from_dialog_id << " to determine correct active reactions"; - return vector(); + return ChatReactions(); } } - return get_dialog_active_reactions(d).reactions_; + return get_dialog_active_reactions(d); } bool MessagesManager::need_poll_dialog_message_reactions(const Dialog *d) { @@ -24493,7 +24493,8 @@ vector MessagesManager::get_message_available_reactions(const for (const auto &active_reaction : active_reactions_) { // can add the reaction if it has already been used for the message or is available in the chat bool is_set = (m->reactions != nullptr && m->reactions->get_reaction(active_reaction.reaction_) != nullptr); - if (is_set || (can_add_new_reactions && td::contains(active_reactions, active_reaction.reaction_))) { + if (is_set || (can_add_new_reactions && (active_reactions.allow_all_ || + td::contains(active_reactions.reactions_, active_reaction.reaction_)))) { result.emplace_back(active_reaction.reaction_); } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index f0f74aaa0..bb5685e2c 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2696,7 +2696,7 @@ class MessagesManager final : public Actor { ChatReactions get_dialog_active_reactions(const Dialog *d) const; - vector get_message_active_reactions(const Dialog *d, const Message *m) const; + ChatReactions get_message_active_reactions(const Dialog *d, const Message *m) const; static bool need_poll_dialog_message_reactions(const Dialog *d); From 284dc4428b99770179d9a0687c690f7ef3758421 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 3 Sep 2022 10:21:04 +0300 Subject: [PATCH 072/200] Use send_closure to load dialogs to ensure that MessagesManager is inited. --- td/telegram/TopDialogManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/TopDialogManager.cpp b/td/telegram/TopDialogManager.cpp index e57752cd0..48e0519ec 100644 --- a/td/telegram/TopDialogManager.cpp +++ b/td/telegram/TopDialogManager.cpp @@ -375,7 +375,7 @@ void TopDialogManager::do_get_top_dialogs(GetTopDialogsQuery &&query) { } send_closure(actor_id, &TopDialogManager::on_load_dialogs, std::move(query), r_dialog_ids.move_as_ok()); }); - td_->messages_manager_->load_dialogs(std::move(dialog_ids), std::move(promise)); + send_closure(td_->messages_manager_actor_, &MessagesManager::load_dialogs, std::move(dialog_ids), std::move(promise)); } void TopDialogManager::on_load_dialogs(GetTopDialogsQuery &&query, vector &&dialog_ids) { From 16ba2ebfb801296f2acfe5a3adee0a732b36d877 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 4 Sep 2022 01:14:25 +0300 Subject: [PATCH 073/200] Add messageSendOptions.update_order_of_installed_sticker_sets. --- td/generate/scheme/td_api.tl | 3 ++- td/telegram/MessagesManager.cpp | 24 ++++++++++++++++++------ td/telegram/MessagesManager.h | 9 +++++++-- td/telegram/cli.cpp | 4 ++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 085ba5990..8ac974df6 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2147,8 +2147,9 @@ messageSchedulingStateSendWhenOnline = MessageSchedulingState; //@disable_notification Pass true to disable notification for the message //@from_background Pass true if the message is sent from the background //@protect_content Pass true if the content of the message must be protected from forwarding and saving; for bots only +//@update_order_of_installed_sticker_sets Pass true if the user explicitly chosen a sticker or a custom emoji from an installed sticker set; applicable only to sendMessage and sendMessageAlbum //@scheduling_state Message scheduling state; pass null to send message immediately. Messages sent to a secret chat, live location messages and self-destructing messages can't be scheduled -messageSendOptions disable_notification:Bool from_background:Bool protect_content:Bool scheduling_state:MessageSchedulingState = MessageSendOptions; +messageSendOptions disable_notification:Bool from_background:Bool protect_content:Bool update_order_of_installed_sticker_sets:Bool scheduling_state:MessageSchedulingState = MessageSendOptions; //@description Options to be used when a message content is copied without reference to the original sender. Service messages and messageInvoice can't be copied //@send_copy True, if content of the message needs to be copied without reference to the original sender. Always true if the message is forwarded to a secret chat or is local diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index eb22c7437..7c887792e 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4762,6 +4762,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(has_explicit_sender); STORE_FLAG(has_reactions); STORE_FLAG(has_available_reactions_generation); + STORE_FLAG(update_stickersets_order); END_STORE_FLAGS(); } @@ -5003,6 +5004,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(has_explicit_sender); PARSE_FLAG(has_reactions); PARSE_FLAG(has_available_reactions_generation); + PARSE_FLAG(update_stickersets_order); END_PARSE_FLAGS(); } @@ -25006,6 +25008,7 @@ unique_ptr MessagesManager::create_message_to_send( m->is_channel_post = is_channel_post; m->is_outgoing = is_scheduled || dialog_id != DialogId(my_id); m->from_background = options.from_background; + m->update_stickersets_order = options.update_stickersets_order; m->noforwards = options.protect_content; m->view_count = is_channel_post && !is_scheduled ? 1 : 0; m->forward_count = 0; @@ -25564,7 +25567,7 @@ Result> MessagesManager::send_message( TRY_STATUS(can_send_message(dialog_id)); TRY_RESULT(message_reply_markup, get_dialog_reply_markup(dialog_id, std::move(reply_markup))); TRY_RESULT(message_content, process_input_message_content(dialog_id, std::move(input_message_content))); - TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options))); + TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options), true)); TRY_STATUS(can_use_message_send_options(message_send_options, message_content)); TRY_STATUS(can_use_top_thread_message_id(d, top_thread_message_id, reply_to_message_id)); @@ -25685,11 +25688,15 @@ Result MessagesManager::process_message_copy_options( } Result MessagesManager::process_message_send_options( - DialogId dialog_id, tl_object_ptr &&options) const { + DialogId dialog_id, tl_object_ptr &&options, + bool allow_update_stickersets_order) const { MessageSendOptions result; if (options != nullptr) { result.disable_notification = options->disable_notification_; result.from_background = options->from_background_; + if (allow_update_stickersets_order) { + result.update_stickersets_order = options->update_order_of_installed_sticker_sets_; + } result.protect_content = options->protect_content_; TRY_RESULT_ASSIGN(result.schedule_date, get_message_schedule_date(std::move(options->scheduling_state_))); } @@ -25794,7 +25801,7 @@ Result> MessagesManager::send_message_group } TRY_STATUS(can_send_message(dialog_id)); - TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options))); + TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options), true)); vector, int32>> message_contents; std::unordered_set message_content_types; @@ -26674,7 +26681,7 @@ Result MessagesManager::send_inline_query_result_message(DialogId dia } TRY_STATUS(can_send_message(dialog_id)); - TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options))); + TRY_RESULT(message_send_options, process_message_send_options(dialog_id, std::move(options), false)); bool to_secret = false; switch (dialog_id.get_type()) { case DialogType::User: @@ -27933,6 +27940,9 @@ int32 MessagesManager::get_message_flags(const Message *m) { if (m->noforwards) { flags |= SEND_MESSAGE_FLAG_NOFORWARDS; } + if (m->update_stickersets_order) { + flags |= SEND_MESSAGE_FLAG_UPDATE_STICKER_SETS_ORDER; + } return flags; } @@ -28458,7 +28468,7 @@ Result MessagesManager::get_forwarded_messag } TRY_STATUS(can_send_message(to_dialog_id)); - TRY_RESULT(message_send_options, process_message_send_options(to_dialog_id, std::move(options))); + TRY_RESULT(message_send_options, process_message_send_options(to_dialog_id, std::move(options), false)); { MessageId last_message_id; @@ -28859,7 +28869,8 @@ Result> MessagesManager::resend_messages(DialogId dialog_id, v auto need_another_sender = message->send_error_code == 400 && message->send_error_message == CSlice("SEND_AS_PEER_INVALID"); - MessageSendOptions options(message->disable_notification, message->from_background, message->noforwards, + MessageSendOptions options(message->disable_notification, message->from_background, + message->update_stickersets_order, message->noforwards, get_message_schedule_date(message.get())); Message *m = get_message_to_send( d, message->top_thread_message_id, @@ -29066,6 +29077,7 @@ Result MessagesManager::add_local_message( m->is_outgoing = dialog_id != DialogId(my_id) && sender_user_id == my_id; m->disable_notification = disable_notification; m->from_background = false; + m->update_stickersets_order = false; m->view_count = 0; m->forward_count = 0; m->content = std::move(message_content.content); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index bb5685e2c..331c813a4 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1151,6 +1151,7 @@ class MessagesManager final : public Actor { bool has_explicit_sender = false; // for send_message bool is_copy = false; // for send_message bool from_background = false; // for send_message + bool update_stickersets_order = false; // for send_message bool disable_web_page_preview = false; // for send_message bool clear_draft = false; // for send_message bool in_game_share = false; // for send_message @@ -1721,13 +1722,16 @@ class MessagesManager final : public Actor { struct MessageSendOptions { bool disable_notification = false; bool from_background = false; + bool update_stickersets_order = false; bool protect_content = false; int32 schedule_date = 0; MessageSendOptions() = default; - MessageSendOptions(bool disable_notification, bool from_background, bool protect_content, int32 schedule_date) + MessageSendOptions(bool disable_notification, bool from_background, bool update_stickersets_order, + bool protect_content, int32 schedule_date) : disable_notification(disable_notification) , from_background(from_background) + , update_stickersets_order(update_stickersets_order) , protect_content(protect_content) , schedule_date(schedule_date) { } @@ -1881,7 +1885,8 @@ class MessagesManager final : public Actor { tl_object_ptr &&options) const; Result process_message_send_options(DialogId dialog_id, - tl_object_ptr &&options) const; + tl_object_ptr &&options, + bool allow_update_stickersets_order) const; static Status can_use_message_send_options(const MessageSendOptions &options, const unique_ptr &content, int32 ttl); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ac5eb4629..83b2b10fc 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1808,7 +1808,7 @@ class CliClient final : public Actor { bool disable_notification = false, bool from_background = false, int64 reply_to_message_id = 0) { auto id = send_request(td_api::make_object( chat_id, as_message_thread_id(message_thread_id_), reply_to_message_id, - td_api::make_object(disable_notification, from_background, true, + td_api::make_object(disable_notification, from_background, true, true, as_message_scheduling_state(schedule_date_)), nullptr, std::move(input_message_content))); if (id != 0) { @@ -1817,7 +1817,7 @@ class CliClient final : public Actor { } td_api::object_ptr default_message_send_options() const { - return td_api::make_object(false, false, false, + return td_api::make_object(false, false, false, true, as_message_scheduling_state(schedule_date_)); } From 17bb58d8bb50f901cdb05d00a5857b2d08810844 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 4 Sep 2022 17:50:03 +0300 Subject: [PATCH 074/200] Improve NetBSD build instructions. --- build.html | 6 +++--- tdutils/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build.html b/build.html index 88739752d..6174e7669 100644 --- a/build.html +++ b/build.html @@ -746,7 +746,7 @@ function onOptionsChanged() { pre_text.push('Note that building requires a lot of memory, so you may need to increase allowed per-process memory usage in /etc/login.conf or build from root.'); } if (os_netbsd) { - pre_text.push('Note that the following instruction is for NetBSD 8.0 and default SH shell.'); + pre_text.push('Note that the following instruction is for NetBSD 8+ and default SH shell.'); } if (os_mac) { pre_text.push('Note that the following instruction will build TDLib only for ' + os_mac_host_name + '.'); @@ -917,8 +917,8 @@ function onOptionsChanged() { if (!use_root) { commands.push('su -'); } - commands.push('export PKG_PATH=ftp://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/i386/8.0_2019Q2/All'); - var packages = 'git gperf php-7.3.6 cmake openssl gcc5-libs'; + commands.push('export PKG_PATH=http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r)/All'); + var packages = 'git gperf php-8* cmake openssl gcc12-libs mozilla-rootcerts-openssl'; commands.push('pkg_add ' + packages); if (!use_root) { commands.push('exit'); diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt index 59722ca8c..19c896bbe 100644 --- a/tdutils/CMakeLists.txt +++ b/tdutils/CMakeLists.txt @@ -399,7 +399,8 @@ if (ANDROID) endif() if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") - target_link_libraries(tdutils PUBLIC /usr/pkg/gcc5/i486--netbsdelf/lib/libatomic.so) + target_link_directories(tdutils PUBLIC /usr/pkg/gcc12/x86_64--netbsd/lib /usr/pkg/gcc12/i486--netbsdelf/lib) + target_link_libraries(tdutils PUBLIC atomic) endif() install(TARGETS tdutils EXPORT TdTargets From c5040d9fcd2ece0332b870a424e18bb05a1e6fbf Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 4 Sep 2022 21:35:11 +0300 Subject: [PATCH 075/200] Locally move sticker set to top. --- td/telegram/MessageContent.cpp | 26 ++++++++++++++++++-- td/telegram/MessageContent.h | 2 ++ td/telegram/MessagesManager.cpp | 3 +++ td/telegram/StickersManager.cpp | 42 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 4 ++++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 150258ff6..72b43b62b 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -5933,15 +5933,37 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC void on_sent_message_content(Td *td, const MessageContent *content) { switch (content->get_type()) { case MessageContentType::Animation: - return td->animations_manager_->add_saved_animation_by_id(get_message_content_any_file_id(content)); + return td->animations_manager_->add_saved_animation_by_id(get_message_content_upload_file_id(content)); case MessageContentType::Sticker: - return td->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_any_file_id(content)); + return td->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_upload_file_id(content)); default: // nothing to do return; } } +void move_message_content_sticker_set_to_top(Td *td, const MessageContent *content) { + CHECK(content != nullptr); + if (content->get_type() == MessageContentType::Sticker) { + td->stickers_manager_->move_sticker_set_to_top_by_sticker_id(get_message_content_upload_file_id(content)); + return; + } + + auto text = get_message_content_text(content); + if (text == nullptr) { + return; + } + vector custom_emoji_ids; + for (auto &entity : text->entities) { + if (entity.type == MessageEntity::Type::CustomEmoji) { + custom_emoji_ids.push_back(entity.document_id); + } + } + if (!custom_emoji_ids.empty()) { + td->stickers_manager_->move_sticker_set_to_top_by_custom_emoji_ids(custom_emoji_ids); + } +} + bool is_unsent_animated_emoji_click(Td *td, DialogId dialog_id, const DialogAction &action) { auto emoji = action.get_watching_animations_emoji(); if (emoji.empty()) { diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index cde9f3f2f..9e7c6f6bd 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -246,6 +246,8 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC void on_sent_message_content(Td *td, const MessageContent *content); +void move_message_content_sticker_set_to_top(Td *td, const MessageContent *content); + bool is_unsent_animated_emoji_click(Td *td, DialogId dialog_id, const DialogAction &action); void init_stickers_manager(Td *td); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7c887792e..12542ca62 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -25098,6 +25098,9 @@ MessagesManager::Message *MessagesManager::get_message_to_send( if (result->message_id.is_scheduled()) { send_update_chat_has_scheduled_messages(d, false); } + if (options.update_stickersets_order && !td_->auth_manager_->is_bot()) { + move_message_content_sticker_set_to_top(td_, result->content.get()); + } return result; } diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 1d9b6fe53..135df538e 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -6742,6 +6742,7 @@ void StickersManager::on_update_sticker_sets_order(StickerType sticker_type, // -1 - sticker set can't be moved to top, 0 - order wasn't changed, 1 - sticker set was moved to top int StickersManager::move_installed_sticker_set_to_top(StickerType sticker_type, StickerSetId sticker_set_id) { + LOG(INFO) << "Move " << sticker_set_id << " to top of " << sticker_type; auto type = static_cast(sticker_type); if (!are_installed_sticker_sets_loaded_[type]) { return -1; @@ -6788,6 +6789,47 @@ void StickersManager::reorder_installed_sticker_sets(StickerType sticker_type, promise.set_value(Unit()); } +void StickersManager::move_sticker_set_to_top_by_sticker_id(FileId sticker_id) { + LOG(INFO) << "Move to top sticker set of " << sticker_id; + const auto *s = get_sticker(sticker_id); + if (s == nullptr || !s->set_id_.is_valid()) { + return; + } + if (s->type_ == StickerType::CustomEmoji) { + // just in case + return; + } + if (move_installed_sticker_set_to_top(s->type_, s->set_id_) > 0) { + send_update_installed_sticker_sets(); + } +} + +void StickersManager::move_sticker_set_to_top_by_custom_emoji_ids(const vector &custom_emoji_ids) { + LOG(INFO) << "Move to top sticker set of " << custom_emoji_ids; + StickerSetId sticker_set_id; + for (auto custom_emoji_id : custom_emoji_ids) { + auto sticker_id = custom_emoji_to_sticker_id_.get(custom_emoji_id); + if (!sticker_id.is_valid()) { + return; + } + const auto *s = get_sticker(sticker_id); + if (s == nullptr || !s->set_id_.is_valid()) { + return; + } + CHECK(s->type_ == StickerType::CustomEmoji); + if (s->set_id_ != sticker_set_id) { + if (sticker_set_id.is_valid()) { + return; + } + sticker_set_id = s->set_id_; + } + } + CHECK(sticker_set_id.is_valid()); + if (move_installed_sticker_set_to_top(StickerType::CustomEmoji, sticker_set_id) > 0) { + send_update_installed_sticker_sets(); + } +} + Result> StickersManager::prepare_input_sticker( td_api::inputSticker *sticker, StickerType sticker_type) { if (sticker == nullptr) { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 7b7d209b5..efcd510b6 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -240,6 +240,10 @@ class StickersManager final : public Actor { void reorder_installed_sticker_sets(StickerType sticker_type, const vector &sticker_set_ids, Promise &&promise); + void move_sticker_set_to_top_by_sticker_id(FileId sticker_id); + + void move_sticker_set_to_top_by_custom_emoji_ids(const vector &custom_emoji_ids); + FileId upload_sticker_file(UserId user_id, tl_object_ptr &&sticker, Promise &&promise); void get_suggested_sticker_set_name(string title, Promise &&promise); From af0ca93b0985339cf3d65c6890a41086302d2bb7 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 12:06:16 +0300 Subject: [PATCH 076/200] Add pcre2 to the list of explicitly installed libraries on NetBSD. --- build.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.html b/build.html index 6174e7669..2c24bbb30 100644 --- a/build.html +++ b/build.html @@ -918,7 +918,7 @@ function onOptionsChanged() { commands.push('su -'); } commands.push('export PKG_PATH=http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r)/All'); - var packages = 'git gperf php-8* cmake openssl gcc12-libs mozilla-rootcerts-openssl'; + var packages = 'git gperf pcre2 php-8* cmake openssl gcc12-libs mozilla-rootcerts-openssl'; commands.push('pkg_add ' + packages); if (!use_root) { commands.push('exit'); From e843343a2254b09c69710cefc6e2599a79b80305 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 17:54:03 +0300 Subject: [PATCH 077/200] Add source to remove_file_impl. --- td/telegram/DownloadManager.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/td/telegram/DownloadManager.cpp b/td/telegram/DownloadManager.cpp index 8859cc4c2..4f0ba9e72 100644 --- a/td/telegram/DownloadManager.cpp +++ b/td/telegram/DownloadManager.cpp @@ -110,7 +110,7 @@ class DownloadManagerImpl final : public DownloadManager { } void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, Promise promise) final { - promise.set_result(remove_file_impl(file_id, file_source_id, delete_from_cache)); + promise.set_result(remove_file_impl(file_id, file_source_id, delete_from_cache, "remove_file")); } void remove_file_if_finished(FileId file_id) final { @@ -131,7 +131,7 @@ class DownloadManagerImpl final : public DownloadManager { to_remove.push_back(file_info.file_id); } for (auto file_id : to_remove) { - remove_file_impl(file_id, {}, delete_from_cache); + remove_file_impl(file_id, {}, delete_from_cache, "remove_all_files"); } promise.set_value(Unit()); } @@ -140,7 +140,7 @@ class DownloadManagerImpl final : public DownloadManager { Promise> promise) final { TRY_STATUS_PROMISE(promise, check_is_active("add_file")); - remove_file_impl(file_id, {}, false); + remove_file_impl(file_id, {}, false, "add_file"); auto download_id = next_download_id(); @@ -311,7 +311,7 @@ class DownloadManagerImpl final : public DownloadManager { return; } auto &file_info = *r_file_info_ptr.ok(); - remove_file_impl(file_info.file_id, {}, false); + remove_file_impl(file_info.file_id, {}, false, "update_file_deleted"); } void update_file_viewed(FileId file_id, FileSourceId file_source_id) final { @@ -517,7 +517,7 @@ class DownloadManagerImpl final : public DownloadManager { if (r_search_text.is_error()) { if (!G()->close_flag()) { - remove_file_impl(it->second->file_id, {}, false); + remove_file_impl(it->second->file_id, {}, false, "add_download_to_hints"); } } else { auto search_text = r_search_text.move_as_ok(); @@ -572,9 +572,9 @@ class DownloadManagerImpl final : public DownloadManager { } } - Status remove_file_impl(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) { + Status remove_file_impl(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, const char *source) { LOG(INFO) << "Remove from downloads file " << file_id << " from " << file_source_id; - TRY_STATUS(check_is_active("remove_file_impl")); + TRY_STATUS(check_is_active(source)); TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id)); auto &file_info = *file_info_ptr; auto download_id = file_info.download_id; @@ -608,7 +608,7 @@ class DownloadManagerImpl final : public DownloadManager { if (!is_completed(*file_info_ptr)) { return Status::Error("File is active"); } - return remove_file_impl(file_id, {}, false); + return remove_file_impl(file_id, {}, false, "remove_file_if_finished_impl"); } void timeout_expired() final { @@ -779,7 +779,7 @@ class DownloadManagerImpl final : public DownloadManager { while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) { auto download_id = *completed_download_ids_.begin(); auto file_info = get_file_info(download_id).move_as_ok(); - remove_file_impl(file_info->file_id, FileSourceId(), false); + remove_file_impl(file_info->file_id, FileSourceId(), false, "check_completed_downloads_size"); } } From cc4194a4066fd360488070f6f3d29ecef5fc8c6a Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 17:58:15 +0300 Subject: [PATCH 078/200] Check completed downloads size only after the database is loaded. --- td/telegram/DownloadManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/td/telegram/DownloadManager.cpp b/td/telegram/DownloadManager.cpp index 4f0ba9e72..b04e7fe93 100644 --- a/td/telegram/DownloadManager.cpp +++ b/td/telegram/DownloadManager.cpp @@ -775,6 +775,10 @@ class DownloadManagerImpl final : public DownloadManager { } void check_completed_downloads_size() { + if (!is_database_loaded_) { + return; + } + constexpr size_t MAX_COMPLETED_DOWNLOADS = 200; while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) { auto download_id = *completed_download_ids_.begin(); From 41a5e84d1c9c5bf30a1bbb737fbb11773aa99c7f Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 18:02:41 +0300 Subject: [PATCH 079/200] Remove unused DownloadManager::update_file_deleted. --- td/telegram/DownloadManager.cpp | 13 ------------- td/telegram/DownloadManager.h | 1 - 2 files changed, 14 deletions(-) diff --git a/td/telegram/DownloadManager.cpp b/td/telegram/DownloadManager.cpp index b04e7fe93..1c4628a2b 100644 --- a/td/telegram/DownloadManager.cpp +++ b/td/telegram/DownloadManager.cpp @@ -301,19 +301,6 @@ class DownloadManagerImpl final : public DownloadManager { } } - void update_file_deleted(FileId internal_file_id) final { - if (!callback_ || !is_database_loaded_) { - return; - } - - auto r_file_info_ptr = get_file_info_by_internal(internal_file_id); - if (r_file_info_ptr.is_error()) { - return; - } - auto &file_info = *r_file_info_ptr.ok(); - remove_file_impl(file_info.file_id, {}, false, "update_file_deleted"); - } - void update_file_viewed(FileId file_id, FileSourceId file_source_id) final { if (unviewed_completed_download_ids_.empty() || !callback_ || !is_database_loaded_) { return; diff --git a/td/telegram/DownloadManager.h b/td/telegram/DownloadManager.h index 51068e190..71624c611 100644 --- a/td/telegram/DownloadManager.h +++ b/td/telegram/DownloadManager.h @@ -106,7 +106,6 @@ class DownloadManager : public Actor { virtual void remove_file_if_finished(FileId file_id) = 0; virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size, int64 expected_size, bool is_paused) = 0; - virtual void update_file_deleted(FileId internal_file_id) = 0; virtual void update_file_viewed(FileId file_id, FileSourceId file_source_id) = 0; }; From 8d6a83433f6889509577952e829076c2f1c4ebf9 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 20:26:10 +0300 Subject: [PATCH 080/200] Use checks to catch wrong custom_emoji_to_sticker_id_ cache. --- td/telegram/StickersManager.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 135df538e..1543fb1be 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1737,13 +1737,11 @@ StickerType StickersManager::get_sticker_type(FileId file_id) const { bool StickersManager::is_premium_custom_emoji(int64 custom_emoji_id, bool default_result) const { auto sticker_id = custom_emoji_to_sticker_id_.get(custom_emoji_id); - const Sticker *s = get_sticker(sticker_id); - if (s == nullptr) { - if (sticker_id.is_valid()) { - LOG(ERROR) << "Failed to find custom emoji sticker " << sticker_id; - } + if (!sticker_id.is_valid()) { return default_result; } + const Sticker *s = get_sticker(sticker_id); + CHECK(s != nullptr); return s->is_premium_; } @@ -5557,13 +5555,17 @@ td_api::object_ptr StickersManager::get_custom_emoji_stickers_ vector reload_document_ids; for (auto document_id : document_ids) { auto file_id = custom_emoji_to_sticker_id_.get(document_id); - auto sticker = get_sticker_object(file_id); - if (sticker != nullptr && sticker->type_->get_id() == td_api::stickerTypeCustomEmoji::ID) { + if (file_id.is_valid()) { auto s = get_sticker(file_id); + CHECK(s != nullptr); + CHECK(s->type_ == StickerType::CustomEmoji); if (s->emoji_receive_date_ < update_before_date && !s->is_being_reloaded_) { s->is_being_reloaded_ = true; reload_document_ids.push_back(document_id); } + + auto sticker = get_sticker_object(file_id); + CHECK(sticker != nullptr); stickers.push_back(std::move(sticker)); } } @@ -6813,10 +6815,11 @@ void StickersManager::move_sticker_set_to_top_by_custom_emoji_ids(const vectorset_id_.is_valid()) { + CHECK(s != nullptr); + CHECK(s->type_ == StickerType::CustomEmoji); + if (!s->set_id_.is_valid()) { return; } - CHECK(s->type_ == StickerType::CustomEmoji); if (s->set_id_ != sticker_set_id) { if (sticker_set_id.is_valid()) { return; From 51ea826b6c27f4afd597bbc6b938b89ce7fb84e2 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 21:04:08 +0300 Subject: [PATCH 081/200] Synchronously load custom emoji from database if they are to be shown as an animated emoji. --- td/telegram/StickersManager.cpp | 29 ++++++++++++++++++++++++++--- td/telegram/StickersManager.h | 2 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 1543fb1be..21e078fb1 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -5343,10 +5343,13 @@ void StickersManager::register_emoji(const string &emoji, int64 custom_emoji_id, } auto &emoji_messages = *emoji_messages_ptr; if (emoji_messages.full_message_ids_.empty()) { - emoji_messages.sticker_id_ = get_custom_animated_emoji_sticker_id(custom_emoji_id); - if (!disable_animated_emojis_) { - get_custom_emoji_stickers({custom_emoji_id}, true, Promise>()); + if (!disable_animated_emojis_ && custom_emoji_to_sticker_id_.count(custom_emoji_id) == 0) { + load_custom_emoji_sticker_from_database_force(custom_emoji_id); + if (custom_emoji_to_sticker_id_.count(custom_emoji_id) == 0) { + get_custom_emoji_stickers({custom_emoji_id}, false, Promise>()); + } } + emoji_messages.sticker_id_ = get_custom_animated_emoji_sticker_id(custom_emoji_id); } emoji_messages.full_message_ids_.insert(full_message_id); return; @@ -5508,6 +5511,26 @@ bool StickersManager::is_default_emoji_status(int64 custom_emoji_id) { return false; } +void StickersManager::load_custom_emoji_sticker_from_database_force(int64 custom_emoji_id) { + if (!G()->parameters().use_file_db) { + return; + } + + auto value = G()->td_db()->get_sqlite_sync_pmc()->get(get_custom_emoji_database_key(custom_emoji_id)); + if (value.empty()) { + LOG(INFO) << "Failed to load custom emoji " << custom_emoji_id << " from database"; + return; + } + + LOG(INFO) << "Synchronously loaded custom emoji " << custom_emoji_id << " of size " << value.size() + << " from database"; + CustomEmojiLogEvent log_event; + if (log_event_parse(log_event, value).is_error()) { + LOG(ERROR) << "Delete invalid custom emoji " << custom_emoji_id << " value from database"; + G()->td_db()->get_sqlite_sync_pmc()->erase(get_custom_emoji_database_key(custom_emoji_id)); + } +} + void StickersManager::load_custom_emoji_sticker_from_database(int64 custom_emoji_id, Promise &&promise) { CHECK(custom_emoji_id != 0); auto &queries = custom_emoji_load_queries_[custom_emoji_id]; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index efcd510b6..2c0b59610 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -578,6 +578,8 @@ class StickersManager final : public Actor { static string get_custom_emoji_database_key(int64 custom_emoji_id); + void load_custom_emoji_sticker_from_database_force(int64 custom_emoji_id); + void load_custom_emoji_sticker_from_database(int64 custom_emoji_id, Promise &&promise); void on_load_custom_emoji_from_database(int64 custom_emoji_id, string value); From 4fdac24cc5c8a12c081d2d9e09173f70887b1a4d Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Sep 2022 22:04:50 +0300 Subject: [PATCH 082/200] Add setMessageReaction.update_recent_reactions. --- td/generate/scheme/td_api.tl | 3 ++- td/telegram/MessageReaction.cpp | 11 ++++++++--- td/telegram/MessageReaction.h | 3 ++- td/telegram/MessagesManager.cpp | 5 +++-- td/telegram/MessagesManager.h | 3 ++- td/telegram/Td.cpp | 2 +- td/telegram/cli.cpp | 6 +++--- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8ac974df6..a890cdbf0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5142,7 +5142,8 @@ getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions //@message_id Identifier of the message //@reaction_type Type of the new chosen reaction; pass null or the currently chosen non-big reaction to remove the reaction //@is_big Pass true if the reaction is added with a big animation -setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_big:Bool = Ok; +//@update_recent_reactions Pass true if the reaction needs to be added to recent reactions +setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_big:Bool update_recent_reactions:Bool = Ok; //@description Returns reactions added for a message, along with their sender //@chat_id Identifier of the chat to which the message belongs diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index ebf8f3464..1da9c2ae7 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -169,7 +169,7 @@ class SendReactionQuery final : public Td::ResultHandler { explicit SendReactionQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(FullMessageId full_message_id, string reaction, bool is_big) { + void send(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent) { dialog_id_ = full_message_id.get_dialog_id(); auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read); @@ -184,6 +184,10 @@ class SendReactionQuery final : public Td::ResultHandler { if (is_big) { flags |= telegram_api::messages_sendReaction::BIG_MASK; } + + if (add_to_recent) { + flags |= telegram_api::messages_sendReaction::ADD_TO_RECENT_MASK; + } } vector> reactions; @@ -689,9 +693,10 @@ void reload_message_reactions(Td *td, DialogId dialog_id, vector &&me td->create_handler()->send(dialog_id, std::move(message_ids)); } -void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, +void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise) { - td->create_handler(std::move(promise))->send(full_message_id, std::move(reaction), is_big); + td->create_handler(std::move(promise)) + ->send(full_message_id, std::move(reaction), is_big, add_to_recent); } void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit, diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 75ab1726e..eea0a108f 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -183,7 +183,8 @@ string get_message_reaction_string(const td_api::object_ptr &&message_ids); -void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, Promise &&promise); +void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, + Promise &&promise); void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit, Promise> &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 12542ca62..f7e560db6 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24515,7 +24515,7 @@ vector MessagesManager::get_message_available_reactions(const } void MessagesManager::set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, - Promise &&promise) { + bool add_to_recent, Promise &&promise) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "set_message_reaction"); if (d == nullptr) { @@ -24591,7 +24591,8 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string send_closure(actor_id, &MessagesManager::on_set_message_reaction, full_message_id, std::move(result), std::move(promise)); }); - ::td::set_message_reaction(td_, full_message_id, std::move(reaction), is_big, std::move(query_promise)); + ::td::set_message_reaction(td_, full_message_id, std::move(reaction), is_big, add_to_recent, + std::move(query_promise)); } void MessagesManager::on_set_message_reaction(FullMessageId full_message_id, Result result, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 331c813a4..c9d126491 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -808,7 +808,8 @@ class MessagesManager final : public Actor { Result> get_message_available_reactions(FullMessageId full_message_id); - void set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, Promise &&promise); + void set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, + Promise &&promise); void get_message_public_forwards(FullMessageId full_message_id, string offset, int32 limit, Promise> &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 46543219e..c3425e1e4 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5254,7 +5254,7 @@ void Td::on_request(uint64 id, td_api::setMessageReaction &request) { CREATE_OK_REQUEST_PROMISE(); messages_manager_->set_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)}, get_message_reaction_string(request.reaction_type_), request.is_big_, - std::move(promise)); + request.update_recent_reactions_, std::move(promise)); } void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 83b2b10fc..fc95940eb 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2225,14 +2225,14 @@ class CliClient final : public Actor { MessageId message_id; get_args(args, chat_id, message_id); send_request(td_api::make_object(chat_id, message_id)); - } else if (op == "react") { + } else if (op == "react" || op == "reactr") { ChatId chat_id; MessageId message_id; string reaction; bool is_big; get_args(args, chat_id, message_id, reaction, is_big); - send_request( - td_api::make_object(chat_id, message_id, as_reaction_type(reaction), is_big)); + send_request(td_api::make_object(chat_id, message_id, as_reaction_type(reaction), + is_big, op == "reactr")); } else if (op == "gmars") { ChatId chat_id; MessageId message_id; From 6ac839576c76c9eae99569567e2818bbe6528d2b Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 12:31:54 +0300 Subject: [PATCH 083/200] Add authorizationStateWaitEmailAddress. --- td/generate/scheme/td_api.tl | 4 ++++ td/telegram/AuthManager.cpp | 35 +++++++++++++++++++++++++--------- td/telegram/AuthManager.h | 20 ++++++++++++++++++- td/telegram/AuthManager.hpp | 12 ++++++++++-- td/telegram/SendCodeHelper.cpp | 6 ++---- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a890cdbf0..8e3a6929c 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -92,6 +92,10 @@ authorizationStateWaitEncryptionKey is_encrypted:Bool = AuthorizationState; //@description TDLib needs the user's phone number to authorize. Call `setAuthenticationPhoneNumber` to provide the phone number, or use `requestQrCodeAuthentication`, or `checkAuthenticationBotToken` for other authentication options authorizationStateWaitPhoneNumber = AuthorizationState; +//@description TDLib needs the user's email address to authorize. Call `setAuthenticationEmailAddress` to provide the email address, or directly call `setAuthenticationEmailCode` with Apple ID/Google ID token if allowed +//@allow_apple_id True, if authorization through Apple ID is allowed @allow_google_id True, if authorization through Google ID is allowed +authorizationStateWaitEmailAddress allow_apple_id:Bool allow_google_id:Bool = AuthorizationState; + //@description TDLib needs the user's authentication code to authorize @code_info Information about the authorization code that was sent authorizationStateWaitCode code_info:authenticationCodeInfo = AuthorizationState; diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index bc790af89..33110a457 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -107,6 +107,8 @@ tl_object_ptr AuthManager::get_authorization_state_o switch (authorization_state) { case State::WaitPhoneNumber: return make_tl_object(); + case State::WaitEmailAddress: + return make_tl_object(allow_apple_id_, allow_google_id_); case State::WaitCode: return send_code_helper_.get_authorization_state_wait_code(); case State::WaitQrCodeConfirmation: @@ -174,7 +176,8 @@ void AuthManager::check_bot_token(uint64 query_id, string bot_token) { void AuthManager::request_qr_code_authentication(uint64 query_id, vector other_user_ids) { if (state_ != State::WaitPhoneNumber) { - if ((state_ == State::WaitCode || state_ == State::WaitPassword || state_ == State::WaitRegistration) && + if ((state_ == State::WaitEmailAddress || state_ == State::WaitCode || state_ == State::WaitPassword || + state_ == State::WaitRegistration) && net_query_id_ == 0) { // ok } else { @@ -239,7 +242,8 @@ void AuthManager::on_update_login_token() { void AuthManager::set_phone_number(uint64 query_id, string phone_number, td_api::object_ptr settings) { if (state_ != State::WaitPhoneNumber) { - if ((state_ == State::WaitCode || state_ == State::WaitPassword || state_ == State::WaitRegistration) && + if ((state_ == State::WaitEmailAddress || state_ == State::WaitCode || state_ == State::WaitPassword || + state_ == State::WaitRegistration) && net_query_id_ == 0) { // ok } else { @@ -490,9 +494,15 @@ void AuthManager::on_send_code_result(NetQueryPtr &result) { LOG(INFO) << "Receive " << to_string(sent_code); - send_code_helper_.on_sent_code(std::move(sent_code)); - - update_state(State::WaitCode, true); + if (sent_code->type_->get_id() == telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID) { + auto code_type = move_tl_object_as(std::move(sent_code->type_)); + allow_apple_id_ = code_type->apple_signin_allowed_; + allow_google_id_ = code_type->google_signin_allowed_; + update_state(State::WaitEmailAddress, true); + } else { + send_code_helper_.on_sent_code(std::move(sent_code)); + update_state(State::WaitCode, true); + } on_query_ok(); } @@ -992,6 +1002,7 @@ bool AuthManager::load_state() { case State::WaitPassword: case State::WaitRegistration: return 86400; + case State::WaitEmailAddress: case State::WaitCode: case State::WaitQrCodeConfirmation: return 5 * 60; @@ -1007,7 +1018,11 @@ bool AuthManager::load_state() { } LOG(INFO) << "Load auth_state from database: " << tag("state", static_cast(db_state.state_)); - if (db_state.state_ == State::WaitCode) { + if (db_state.state_ == State::WaitEmailAddress) { + allow_apple_id_ = db_state.allow_apple_id_; + allow_google_id_ = db_state.allow_google_id_; + send_code_helper_ = std::move(db_state.send_code_helper_); + } else if (db_state.state_ == State::WaitCode) { send_code_helper_ = std::move(db_state.send_code_helper_); } else if (db_state.state_ == State::WaitQrCodeConfirmation) { other_user_ids_ = std::move(db_state.other_user_ids_); @@ -1026,8 +1041,8 @@ bool AuthManager::load_state() { } void AuthManager::save_state() { - if (state_ != State::WaitCode && state_ != State::WaitQrCodeConfirmation && state_ != State::WaitPassword && - state_ != State::WaitRegistration) { + if (state_ != State::WaitEmailAddress && state_ != State::WaitCode && state_ != State::WaitQrCodeConfirmation && + state_ != State::WaitPassword && state_ != State::WaitRegistration) { if (state_ != State::Closing) { G()->td_db()->get_binlog_pmc()->erase("auth_state"); } @@ -1035,7 +1050,9 @@ void AuthManager::save_state() { } DbState db_state = [&] { - if (state_ == State::WaitCode) { + if (state_ == State::WaitEmailAddress) { + return DbState::wait_email_address(api_id_, api_hash_, allow_apple_id_, allow_google_id_, send_code_helper_); + } else if (state_ == State::WaitCode) { return DbState::wait_code(api_id_, api_hash_, send_code_helper_); } else if (state_ == State::WaitQrCodeConfirmation) { return DbState::wait_qr_code_confirmation(api_id_, api_hash_, other_user_ids_, login_token_, diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 377925f8a..59b6f79c3 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -65,6 +65,7 @@ class AuthManager final : public NetActor { WaitQrCodeConfirmation, WaitPassword, WaitRegistration, + WaitEmailAddress, Ok, LoggingOut, DestroyingKeys, @@ -111,7 +112,11 @@ class AuthManager final : public NetActor { string api_hash_; Timestamp state_timestamp_; - // WaitCode + // WaitEmailAddress + bool allow_apple_id_ = false; + bool allow_google_id_ = false; + + // WaitEmailAddress and WaitCode SendCodeHelper send_code_helper_; // WaitQrCodeConfirmation @@ -127,6 +132,15 @@ class AuthManager final : public NetActor { DbState() = default; + static DbState wait_email_address(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id, + SendCodeHelper send_code_helper) { + DbState state(State::WaitEmailAddress, api_id, std::move(api_hash)); + state.send_code_helper_ = std::move(send_code_helper); + state.allow_apple_id_ = allow_apple_id; + state.allow_google_id_ = allow_google_id; + return state; + } + static DbState wait_code(int32 api_id, string api_hash, SendCodeHelper send_code_helper) { DbState state(State::WaitCode, api_id, std::move(api_hash)); state.send_code_helper_ = std::move(send_code_helper); @@ -177,6 +191,10 @@ class AuthManager final : public NetActor { int32 api_id_; string api_hash_; + // State::WaitEmailAddress + bool allow_apple_id_ = false; + bool allow_google_id_ = false; + // State::WaitCode SendCodeHelper send_code_helper_; string code_; diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp index b80df5191..2548e9cfa 100644 --- a/td/telegram/AuthManager.hpp +++ b/td/telegram/AuthManager.hpp @@ -62,6 +62,8 @@ void AuthManager::DbState::store(StorerT &storer) const { STORE_FLAG(is_wait_registration_supported); STORE_FLAG(is_wait_registration_stores_phone_number); STORE_FLAG(is_wait_qr_code_confirmation_supported); + STORE_FLAG(allow_apple_id_); + STORE_FLAG(allow_google_id_); END_STORE_FLAGS(); store(state_, storer); store(api_id_, storer); @@ -72,7 +74,9 @@ void AuthManager::DbState::store(StorerT &storer) const { store(terms_of_service_, storer); } - if (state_ == State::WaitCode) { + if (state_ == State::WaitEmailAddress) { + store(send_code_helper_, storer); + } else if (state_ == State::WaitCode) { store(send_code_helper_, storer); } else if (state_ == State::WaitQrCodeConfirmation) { store(other_user_ids_, storer); @@ -104,6 +108,8 @@ void AuthManager::DbState::parse(ParserT &parser) { PARSE_FLAG(is_wait_registration_supported); PARSE_FLAG(is_wait_registration_stores_phone_number); PARSE_FLAG(is_wait_qr_code_confirmation_supported); + PARSE_FLAG(allow_apple_id_); + PARSE_FLAG(allow_google_id_); END_PARSE_FLAGS(); } if (!is_wait_qr_code_confirmation_supported) { @@ -123,7 +129,9 @@ void AuthManager::DbState::parse(ParserT &parser) { parse(terms_of_service_, parser); } - if (state_ == State::WaitCode) { + if (state_ == State::WaitEmailAddress) { + parse(send_code_helper_, parser); + } else if (state_ == State::WaitCode) { parse(send_code_helper_, parser); } else if (state_ == State::WaitQrCodeConfirmation) { parse(other_user_ids_, parser); diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index 025532a65..e9ab0918f 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -145,10 +145,8 @@ SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_i auto code_type = move_tl_object_as(sent_code_type_ptr); return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::Message, code_type->length_, ""}; } - case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: { - auto code_type = move_tl_object_as(sent_code_type_ptr); - return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::Message, 0, ""}; - } + case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: + return AuthenticationCodeInfo(); default: UNREACHABLE(); return AuthenticationCodeInfo(); From 9fc136976cc7add02e6c0e6a438878201feab541 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 12:42:00 +0300 Subject: [PATCH 084/200] Remove ChainBufferWriter::init. --- tdutils/td/utils/buffer.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tdutils/td/utils/buffer.h b/tdutils/td/utils/buffer.h index ec81c85ad..798ceb9d5 100644 --- a/tdutils/td/utils/buffer.h +++ b/tdutils/td/utils/buffer.h @@ -678,14 +678,10 @@ class ChainBufferReader { class ChainBufferWriter { public: - ChainBufferWriter() { - init(); - } - - void init(size_t size = 0) { - writer_ = BufferWriter(size); - tail_ = ChainBufferNodeAllocator::create(writer_.as_buffer_slice(), true); - head_ = ChainBufferNodeAllocator::clone(tail_); + ChainBufferWriter() + : writer_(0) + , tail_(ChainBufferNodeAllocator::create(writer_.as_buffer_slice(), true)) + , head_(ChainBufferNodeAllocator::clone(tail_)) { } MutableSlice prepare_append(size_t hint = 0) { @@ -770,9 +766,9 @@ class ChainBufferWriter { return !tail_; } - ChainBufferNodeReaderPtr head_; - ChainBufferNodeWriterPtr tail_; BufferWriter writer_; + ChainBufferNodeWriterPtr tail_; + ChainBufferNodeReaderPtr head_; }; class BufferBuilder { From 45484ce53b3c44fb27125e84152140c277f15997 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 14:04:39 +0300 Subject: [PATCH 085/200] Add td_api::setAuthenticationEmailAddress. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/AuthManager.cpp | 40 ++++++++++++++++++++++++++++++---- td/telegram/AuthManager.h | 4 ++++ td/telegram/SendCodeHelper.cpp | 15 ++++++++++++- td/telegram/SendCodeHelper.h | 6 +++++ td/telegram/Td.cpp | 5 +++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 8 files changed, 72 insertions(+), 5 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8e3a6929c..53f34bbd8 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4615,6 +4615,9 @@ checkDatabaseEncryptionKey encryption_key:bytes = Ok; //@phone_number The phone number of the user, in international format @settings Settings for the authentication of the user's phone number; pass null to use default settings setAuthenticationPhoneNumber phone_number:string settings:phoneNumberAuthenticationSettings = Ok; +//@description Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress @email_address The email address of the user +setAuthenticationEmailAddress email_address:string = Ok; + //@description Re-sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed resendAuthenticationCode = Ok; diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 33110a457..46ce73db5 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -255,7 +255,7 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, query_id, Status::Error(400, "Cannot set phone number after bot token was entered. You need to log out first")); } if (phone_number.empty()) { - return on_query_error(query_id, Status::Error(400, "Phone number can't be empty")); + return on_query_error(query_id, Status::Error(400, "Phone number must be non-empty")); } other_user_ids_.clear(); @@ -272,6 +272,22 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, std::move(phone_number), settings, api_id_, api_hash_))); } +void AuthManager::set_email_address(uint64 query_id, string email_address) { + if (state_ != State::WaitEmailAddress) { + return on_query_error(query_id, Status::Error(400, "Call to setAuthenticationEmailAddress unexpected")); + } + if (email_address.empty()) { + return on_query_error(query_id, Status::Error(400, "Email address must be non-empty")); + } + + email_address_ = std::move(email_address); + + on_new_query(query_id); + + start_net_query(NetQueryType::SendEmailCode, + G()->net_query_creator().create_unauth(send_code_helper_.send_verify_email_code(email_address_))); +} + void AuthManager::resend_authentication_code(uint64 query_id) { if (state_ != State::WaitCode) { return on_query_error(query_id, Status::Error(400, "Call to resendAuthenticationCode unexpected")); @@ -308,7 +324,7 @@ void AuthManager::register_user(uint64 query_id, string first_name, string last_ on_new_query(query_id); first_name = clean_name(first_name, MAX_NAME_LENGTH); if (first_name.empty()) { - return on_query_error(Status::Error(400, "First name can't be empty")); + return on_query_error(Status::Error(400, "First name must be non-empty")); } last_name = clean_name(last_name, MAX_NAME_LENGTH); @@ -496,6 +512,7 @@ void AuthManager::on_send_code_result(NetQueryPtr &result) { if (sent_code->type_->get_id() == telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID) { auto code_type = move_tl_object_as(std::move(sent_code->type_)); + send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_)); allow_apple_id_ = code_type->apple_signin_allowed_; allow_google_id_ = code_type->google_signin_allowed_; update_state(State::WaitEmailAddress, true); @@ -506,6 +523,18 @@ void AuthManager::on_send_code_result(NetQueryPtr &result) { on_query_ok(); } +void AuthManager::on_send_email_code_result(NetQueryPtr &result) { + auto r_sent_code = fetch_result(result->ok()); + if (r_sent_code.is_error()) { + return on_query_error(r_sent_code.move_as_error()); + } + auto sent_code = r_sent_code.move_as_ok(); + + LOG(INFO) << "Receive " << to_string(sent_code); + + on_query_ok(); +} + void AuthManager::on_request_qr_code_result(NetQueryPtr &result, bool is_import) { Status status; if (result->is_ok()) { @@ -871,8 +900,8 @@ void AuthManager::on_result(NetQueryPtr result) { type = net_query_type_; net_query_type_ = NetQueryType::None; if (result->is_error()) { - if ((type == NetQueryType::SendCode || type == NetQueryType::SignIn || type == NetQueryType::RequestQrCode || - type == NetQueryType::ImportQrCode) && + if ((type == NetQueryType::SendCode || type == NetQueryType::SendEmailCode || type == NetQueryType::SignIn || + type == NetQueryType::RequestQrCode || type == NetQueryType::ImportQrCode) && result->error().code() == 401 && result->error().message() == CSlice("SESSION_PASSWORD_NEEDED")) { auto dc_id = DcId::main(); if (type == NetQueryType::ImportQrCode) { @@ -927,6 +956,9 @@ void AuthManager::on_result(NetQueryPtr result) { case NetQueryType::SendCode: on_send_code_result(result); break; + case NetQueryType::SendEmailCode: + on_send_email_code_result(result); + break; case NetQueryType::RequestQrCode: on_request_qr_code_result(result, false); break; diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 59b6f79c3..06b43c691 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -35,6 +35,7 @@ class AuthManager final : public NetActor { void set_phone_number(uint64 query_id, string phone_number, td_api::object_ptr settings); + void set_email_address(uint64 query_id, string email_address); void resend_authentication_code(uint64 query_id); void check_code(uint64 query_id, string code); void register_user(uint64 query_id, string first_name, string last_name); @@ -76,6 +77,7 @@ class AuthManager final : public NetActor { SignIn, SignUp, SendCode, + SendEmailCode, RequestQrCode, ImportQrCode, GetPassword, @@ -194,6 +196,7 @@ class AuthManager final : public NetActor { // State::WaitEmailAddress bool allow_apple_id_ = false; bool allow_google_id_ = false; + string email_address_; // State::WaitCode SendCodeHelper send_code_helper_; @@ -249,6 +252,7 @@ class AuthManager final : public NetActor { void destroy_auth_keys(); void on_send_code_result(NetQueryPtr &result); + void on_send_email_code_result(NetQueryPtr &result); void on_request_qr_code_result(NetQueryPtr &result, bool is_import); void on_get_password_result(NetQueryPtr &result); void on_request_password_recovery_result(NetQueryPtr &result); diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index e9ab0918f..f8636e835 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -12,12 +12,16 @@ namespace td { void SendCodeHelper::on_sent_code(telegram_api::object_ptr sent_code) { - phone_code_hash_ = sent_code->phone_code_hash_; + phone_code_hash_ = std::move(sent_code->phone_code_hash_); sent_code_info_ = get_authentication_code_info(std::move(sent_code->type_)); next_code_info_ = get_authentication_code_info(std::move(sent_code->next_type_)); next_code_timestamp_ = Timestamp::in((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); } +void SendCodeHelper::on_phone_code_hash(string &&phone_code_hash) { + phone_code_hash_ = std::move(phone_code_hash); +} + td_api::object_ptr SendCodeHelper::get_authorization_state_wait_code() const { return make_tl_object(get_authentication_code_info_object()); } @@ -76,6 +80,10 @@ telegram_api::auth_sendCode SendCodeHelper::send_code(string phone_number, const return telegram_api::auth_sendCode(phone_number_, api_id, api_hash, get_input_code_settings(settings)); } +telegram_api::account_sendVerifyEmailCode SendCodeHelper::send_verify_email_code(const string &email_address) { + return telegram_api::account_sendVerifyEmailCode(get_email_verify_purpose_login_setup(), email_address); +} + telegram_api::account_sendChangePhoneCode SendCodeHelper::send_change_phone_code(Slice phone_number, const Settings &settings) { phone_number_ = phone_number.str(); @@ -175,4 +183,9 @@ td_api::object_ptr SendCodeHelper::get_authentic } } +telegram_api::object_ptr +SendCodeHelper::get_email_verify_purpose_login_setup() const { + return telegram_api::make_object(phone_number_, phone_code_hash_); +} + } // namespace td diff --git a/td/telegram/SendCodeHelper.h b/td/telegram/SendCodeHelper.h index f37fb8d8c..bae0cc45d 100644 --- a/td/telegram/SendCodeHelper.h +++ b/td/telegram/SendCodeHelper.h @@ -20,6 +20,8 @@ class SendCodeHelper { public: void on_sent_code(telegram_api::object_ptr sent_code); + void on_phone_code_hash(string &&phone_code_hash); + td_api::object_ptr get_authorization_state_wait_code() const; td_api::object_ptr get_authentication_code_info_object() const; @@ -31,6 +33,8 @@ class SendCodeHelper { telegram_api::auth_sendCode send_code(string phone_number, const Settings &settings, int32 api_id, const string &api_hash); + telegram_api::account_sendVerifyEmailCode send_verify_email_code(const string &email_address); + telegram_api::account_sendChangePhoneCode send_change_phone_code(Slice phone_number, const Settings &settings); telegram_api::account_sendVerifyPhoneCode send_verify_phone_code(Slice phone_number, const Settings &settings); @@ -88,6 +92,8 @@ class SendCodeHelper { const AuthenticationCodeInfo &authentication_code_info); static telegram_api::object_ptr get_input_code_settings(const Settings &settings); + + telegram_api::object_ptr get_email_verify_purpose_login_setup() const; }; } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index c3425e1e4..d9d6057c1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4261,6 +4261,11 @@ void Td::on_request(uint64 id, td_api::setAuthenticationPhoneNumber &request) { std::move(request.settings_)); } +void Td::on_request(uint64 id, td_api::setAuthenticationEmailAddress &request) { + CLEAN_INPUT_STRING(request.email_address_); + send_closure(auth_manager_actor_, &AuthManager::set_email_address, id, std::move(request.email_address_)); +} + void Td::on_request(uint64 id, const td_api::resendAuthenticationCode &request) { send_closure(auth_manager_actor_, &AuthManager::resend_authentication_code, id); } diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 7eabb8a6b..57375315c 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -398,6 +398,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setAuthenticationPhoneNumber &request); + void on_request(uint64 id, td_api::setAuthenticationEmailAddress &request); + void on_request(uint64 id, const td_api::resendAuthenticationCode &request); void on_request(uint64 id, td_api::checkAuthenticationCode &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index fc95940eb..bfeb46937 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1842,6 +1842,8 @@ class CliClient final : public Actor { } else if (op == "sap" || op == "sapn") { send_request( td_api::make_object(args, get_phone_number_authentication_settings())); + } else if (op == "sae" || op == "saea") { + send_request(td_api::make_object(args)); } else if (op == "rac") { send_request(td_api::make_object()); } else if (op == "cdek" || op == "CheckDatabaseEncryptionKey") { From 79be03d0718c0fc2619c6a2a2e4d79a6cf7a7030 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 14:46:11 +0300 Subject: [PATCH 086/200] Add class SentEmailCode. --- CMakeLists.txt | 2 ++ td/telegram/PasswordManager.cpp | 52 ++++++++++++++++----------------- td/telegram/PasswordManager.h | 14 ++++----- td/telegram/SentEmailCode.cpp | 27 +++++++++++++++++ td/telegram/SentEmailCode.h | 50 +++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 td/telegram/SentEmailCode.cpp create mode 100644 td/telegram/SentEmailCode.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d027bfed9..9f755cfb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -429,6 +429,7 @@ set(TDLIB_SOURCE td/telegram/SecureStorage.cpp td/telegram/SecureValue.cpp td/telegram/SendCodeHelper.cpp + td/telegram/SentEmailCode.cpp td/telegram/SequenceDispatcher.cpp td/telegram/SpecialStickerSetType.cpp td/telegram/SponsoredMessageManager.cpp @@ -676,6 +677,7 @@ set(TDLIB_SOURCE td/telegram/SecureStorage.h td/telegram/SecureValue.h td/telegram/SendCodeHelper.h + td/telegram/SentEmailCode.h td/telegram/SequenceDispatcher.h td/telegram/ServerMessageId.h td/telegram/SetWithPosition.h diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 765c78253..eb0d598af 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -425,20 +425,18 @@ void PasswordManager::send_email_address_verification_code( last_verified_email_address_ = email; auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode( make_tl_object(), std::move(email))); - send_with_promise( - std::move(query), PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { - auto r_result = fetch_result(std::move(r_query)); - if (r_result.is_error()) { - return promise.set_error(r_result.move_as_error()); - } - auto result = r_result.move_as_ok(); - if (result->length_ < 0 || result->length_ >= 100) { - LOG(ERROR) << "Receive wrong code length " << result->length_; - result->length_ = 0; - } - return promise.set_value( - make_tl_object(result->email_pattern_, result->length_)); - })); + send_with_promise(std::move(query), + PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + SentEmailCode sent_code(r_result.move_as_ok()); + if (sent_code.is_empty()) { + return promise.set_error(Status::Error(500, "Receive invalid response")); + } + return promise.set_value(sent_code.get_email_address_authentication_code_info_object()); + })); } void PasswordManager::resend_email_address_verification_code( @@ -469,16 +467,19 @@ void PasswordManager::check_email_address_verification_code(string code, Promise void PasswordManager::request_password_recovery( Promise> promise) { // is called only after authorization - send_with_promise( - G()->net_query_creator().create(telegram_api::auth_requestPasswordRecovery()), - PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { - auto r_result = fetch_result(std::move(r_query)); - if (r_result.is_error()) { - return promise.set_error(r_result.move_as_error()); - } - auto result = r_result.move_as_ok(); - return promise.set_value(make_tl_object(result->email_pattern_, 0)); - })); + send_with_promise(G()->net_query_creator().create(telegram_api::auth_requestPasswordRecovery()), + PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + auto result = r_result.move_as_ok(); + SentEmailCode sent_code(std::move(result->email_pattern_), 0); + if (sent_code.is_empty()) { + return promise.set_error(Status::Error(500, "Receive invalid response")); + } + return promise.set_value(sent_code.get_email_address_authentication_code_info_object()); + })); } void PasswordManager::check_password_recovery_code(string code, Promise promise) { @@ -795,8 +796,7 @@ void PasswordManager::do_get_state(Promise promise) { state.has_password = false; send_closure(actor_id, &PasswordManager::drop_cached_secret); } - state.unconfirmed_recovery_email_address_pattern = std::move(password->email_unconfirmed_pattern_); - state.code_length = code_length; + state.unconfirmed_recovery_email_code = {std::move(password->email_unconfirmed_pattern_), code_length}; if (password->flags_ & telegram_api::account_password::PENDING_RESET_DATE_MASK) { state.pending_reset_date = td::max(password->pending_reset_date_, 0); diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index dd5eb1546..292c6a0c3 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -9,6 +9,7 @@ #include "td/telegram/net/NetQuery.h" #include "td/telegram/NewPasswordState.h" #include "td/telegram/SecureStorage.h" +#include "td/telegram/SentEmailCode.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -106,8 +107,7 @@ class PasswordManager final : public NetQueryCallback { string password_hint; bool has_recovery_email_address = false; bool has_secure_values = false; - string unconfirmed_recovery_email_address_pattern; - int32 code_length = 0; + SentEmailCode unconfirmed_recovery_email_code; int32 pending_reset_date = 0; string current_client_salt; @@ -120,13 +120,9 @@ class PasswordManager final : public NetQueryCallback { NewPasswordState new_state; State get_password_state_object() const { - td_api::object_ptr code_info; - if (!unconfirmed_recovery_email_address_pattern.empty()) { - code_info = td_api::make_object( - unconfirmed_recovery_email_address_pattern, code_length); - } - return td_api::make_object(has_password, password_hint, has_recovery_email_address, - has_secure_values, std::move(code_info), pending_reset_date); + return td_api::make_object( + has_password, password_hint, has_recovery_email_address, has_secure_values, + unconfirmed_recovery_email_code.get_email_address_authentication_code_info_object(), pending_reset_date); } }; diff --git a/td/telegram/SentEmailCode.cpp b/td/telegram/SentEmailCode.cpp new file mode 100644 index 000000000..04a0e883a --- /dev/null +++ b/td/telegram/SentEmailCode.cpp @@ -0,0 +1,27 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/SentEmailCode.h" + +namespace td { + +SentEmailCode::SentEmailCode(telegram_api::object_ptr &&email_code) + : email_address_pattern_(std::move(email_code->email_pattern_)), code_length_(email_code->length_) { + if (code_length_ < 0 || code_length_ >= 100) { + LOG(ERROR) << "Receive wrong email code length " << code_length_; + code_length_ = 0; + } +} + +td_api::object_ptr +SentEmailCode::get_email_address_authentication_code_info_object() const { + if (is_empty()) { + return nullptr; + } + return td_api::make_object(email_address_pattern_, code_length_); +} + +} // namespace td diff --git a/td/telegram/SentEmailCode.h b/td/telegram/SentEmailCode.h new file mode 100644 index 000000000..564bbff88 --- /dev/null +++ b/td/telegram/SentEmailCode.h @@ -0,0 +1,50 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +class SentEmailCode { + string email_address_pattern_; + int32 code_length_ = 0; + + public: + SentEmailCode() = default; + + SentEmailCode(string &&email_address_pattern, int32 code_length) + : email_address_pattern_(std::move(email_address_pattern)), code_length_(code_length) { + } + + explicit SentEmailCode(telegram_api::object_ptr &&email_code); + + td_api::object_ptr get_email_address_authentication_code_info_object() + const; + + bool is_empty() const { + return email_address_pattern_.empty(); + } + + template + void store(StorerT &storer) const { + td::store(email_address_pattern_, storer); + td::store(code_length_, storer); + } + + template + void parse(ParserT &parser) { + td::parse(email_address_pattern_, parser); + td::parse(code_length_, parser); + } +}; + +} // namespace td From 3ad9ecc3a8e9108dc99f3014e373a846c3bf5b1e Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 14:53:19 +0300 Subject: [PATCH 087/200] Use Promise. --- td/telegram/PasswordManager.cpp | 21 +++++---------------- td/telegram/PasswordManager.h | 8 +++----- td/telegram/Td.cpp | 28 +++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index eb0d598af..e27f52c93 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -420,8 +420,7 @@ void PasswordManager::resend_recovery_email_address_code(Promise promise) })); } -void PasswordManager::send_email_address_verification_code( - string email, Promise> promise) { +void PasswordManager::send_email_address_verification_code(string email, Promise promise) { last_verified_email_address_ = email; auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode( make_tl_object(), std::move(email))); @@ -431,16 +430,11 @@ void PasswordManager::send_email_address_verification_code( if (r_result.is_error()) { return promise.set_error(r_result.move_as_error()); } - SentEmailCode sent_code(r_result.move_as_ok()); - if (sent_code.is_empty()) { - return promise.set_error(Status::Error(500, "Receive invalid response")); - } - return promise.set_value(sent_code.get_email_address_authentication_code_info_object()); + return promise.set_value(SentEmailCode(r_result.move_as_ok())); })); } -void PasswordManager::resend_email_address_verification_code( - Promise> promise) { +void PasswordManager::resend_email_address_verification_code(Promise promise) { if (last_verified_email_address_.empty()) { return promise.set_error(Status::Error(400, "No email address verification was sent")); } @@ -464,8 +458,7 @@ void PasswordManager::check_email_address_verification_code(string code, Promise })); } -void PasswordManager::request_password_recovery( - Promise> promise) { +void PasswordManager::request_password_recovery(Promise promise) { // is called only after authorization send_with_promise(G()->net_query_creator().create(telegram_api::auth_requestPasswordRecovery()), PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { @@ -474,11 +467,7 @@ void PasswordManager::request_password_recovery( return promise.set_error(r_result.move_as_error()); } auto result = r_result.move_as_ok(); - SentEmailCode sent_code(std::move(result->email_pattern_), 0); - if (sent_code.is_empty()) { - return promise.set_error(Status::Error(500, "Receive invalid response")); - } - return promise.set_value(sent_code.get_email_address_authentication_code_info_object()); + return promise.set_value(SentEmailCode(std::move(result->email_pattern_), 0)); })); } diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 292c6a0c3..8b465bc94 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -75,13 +75,11 @@ class PasswordManager final : public NetQueryCallback { void check_recovery_email_address_code(string code, Promise promise); void resend_recovery_email_address_code(Promise promise); - void send_email_address_verification_code( - string email, Promise> promise); - void resend_email_address_verification_code( - Promise> promise); + void send_email_address_verification_code(string email, Promise promise); + void resend_email_address_verification_code(Promise promise); void check_email_address_verification_code(string code, Promise promise); - void request_password_recovery(Promise> promise); + void request_password_recovery(Promise promise); void check_password_recovery_code(string code, Promise promise); void recover_password(string code, string new_password, string new_hint, Promise promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index d9d6057c1..93c96311e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -104,6 +104,7 @@ #include "td/telegram/SecretChatsManager.h" #include "td/telegram/SecureManager.h" #include "td/telegram/SecureValue.h" +#include "td/telegram/SentEmailCode.h" #include "td/telegram/SponsoredMessageManager.h" #include "td/telegram/StateManager.h" #include "td/telegram/StickerSetId.h" @@ -4434,7 +4435,14 @@ void Td::on_request(uint64 id, const td_api::resendRecoveryEmailAddressCode &req void Td::on_request(uint64 id, td_api::requestPasswordRecovery &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); - send_closure(password_manager_, &PasswordManager::request_password_recovery, std::move(promise)); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(result.ok().get_email_address_authentication_code_info_object()); + } + }); + send_closure(password_manager_, &PasswordManager::request_password_recovery, std::move(query_promise)); } void Td::on_request(uint64 id, td_api::checkPasswordRecoveryCode &request) { @@ -7651,14 +7659,28 @@ void Td::on_request(uint64 id, td_api::sendEmailAddressVerificationCode &request CHECK_IS_USER(); CLEAN_INPUT_STRING(request.email_address_); CREATE_REQUEST_PROMISE(); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(result.ok().get_email_address_authentication_code_info_object()); + } + }); send_closure(password_manager_, &PasswordManager::send_email_address_verification_code, - std::move(request.email_address_), std::move(promise)); + std::move(request.email_address_), std::move(query_promise)); } void Td::on_request(uint64 id, const td_api::resendEmailAddressVerificationCode &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); - send_closure(password_manager_, &PasswordManager::resend_email_address_verification_code, std::move(promise)); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(result.ok().get_email_address_authentication_code_info_object()); + } + }); + send_closure(password_manager_, &PasswordManager::resend_email_address_verification_code, std::move(query_promise)); } void Td::on_request(uint64 id, td_api::checkEmailAddressVerificationCode &request) { From 5e4a8ea66459325bc06fdd13409d137340bc30c1 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 16:08:10 +0300 Subject: [PATCH 088/200] Add authorizationStateWaitEmailCode. --- td/generate/scheme/td_api.tl | 6 +++++- td/telegram/AuthManager.cpp | 42 ++++++++++++++++++++++++++++++------ td/telegram/AuthManager.h | 24 +++++++++++++++++++-- td/telegram/AuthManager.hpp | 8 +++++++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 53f34bbd8..204235846 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -92,10 +92,14 @@ authorizationStateWaitEncryptionKey is_encrypted:Bool = AuthorizationState; //@description TDLib needs the user's phone number to authorize. Call `setAuthenticationPhoneNumber` to provide the phone number, or use `requestQrCodeAuthentication`, or `checkAuthenticationBotToken` for other authentication options authorizationStateWaitPhoneNumber = AuthorizationState; -//@description TDLib needs the user's email address to authorize. Call `setAuthenticationEmailAddress` to provide the email address, or directly call `setAuthenticationEmailCode` with Apple ID/Google ID token if allowed +//@description TDLib needs the user's email address to authorize. Call `setAuthenticationEmailAddress` to provide the email address, or directly call `checkAuthenticationEmailCode` with Apple ID/Google ID token if allowed //@allow_apple_id True, if authorization through Apple ID is allowed @allow_google_id True, if authorization through Google ID is allowed authorizationStateWaitEmailAddress allow_apple_id:Bool allow_google_id:Bool = AuthorizationState; +//@description TDLib needs the user's authentication code sent to an email address to authorize. Call `checkAuthenticationEmailCode` to provide the code +//@allow_apple_id True, if authorization through Apple ID is allowed @allow_google_id True, if authorization through Google ID is allowed @code_info Information about the sent authentication code +authorizationStateWaitEmailCode allow_apple_id:Bool allow_google_id:Bool code_info:emailAddressAuthenticationCodeInfo = AuthorizationState; + //@description TDLib needs the user's authentication code to authorize @code_info Information about the authorization code that was sent authorizationStateWaitCode code_info:authenticationCodeInfo = AuthorizationState; diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 46ce73db5..90f4eb8d9 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -109,6 +109,9 @@ tl_object_ptr AuthManager::get_authorization_state_o return make_tl_object(); case State::WaitEmailAddress: return make_tl_object(allow_apple_id_, allow_google_id_); + case State::WaitEmailCode: + return make_tl_object( + allow_apple_id_, allow_google_id_, email_code_.get_email_address_authentication_code_info_object()); case State::WaitCode: return send_code_helper_.get_authorization_state_wait_code(); case State::WaitQrCodeConfirmation: @@ -176,8 +179,8 @@ void AuthManager::check_bot_token(uint64 query_id, string bot_token) { void AuthManager::request_qr_code_authentication(uint64 query_id, vector other_user_ids) { if (state_ != State::WaitPhoneNumber) { - if ((state_ == State::WaitEmailAddress || state_ == State::WaitCode || state_ == State::WaitPassword || - state_ == State::WaitRegistration) && + if ((state_ == State::WaitEmailAddress || state_ == State::WaitEmailCode || state_ == State::WaitCode || + state_ == State::WaitPassword || state_ == State::WaitRegistration) && net_query_id_ == 0) { // ok } else { @@ -242,8 +245,8 @@ void AuthManager::on_update_login_token() { void AuthManager::set_phone_number(uint64 query_id, string phone_number, td_api::object_ptr settings) { if (state_ != State::WaitPhoneNumber) { - if ((state_ == State::WaitEmailAddress || state_ == State::WaitCode || state_ == State::WaitPassword || - state_ == State::WaitRegistration) && + if ((state_ == State::WaitEmailAddress || state_ == State::WaitEmailCode || state_ == State::WaitCode || + state_ == State::WaitPassword || state_ == State::WaitRegistration) && net_query_id_ == 0) { // ok } else { @@ -261,6 +264,11 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, other_user_ids_.clear(); was_qr_code_request_ = false; + allow_apple_id_ = false; + allow_google_id_ = false; + email_address_ = {}; + email_code_ = {}; + if (send_code_helper_.phone_number() != phone_number) { send_code_helper_ = SendCodeHelper(); terms_of_service_ = TermsOfService(); @@ -274,7 +282,11 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, void AuthManager::set_email_address(uint64 query_id, string email_address) { if (state_ != State::WaitEmailAddress) { - return on_query_error(query_id, Status::Error(400, "Call to setAuthenticationEmailAddress unexpected")); + if (state_ == State::WaitEmailCode && net_query_id_ == 0) { + // ok + } else { + return on_query_error(query_id, Status::Error(400, "Call to setAuthenticationEmailAddress unexpected")); + } } if (email_address.empty()) { return on_query_error(query_id, Status::Error(400, "Email address must be non-empty")); @@ -532,6 +544,12 @@ void AuthManager::on_send_email_code_result(NetQueryPtr &result) { LOG(INFO) << "Receive " << to_string(sent_code); + email_code_ = SentEmailCode(std::move(sent_code)); + if (email_code_.is_empty()) { + return on_query_error(Status::Error(500, "Receive invalid response")); + } + + update_state(State::WaitEmailCode, true); on_query_ok(); } @@ -1035,6 +1053,7 @@ bool AuthManager::load_state() { case State::WaitRegistration: return 86400; case State::WaitEmailAddress: + case State::WaitEmailCode: case State::WaitCode: case State::WaitQrCodeConfirmation: return 5 * 60; @@ -1054,6 +1073,12 @@ bool AuthManager::load_state() { allow_apple_id_ = db_state.allow_apple_id_; allow_google_id_ = db_state.allow_google_id_; send_code_helper_ = std::move(db_state.send_code_helper_); + } else if (db_state.state_ == State::WaitEmailCode) { + allow_apple_id_ = db_state.allow_apple_id_; + allow_google_id_ = db_state.allow_google_id_; + email_address_ = std::move(db_state.email_address_); + email_code_ = std::move(db_state.email_code_); + send_code_helper_ = std::move(db_state.send_code_helper_); } else if (db_state.state_ == State::WaitCode) { send_code_helper_ = std::move(db_state.send_code_helper_); } else if (db_state.state_ == State::WaitQrCodeConfirmation) { @@ -1073,8 +1098,8 @@ bool AuthManager::load_state() { } void AuthManager::save_state() { - if (state_ != State::WaitEmailAddress && state_ != State::WaitCode && state_ != State::WaitQrCodeConfirmation && - state_ != State::WaitPassword && state_ != State::WaitRegistration) { + if (state_ != State::WaitEmailAddress && state_ != State::WaitEmailCode && state_ != State::WaitCode && + state_ != State::WaitQrCodeConfirmation && state_ != State::WaitPassword && state_ != State::WaitRegistration) { if (state_ != State::Closing) { G()->td_db()->get_binlog_pmc()->erase("auth_state"); } @@ -1084,6 +1109,9 @@ void AuthManager::save_state() { DbState db_state = [&] { if (state_ == State::WaitEmailAddress) { return DbState::wait_email_address(api_id_, api_hash_, allow_apple_id_, allow_google_id_, send_code_helper_); + } else if (state_ == State::WaitEmailCode) { + return DbState::wait_email_code(api_id_, api_hash_, allow_apple_id_, allow_google_id_, email_address_, + email_code_, send_code_helper_); } else if (state_ == State::WaitCode) { return DbState::wait_code(api_id_, api_hash_, send_code_helper_); } else if (state_ == State::WaitQrCodeConfirmation) { diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 06b43c691..b9da53708 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -9,6 +9,7 @@ #include "td/telegram/net/NetActor.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/SendCodeHelper.h" +#include "td/telegram/SentEmailCode.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" #include "td/telegram/TermsOfService.h" @@ -67,6 +68,7 @@ class AuthManager final : public NetActor { WaitPassword, WaitRegistration, WaitEmailAddress, + WaitEmailCode, Ok, LoggingOut, DestroyingKeys, @@ -114,11 +116,15 @@ class AuthManager final : public NetActor { string api_hash_; Timestamp state_timestamp_; - // WaitEmailAddress + // WaitEmailAddress and WaitEmailCode bool allow_apple_id_ = false; bool allow_google_id_ = false; - // WaitEmailAddress and WaitCode + // WaitEmailCode + string email_address_; + SentEmailCode email_code_; + + // WaitEmailAddress, WaitEmailCode, WaitCode and WaitRegistration SendCodeHelper send_code_helper_; // WaitQrCodeConfirmation @@ -143,6 +149,17 @@ class AuthManager final : public NetActor { return state; } + static DbState wait_email_code(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id, + string email_address, SentEmailCode email_code, SendCodeHelper send_code_helper) { + DbState state(State::WaitEmailCode, api_id, std::move(api_hash)); + state.send_code_helper_ = std::move(send_code_helper); + state.allow_apple_id_ = allow_apple_id; + state.allow_google_id_ = allow_google_id; + state.email_address_ = std::move(email_address); + state.email_code_ = std::move(email_code); + return state; + } + static DbState wait_code(int32 api_id, string api_hash, SendCodeHelper send_code_helper) { DbState state(State::WaitCode, api_id, std::move(api_hash)); state.send_code_helper_ = std::move(send_code_helper); @@ -196,7 +213,10 @@ class AuthManager final : public NetActor { // State::WaitEmailAddress bool allow_apple_id_ = false; bool allow_google_id_ = false; + + // State::WaitEmailCode string email_address_; + SentEmailCode email_code_; // State::WaitCode SendCodeHelper send_code_helper_; diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp index 2548e9cfa..1ec3c79d7 100644 --- a/td/telegram/AuthManager.hpp +++ b/td/telegram/AuthManager.hpp @@ -76,6 +76,10 @@ void AuthManager::DbState::store(StorerT &storer) const { if (state_ == State::WaitEmailAddress) { store(send_code_helper_, storer); + } else if (state_ == State::WaitEmailCode) { + store(send_code_helper_, storer); + store(email_address_, storer); + store(email_code_, storer); } else if (state_ == State::WaitCode) { store(send_code_helper_, storer); } else if (state_ == State::WaitQrCodeConfirmation) { @@ -131,6 +135,10 @@ void AuthManager::DbState::parse(ParserT &parser) { if (state_ == State::WaitEmailAddress) { parse(send_code_helper_, parser); + } else if (state_ == State::WaitEmailCode) { + parse(send_code_helper_, parser); + parse(email_address_, parser); + parse(email_code_, parser); } else if (state_ == State::WaitCode) { parse(send_code_helper_, parser); } else if (state_ == State::WaitQrCodeConfirmation) { From 3a84a9c226aec9b41228f371da97f5000438f338 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 17:17:39 +0300 Subject: [PATCH 089/200] Add td_api::checkAuthenticationEmailCode. --- td/generate/scheme/td_api.tl | 15 ++++++ td/telegram/AuthManager.cpp | 90 ++++++++++++++++++++++++++++++++---- td/telegram/AuthManager.h | 8 ++++ td/telegram/SendCodeHelper.h | 4 +- td/telegram/Td.cpp | 6 +++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 10 ++++ 7 files changed, 123 insertions(+), 12 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 204235846..577d1c10d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -66,6 +66,18 @@ authenticationCodeInfo phone_number:string type:AuthenticationCodeType next_type emailAddressAuthenticationCodeInfo email_address_pattern:string length:int32 = EmailAddressAuthenticationCodeInfo; +//@class EmailAddressAuthentication @description Contains authentication data for a email address + +//@description An authentication code delivered to a user's email address @code The code +emailAddressAuthenticationCode code:string = EmailAddressAuthentication; + +//@description An authentication token received through Apple ID @token The token +emailAddressAuthenticationAppleId token:string = EmailAddressAuthentication; + +//@description An authentication token received through Google ID @token The token +emailAddressAuthenticationGoogleId token:string = EmailAddressAuthentication; + + //@description Represents a part of the text that needs to be formatted in some unusual way @offset Offset of the entity, in UTF-16 code units @length Length of the entity, in UTF-16 code units @type Type of the entity textEntity offset:int32 length:int32 type:TextEntityType = TextEntity; @@ -4625,6 +4637,9 @@ setAuthenticationEmailAddress email_address:string = Ok; //@description Re-sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed resendAuthenticationCode = Ok; +//@description Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode @code Email address authentication to check +checkAuthenticationEmailCode code:EmailAddressAuthentication = Ok; + //@description Checks the authentication code. Works only when the current authorization state is authorizationStateWaitCode @code Authentication code to check checkAuthenticationCode code:string = Ok; diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 90f4eb8d9..49c67eca4 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -315,6 +315,21 @@ void AuthManager::resend_authentication_code(uint64 query_id) { start_net_query(NetQueryType::SendCode, G()->net_query_creator().create_unauth(r_resend_code.move_as_ok())); } +void AuthManager::check_email_code(uint64 query_id, td_api::object_ptr &&code) { + if (code == nullptr) { + return on_query_error(query_id, Status::Error(400, "Code must be non-empty")); + } + if (state_ != State::WaitEmailCode && + !(state_ == State::WaitEmailAddress && code->get_id() == td_api::emailAddressAuthenticationCode::ID)) { + return on_query_error(query_id, Status::Error(400, "Call to checkAuthenticationEmailCode unexpected")); + } + + on_new_query(query_id); + start_net_query(NetQueryType::VerifyEmailAddress, + G()->net_query_creator().create_unauth(telegram_api::account_verifyEmail( + send_code_helper_.get_email_verify_purpose_login_setup(), get_input_email_verification(code)))); +} + void AuthManager::check_code(uint64 query_id, string code) { if (state_ != State::WaitCode) { return on_query_error(query_id, Status::Error(400, "Call to checkAuthenticationCode unexpected")); @@ -513,15 +528,7 @@ void AuthManager::start_net_query(NetQueryType net_query_type, NetQueryPtr net_q G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this)); } -void AuthManager::on_send_code_result(NetQueryPtr &result) { - auto r_sent_code = fetch_result(result->ok()); - if (r_sent_code.is_error()) { - return on_query_error(r_sent_code.move_as_error()); - } - auto sent_code = r_sent_code.move_as_ok(); - - LOG(INFO) << "Receive " << to_string(sent_code); - +void AuthManager::on_sent_code(telegram_api::object_ptr &&sent_code) { if (sent_code->type_->get_id() == telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID) { auto code_type = move_tl_object_as(std::move(sent_code->type_)); send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_)); @@ -532,6 +539,17 @@ void AuthManager::on_send_code_result(NetQueryPtr &result) { send_code_helper_.on_sent_code(std::move(sent_code)); update_state(State::WaitCode, true); } +} + +void AuthManager::on_send_code_result(NetQueryPtr &result) { + auto r_sent_code = fetch_result(result->ok()); + if (r_sent_code.is_error()) { + return on_query_error(r_sent_code.move_as_error()); + } + auto sent_code = r_sent_code.move_as_ok(); + + LOG(INFO) << "Receive " << to_string(sent_code); + on_sent_code(std::move(sent_code)); on_query_ok(); } @@ -553,6 +571,23 @@ void AuthManager::on_send_email_code_result(NetQueryPtr &result) { on_query_ok(); } +void AuthManager::on_verify_email_address_result(NetQueryPtr &result) { + auto r_email_verified = fetch_result(result->ok()); + if (r_email_verified.is_error()) { + return on_query_error(r_email_verified.move_as_error()); + } + auto email_verified = r_email_verified.move_as_ok(); + + LOG(INFO) << "Receive " << to_string(email_verified); + if (email_verified->get_id() != telegram_api::account_emailVerifiedLogin::ID) { + return on_query_error(Status::Error(500, "Receive invalid response")); + } + + auto verified_login = telegram_api::move_object_as(email_verified); + on_sent_code(std::move(verified_login->sent_code_)); + on_query_ok(); +} + void AuthManager::on_request_qr_code_result(NetQueryPtr &result, bool is_import) { Status status; if (result->is_ok()) { @@ -918,7 +953,8 @@ void AuthManager::on_result(NetQueryPtr result) { type = net_query_type_; net_query_type_ = NetQueryType::None; if (result->is_error()) { - if ((type == NetQueryType::SendCode || type == NetQueryType::SendEmailCode || type == NetQueryType::SignIn || + if ((type == NetQueryType::SendCode || type == NetQueryType::SendEmailCode || + type == NetQueryType::VerifyEmailAddress || type == NetQueryType::SignIn || type == NetQueryType::RequestQrCode || type == NetQueryType::ImportQrCode) && result->error().code() == 401 && result->error().message() == CSlice("SESSION_PASSWORD_NEEDED")) { auto dc_id = DcId::main(); @@ -977,6 +1013,9 @@ void AuthManager::on_result(NetQueryPtr result) { case NetQueryType::SendEmailCode: on_send_email_code_result(result); break; + case NetQueryType::VerifyEmailAddress: + on_verify_email_address_result(result); + break; case NetQueryType::RequestQrCode: on_request_qr_code_result(result, false); break; @@ -1127,4 +1166,35 @@ void AuthManager::save_state() { G()->td_db()->get_binlog_pmc()->set("auth_state", log_event_store(db_state).as_slice().str()); } +telegram_api::object_ptr AuthManager::get_input_email_verification( + const td_api::object_ptr &code) { + CHECK(code != nullptr); + switch (code->get_id()) { + case td_api::emailAddressAuthenticationCode::ID: { + auto token = static_cast(code.get())->code_; + if (!clean_input_string(token)) { + token.clear(); + } + return telegram_api::make_object(token); + } + case td_api::emailAddressAuthenticationAppleId::ID: { + auto token = static_cast(code.get())->token_; + if (!clean_input_string(token)) { + token.clear(); + } + return telegram_api::make_object(token); + } + case td_api::emailAddressAuthenticationGoogleId::ID: { + auto token = static_cast(code.get())->token_; + if (!clean_input_string(token)) { + token.clear(); + } + return telegram_api::make_object(token); + } + default: + UNREACHABLE(); + return nullptr; + } +} + } // namespace td diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index b9da53708..7fd9a0b69 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -38,6 +38,7 @@ class AuthManager final : public NetActor { td_api::object_ptr settings); void set_email_address(uint64 query_id, string email_address); void resend_authentication_code(uint64 query_id); + void check_email_code(uint64 query_id, td_api::object_ptr &&code); void check_code(uint64 query_id, string code); void register_user(uint64 query_id, string first_name, string last_name); void request_qr_code_authentication(uint64 query_id, vector other_user_ids); @@ -80,6 +81,7 @@ class AuthManager final : public NetActor { SignUp, SendCode, SendEmailCode, + VerifyEmailAddress, RequestQrCode, ImportQrCode, GetPassword, @@ -271,8 +273,11 @@ class AuthManager final : public NetActor { void send_log_out_query(); void destroy_auth_keys(); + void on_sent_code(telegram_api::object_ptr &&sent_code); + void on_send_code_result(NetQueryPtr &result); void on_send_email_code_result(NetQueryPtr &result); + void on_verify_email_address_result(NetQueryPtr &result); void on_request_qr_code_result(NetQueryPtr &result, bool is_import); void on_get_password_result(NetQueryPtr &result); void on_request_password_recovery_result(NetQueryPtr &result); @@ -291,6 +296,9 @@ class AuthManager final : public NetActor { static void send_ok(uint64 query_id); static void on_query_error(uint64 query_id, Status status); + static telegram_api::object_ptr get_input_email_verification( + const td_api::object_ptr &code); + void start_up() final; void tear_down() final; }; diff --git a/td/telegram/SendCodeHelper.h b/td/telegram/SendCodeHelper.h index bae0cc45d..6ace7fad4 100644 --- a/td/telegram/SendCodeHelper.h +++ b/td/telegram/SendCodeHelper.h @@ -42,6 +42,8 @@ class SendCodeHelper { telegram_api::account_sendConfirmPhoneCode send_confirm_phone_code(const string &hash, Slice phone_number, const Settings &settings); + telegram_api::object_ptr get_email_verify_purpose_login_setup() const; + Slice phone_number() const { return phone_number_; } @@ -92,8 +94,6 @@ class SendCodeHelper { const AuthenticationCodeInfo &authentication_code_info); static telegram_api::object_ptr get_input_code_settings(const Settings &settings); - - telegram_api::object_ptr get_email_verify_purpose_login_setup() const; }; } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 93c96311e..f0a59d9a1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2781,7 +2781,9 @@ bool Td::is_authentication_request(int32 id) { case td_api::setDatabaseEncryptionKey::ID: case td_api::getAuthorizationState::ID: case td_api::setAuthenticationPhoneNumber::ID: + case td_api::setAuthenticationEmailAddress::ID: case td_api::resendAuthenticationCode::ID: + case td_api::checkAuthenticationEmailCode::ID: case td_api::checkAuthenticationCode::ID: case td_api::registerUser::ID: case td_api::requestQrCodeAuthentication::ID: @@ -4271,6 +4273,10 @@ void Td::on_request(uint64 id, const td_api::resendAuthenticationCode &request) send_closure(auth_manager_actor_, &AuthManager::resend_authentication_code, id); } +void Td::on_request(uint64 id, td_api::checkAuthenticationEmailCode &request) { + send_closure(auth_manager_actor_, &AuthManager::check_email_code, id, std::move(request.code_)); +} + void Td::on_request(uint64 id, td_api::checkAuthenticationCode &request) { CLEAN_INPUT_STRING(request.code_); send_closure(auth_manager_actor_, &AuthManager::check_code, id, std::move(request.code_)); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 57375315c..9b187add6 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -402,6 +402,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::resendAuthenticationCode &request); + void on_request(uint64 id, td_api::checkAuthenticationEmailCode &request); + void on_request(uint64 id, td_api::checkAuthenticationCode &request); void on_request(uint64 id, td_api::registerUser &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index bfeb46937..fa42fa7e0 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1850,6 +1850,16 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "sdek" || op == "SetDatabaseEncryptionKey") { send_request(td_api::make_object(args)); + } else if (op == "caec") { + td_api::object_ptr code; + if (begins_with(args, "a ")) { + code = td_api::make_object(args.substr(2)); + } else if (begins_with(args, "g ")) { + code = td_api::make_object(args.substr(2)); + } else if (!args.empty()) { + code = td_api::make_object(args); + } + send_request(td_api::make_object(std::move(code))); } else if (op == "cac") { send_request(td_api::make_object(args)); } else if (op == "ru") { From cba73d5bba923b42ed037d51b725a3720349891d Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 17:42:19 +0300 Subject: [PATCH 090/200] Support login with email verification. --- td/telegram/AuthManager.cpp | 65 ++++++++++++++++++++++++---------- td/telegram/AuthManager.h | 11 +++--- td/telegram/AuthManager.hpp | 4 +-- td/telegram/SendCodeHelper.cpp | 5 +-- 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 49c67eca4..7bc6ee954 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -111,7 +111,7 @@ tl_object_ptr AuthManager::get_authorization_state_o return make_tl_object(allow_apple_id_, allow_google_id_); case State::WaitEmailCode: return make_tl_object( - allow_apple_id_, allow_google_id_, email_code_.get_email_address_authentication_code_info_object()); + allow_apple_id_, allow_google_id_, email_code_info_.get_email_address_authentication_code_info_object()); case State::WaitCode: return send_code_helper_.get_authorization_state_wait_code(); case State::WaitQrCodeConfirmation: @@ -267,7 +267,9 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, allow_apple_id_ = false; allow_google_id_ = false; email_address_ = {}; - email_code_ = {}; + email_code_info_ = {}; + code_ = string(); + email_code_ = nullptr; if (send_code_helper_.phone_number() != phone_number) { send_code_helper_ = SendCodeHelper(); @@ -315,6 +317,16 @@ void AuthManager::resend_authentication_code(uint64 query_id) { start_net_query(NetQueryType::SendCode, G()->net_query_creator().create_unauth(r_resend_code.move_as_ok())); } +void AuthManager::send_auth_sign_in_query() { + bool is_email = email_code_ != nullptr; + int32 flags = + is_email ? telegram_api::auth_signIn::EMAIL_VERIFICATION_MASK : telegram_api::auth_signIn::PHONE_CODE_MASK; + start_net_query(NetQueryType::SignIn, + G()->net_query_creator().create_unauth(telegram_api::auth_signIn( + flags, send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_, + is_email ? get_input_email_verification(email_code_) : nullptr))); +} + void AuthManager::check_email_code(uint64 query_id, td_api::object_ptr &&code) { if (code == nullptr) { return on_query_error(query_id, Status::Error(400, "Code must be non-empty")); @@ -324,10 +336,18 @@ void AuthManager::check_email_code(uint64 query_id, td_api::object_ptrnet_query_creator().create_unauth(telegram_api::account_verifyEmail( - send_code_helper_.get_email_verify_purpose_login_setup(), get_input_email_verification(code)))); + if (email_address_.empty()) { + send_auth_sign_in_query(); + } else { + start_net_query( + NetQueryType::VerifyEmailAddress, + G()->net_query_creator().create_unauth(telegram_api::account_verifyEmail( + send_code_helper_.get_email_verify_purpose_login_setup(), get_input_email_verification(email_code_)))); + } } void AuthManager::check_code(uint64 query_id, string code) { @@ -336,11 +356,10 @@ void AuthManager::check_code(uint64 query_id, string code) { } code_ = std::move(code); - int32 flags = telegram_api::auth_signIn::PHONE_CODE_MASK; + email_code_ = nullptr; + on_new_query(query_id); - start_net_query(NetQueryType::SignIn, G()->net_query_creator().create_unauth(telegram_api::auth_signIn( - flags, send_code_helper_.phone_number().str(), - send_code_helper_.phone_code_hash().str(), code_, nullptr))); + send_auth_sign_in_query(); } void AuthManager::register_user(uint64 query_id, string first_name, string last_name) { @@ -529,12 +548,25 @@ void AuthManager::start_net_query(NetQueryType net_query_type, NetQueryPtr net_q } void AuthManager::on_sent_code(telegram_api::object_ptr &&sent_code) { - if (sent_code->type_->get_id() == telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID) { + auto code_type_id = sent_code->type_->get_id(); + if (code_type_id == telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID) { auto code_type = move_tl_object_as(std::move(sent_code->type_)); send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_)); allow_apple_id_ = code_type->apple_signin_allowed_; allow_google_id_ = code_type->google_signin_allowed_; update_state(State::WaitEmailAddress, true); + } else if (code_type_id == telegram_api::auth_sentCodeTypeEmailCode::ID) { + auto code_type = move_tl_object_as(std::move(sent_code->type_)); + send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_)); + allow_apple_id_ = code_type->apple_signin_allowed_; + allow_google_id_ = code_type->google_signin_allowed_; + email_address_.clear(); + email_code_info_ = SentEmailCode(std::move(code_type->email_pattern_), code_type->length_); + if (email_code_info_.is_empty()) { + email_code_info_ = SentEmailCode("", code_type->length_); + CHECK(!email_code_info_.is_empty()); + } + update_state(State::WaitEmailCode, true); } else { send_code_helper_.on_sent_code(std::move(sent_code)); update_state(State::WaitCode, true); @@ -562,8 +594,8 @@ void AuthManager::on_send_email_code_result(NetQueryPtr &result) { LOG(INFO) << "Receive " << to_string(sent_code); - email_code_ = SentEmailCode(std::move(sent_code)); - if (email_code_.is_empty()) { + email_code_info_ = SentEmailCode(std::move(sent_code)); + if (email_code_info_.is_empty()) { return on_query_error(Status::Error(500, "Receive invalid response")); } @@ -710,10 +742,7 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) { set_login_token_expires_at(Time::now() + login_code_retry_delay_); return; } else { - int32 flags = telegram_api::auth_signIn::PHONE_CODE_MASK; - start_net_query(NetQueryType::SignIn, G()->net_query_creator().create_unauth(telegram_api::auth_signIn( - flags, send_code_helper_.phone_number().str(), - send_code_helper_.phone_code_hash().str(), code_, nullptr))); + send_auth_sign_in_query(); return; } @@ -1116,7 +1145,7 @@ bool AuthManager::load_state() { allow_apple_id_ = db_state.allow_apple_id_; allow_google_id_ = db_state.allow_google_id_; email_address_ = std::move(db_state.email_address_); - email_code_ = std::move(db_state.email_code_); + email_code_info_ = std::move(db_state.email_code_info_); send_code_helper_ = std::move(db_state.send_code_helper_); } else if (db_state.state_ == State::WaitCode) { send_code_helper_ = std::move(db_state.send_code_helper_); @@ -1150,7 +1179,7 @@ void AuthManager::save_state() { return DbState::wait_email_address(api_id_, api_hash_, allow_apple_id_, allow_google_id_, send_code_helper_); } else if (state_ == State::WaitEmailCode) { return DbState::wait_email_code(api_id_, api_hash_, allow_apple_id_, allow_google_id_, email_address_, - email_code_, send_code_helper_); + email_code_info_, send_code_helper_); } else if (state_ == State::WaitCode) { return DbState::wait_code(api_id_, api_hash_, send_code_helper_); } else if (state_ == State::WaitQrCodeConfirmation) { diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 7fd9a0b69..9d0aab0ef 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -124,7 +124,7 @@ class AuthManager final : public NetActor { // WaitEmailCode string email_address_; - SentEmailCode email_code_; + SentEmailCode email_code_info_; // WaitEmailAddress, WaitEmailCode, WaitCode and WaitRegistration SendCodeHelper send_code_helper_; @@ -152,13 +152,14 @@ class AuthManager final : public NetActor { } static DbState wait_email_code(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id, - string email_address, SentEmailCode email_code, SendCodeHelper send_code_helper) { + string email_address, SentEmailCode email_code_info, + SendCodeHelper send_code_helper) { DbState state(State::WaitEmailCode, api_id, std::move(api_hash)); state.send_code_helper_ = std::move(send_code_helper); state.allow_apple_id_ = allow_apple_id; state.allow_google_id_ = allow_google_id; state.email_address_ = std::move(email_address); - state.email_code_ = std::move(email_code); + state.email_code_info_ = std::move(email_code_info); return state; } @@ -218,7 +219,8 @@ class AuthManager final : public NetActor { // State::WaitEmailCode string email_address_; - SentEmailCode email_code_; + SentEmailCode email_code_info_; + td_api::object_ptr email_code_; // State::WaitCode SendCodeHelper send_code_helper_; @@ -270,6 +272,7 @@ class AuthManager final : public NetActor { void do_delete_account(uint64 query_id, string reason, Result> r_input_password); + void send_auth_sign_in_query(); void send_log_out_query(); void destroy_auth_keys(); diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp index 1ec3c79d7..ed4ae7ff7 100644 --- a/td/telegram/AuthManager.hpp +++ b/td/telegram/AuthManager.hpp @@ -79,7 +79,7 @@ void AuthManager::DbState::store(StorerT &storer) const { } else if (state_ == State::WaitEmailCode) { store(send_code_helper_, storer); store(email_address_, storer); - store(email_code_, storer); + store(email_code_info_, storer); } else if (state_ == State::WaitCode) { store(send_code_helper_, storer); } else if (state_ == State::WaitQrCodeConfirmation) { @@ -138,7 +138,7 @@ void AuthManager::DbState::parse(ParserT &parser) { } else if (state_ == State::WaitEmailCode) { parse(send_code_helper_, parser); parse(email_address_, parser); - parse(email_code_, parser); + parse(email_code_info_, parser); } else if (state_ == State::WaitCode) { parse(send_code_helper_, parser); } else if (state_ == State::WaitQrCodeConfirmation) { diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index f8636e835..993268f05 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -149,10 +149,7 @@ SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_i return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::MissedCall, code_type->length_, std::move(code_type->prefix_)}; } - case telegram_api::auth_sentCodeTypeEmailCode::ID: { - auto code_type = move_tl_object_as(sent_code_type_ptr); - return AuthenticationCodeInfo{AuthenticationCodeInfo::Type::Message, code_type->length_, ""}; - } + case telegram_api::auth_sentCodeTypeEmailCode::ID: case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: return AuthenticationCodeInfo(); default: From 8f161911829b56a3f1f8577b9b4c78e308d6b302 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 18:15:43 +0300 Subject: [PATCH 091/200] Add authorizationStateWaitEmailCode.next_phone_number_authorization_date. --- td/generate/scheme/td_api.tl | 6 ++++-- td/telegram/AuthManager.cpp | 9 +++++++-- td/telegram/AuthManager.h | 5 ++++- td/telegram/AuthManager.hpp | 2 ++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 577d1c10d..b2f4da9ac 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -109,8 +109,10 @@ authorizationStateWaitPhoneNumber = AuthorizationState; authorizationStateWaitEmailAddress allow_apple_id:Bool allow_google_id:Bool = AuthorizationState; //@description TDLib needs the user's authentication code sent to an email address to authorize. Call `checkAuthenticationEmailCode` to provide the code -//@allow_apple_id True, if authorization through Apple ID is allowed @allow_google_id True, if authorization through Google ID is allowed @code_info Information about the sent authentication code -authorizationStateWaitEmailCode allow_apple_id:Bool allow_google_id:Bool code_info:emailAddressAuthenticationCodeInfo = AuthorizationState; +//@allow_apple_id True, if authorization through Apple ID is allowed @allow_google_id True, if authorization through Google ID is allowed +//@code_info Information about the sent authentication code +//@next_phone_number_authorization_date Point in time (Unix timestamp) when the user will be able to authorize with a code sent to the user's phone number; 0 if unknown +authorizationStateWaitEmailCode allow_apple_id:Bool allow_google_id:Bool code_info:emailAddressAuthenticationCodeInfo next_phone_number_authorization_date:int32 = AuthorizationState; //@description TDLib needs the user's authentication code to authorize @code_info Information about the authorization code that was sent authorizationStateWaitCode code_info:authenticationCodeInfo = AuthorizationState; diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 7bc6ee954..40b0a8e47 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -111,7 +111,8 @@ tl_object_ptr AuthManager::get_authorization_state_o return make_tl_object(allow_apple_id_, allow_google_id_); case State::WaitEmailCode: return make_tl_object( - allow_apple_id_, allow_google_id_, email_code_info_.get_email_address_authentication_code_info_object()); + allow_apple_id_, allow_google_id_, email_code_info_.get_email_address_authentication_code_info_object(), + next_phone_number_login_date_); case State::WaitCode: return send_code_helper_.get_authorization_state_wait_code(); case State::WaitQrCodeConfirmation: @@ -268,6 +269,7 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, allow_google_id_ = false; email_address_ = {}; email_code_info_ = {}; + next_phone_number_login_date_ = 0; code_ = string(); email_code_ = nullptr; @@ -562,6 +564,7 @@ void AuthManager::on_sent_code(telegram_api::object_ptrgoogle_signin_allowed_; email_address_.clear(); email_code_info_ = SentEmailCode(std::move(code_type->email_pattern_), code_type->length_); + next_phone_number_login_date_ = td::max(static_cast(0), code_type->next_phone_login_date_); if (email_code_info_.is_empty()) { email_code_info_ = SentEmailCode("", code_type->length_); CHECK(!email_code_info_.is_empty()); @@ -598,6 +601,7 @@ void AuthManager::on_send_email_code_result(NetQueryPtr &result) { if (email_code_info_.is_empty()) { return on_query_error(Status::Error(500, "Receive invalid response")); } + next_phone_number_login_date_ = 0; update_state(State::WaitEmailCode, true); on_query_ok(); @@ -1146,6 +1150,7 @@ bool AuthManager::load_state() { allow_google_id_ = db_state.allow_google_id_; email_address_ = std::move(db_state.email_address_); email_code_info_ = std::move(db_state.email_code_info_); + next_phone_number_login_date_ = db_state.next_phone_number_login_date_; send_code_helper_ = std::move(db_state.send_code_helper_); } else if (db_state.state_ == State::WaitCode) { send_code_helper_ = std::move(db_state.send_code_helper_); @@ -1179,7 +1184,7 @@ void AuthManager::save_state() { return DbState::wait_email_address(api_id_, api_hash_, allow_apple_id_, allow_google_id_, send_code_helper_); } else if (state_ == State::WaitEmailCode) { return DbState::wait_email_code(api_id_, api_hash_, allow_apple_id_, allow_google_id_, email_address_, - email_code_info_, send_code_helper_); + email_code_info_, next_phone_number_login_date_, send_code_helper_); } else if (state_ == State::WaitCode) { return DbState::wait_code(api_id_, api_hash_, send_code_helper_); } else if (state_ == State::WaitQrCodeConfirmation) { diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 9d0aab0ef..b218c4def 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -125,6 +125,7 @@ class AuthManager final : public NetActor { // WaitEmailCode string email_address_; SentEmailCode email_code_info_; + int32 next_phone_number_login_date_ = 0; // WaitEmailAddress, WaitEmailCode, WaitCode and WaitRegistration SendCodeHelper send_code_helper_; @@ -153,13 +154,14 @@ class AuthManager final : public NetActor { static DbState wait_email_code(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id, string email_address, SentEmailCode email_code_info, - SendCodeHelper send_code_helper) { + int32 next_phone_number_login_date, SendCodeHelper send_code_helper) { DbState state(State::WaitEmailCode, api_id, std::move(api_hash)); state.send_code_helper_ = std::move(send_code_helper); state.allow_apple_id_ = allow_apple_id; state.allow_google_id_ = allow_google_id; state.email_address_ = std::move(email_address); state.email_code_info_ = std::move(email_code_info); + state.next_phone_number_login_date_ = next_phone_number_login_date; return state; } @@ -220,6 +222,7 @@ class AuthManager final : public NetActor { // State::WaitEmailCode string email_address_; SentEmailCode email_code_info_; + int32 next_phone_number_login_date_ = 0; td_api::object_ptr email_code_; // State::WaitCode diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp index ed4ae7ff7..15e6cb393 100644 --- a/td/telegram/AuthManager.hpp +++ b/td/telegram/AuthManager.hpp @@ -80,6 +80,7 @@ void AuthManager::DbState::store(StorerT &storer) const { store(send_code_helper_, storer); store(email_address_, storer); store(email_code_info_, storer); + store(next_phone_number_login_date_, storer); } else if (state_ == State::WaitCode) { store(send_code_helper_, storer); } else if (state_ == State::WaitQrCodeConfirmation) { @@ -139,6 +140,7 @@ void AuthManager::DbState::parse(ParserT &parser) { parse(send_code_helper_, parser); parse(email_address_, parser); parse(email_code_info_, parser); + parse(next_phone_number_login_date_, parser); } else if (state_ == State::WaitCode) { parse(send_code_helper_, parser); } else if (state_ == State::WaitQrCodeConfirmation) { From 886a6125e98fa83a0205e96f86b8e4abbd36bf9c Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 23:29:57 +0300 Subject: [PATCH 092/200] Add class EmailVerification. --- CMakeLists.txt | 2 ++ td/telegram/AuthManager.cpp | 48 +++++----------------------- td/telegram/AuthManager.h | 8 ++--- td/telegram/EmailVerification.cpp | 53 +++++++++++++++++++++++++++++++ td/telegram/EmailVerification.h | 37 +++++++++++++++++++++ td/telegram/Td.cpp | 2 +- 6 files changed, 104 insertions(+), 46 deletions(-) create mode 100644 td/telegram/EmailVerification.cpp create mode 100644 td/telegram/EmailVerification.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f755cfb8..218012006 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ set(TDLIB_SOURCE td/telegram/DownloadManager.cpp td/telegram/DownloadManagerCallback.cpp td/telegram/DraftMessage.cpp + td/telegram/EmailVerification.cpp td/telegram/EmojiStatus.cpp td/telegram/FileReferenceManager.cpp td/telegram/files/FileBitmask.cpp @@ -541,6 +542,7 @@ set(TDLIB_SOURCE td/telegram/DownloadManager.h td/telegram/DownloadManagerCallback.h td/telegram/DraftMessage.h + td/telegram/EmailVerification.h td/telegram/EmojiStatus.h td/telegram/EncryptedFile.h td/telegram/FileReferenceManager.h diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 40b0a8e47..eabd2e4ab 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -271,7 +271,7 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number, email_code_info_ = {}; next_phone_number_login_date_ = 0; code_ = string(); - email_code_ = nullptr; + email_code_ = {}; if (send_code_helper_.phone_number() != phone_number) { send_code_helper_ = SendCodeHelper(); @@ -320,21 +320,20 @@ void AuthManager::resend_authentication_code(uint64 query_id) { } void AuthManager::send_auth_sign_in_query() { - bool is_email = email_code_ != nullptr; + bool is_email = !email_code_.is_empty(); int32 flags = is_email ? telegram_api::auth_signIn::EMAIL_VERIFICATION_MASK : telegram_api::auth_signIn::PHONE_CODE_MASK; start_net_query(NetQueryType::SignIn, G()->net_query_creator().create_unauth(telegram_api::auth_signIn( flags, send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_, - is_email ? get_input_email_verification(email_code_) : nullptr))); + is_email ? email_code_.get_input_email_verification() : nullptr))); } -void AuthManager::check_email_code(uint64 query_id, td_api::object_ptr &&code) { - if (code == nullptr) { +void AuthManager::check_email_code(uint64 query_id, EmailVerification &&code) { + if (code.is_empty()) { return on_query_error(query_id, Status::Error(400, "Code must be non-empty")); } - if (state_ != State::WaitEmailCode && - !(state_ == State::WaitEmailAddress && code->get_id() == td_api::emailAddressAuthenticationCode::ID)) { + if (state_ != State::WaitEmailCode && !(state_ == State::WaitEmailAddress && code.is_email_code())) { return on_query_error(query_id, Status::Error(400, "Call to checkAuthenticationEmailCode unexpected")); } @@ -348,7 +347,7 @@ void AuthManager::check_email_code(uint64 query_id, td_api::object_ptrnet_query_creator().create_unauth(telegram_api::account_verifyEmail( - send_code_helper_.get_email_verify_purpose_login_setup(), get_input_email_verification(email_code_)))); + send_code_helper_.get_email_verify_purpose_login_setup(), email_code_.get_input_email_verification()))); } } @@ -358,7 +357,7 @@ void AuthManager::check_code(uint64 query_id, string code) { } code_ = std::move(code); - email_code_ = nullptr; + email_code_ = {}; on_new_query(query_id); send_auth_sign_in_query(); @@ -1200,35 +1199,4 @@ void AuthManager::save_state() { G()->td_db()->get_binlog_pmc()->set("auth_state", log_event_store(db_state).as_slice().str()); } -telegram_api::object_ptr AuthManager::get_input_email_verification( - const td_api::object_ptr &code) { - CHECK(code != nullptr); - switch (code->get_id()) { - case td_api::emailAddressAuthenticationCode::ID: { - auto token = static_cast(code.get())->code_; - if (!clean_input_string(token)) { - token.clear(); - } - return telegram_api::make_object(token); - } - case td_api::emailAddressAuthenticationAppleId::ID: { - auto token = static_cast(code.get())->token_; - if (!clean_input_string(token)) { - token.clear(); - } - return telegram_api::make_object(token); - } - case td_api::emailAddressAuthenticationGoogleId::ID: { - auto token = static_cast(code.get())->token_; - if (!clean_input_string(token)) { - token.clear(); - } - return telegram_api::make_object(token); - } - default: - UNREACHABLE(); - return nullptr; - } -} - } // namespace td diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index b218c4def..d6aeef3c3 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/EmailVerification.h" #include "td/telegram/net/NetActor.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/SendCodeHelper.h" @@ -38,7 +39,7 @@ class AuthManager final : public NetActor { td_api::object_ptr settings); void set_email_address(uint64 query_id, string email_address); void resend_authentication_code(uint64 query_id); - void check_email_code(uint64 query_id, td_api::object_ptr &&code); + void check_email_code(uint64 query_id, EmailVerification &&code); void check_code(uint64 query_id, string code); void register_user(uint64 query_id, string first_name, string last_name); void request_qr_code_authentication(uint64 query_id, vector other_user_ids); @@ -223,7 +224,7 @@ class AuthManager final : public NetActor { string email_address_; SentEmailCode email_code_info_; int32 next_phone_number_login_date_ = 0; - td_api::object_ptr email_code_; + EmailVerification email_code_; // State::WaitCode SendCodeHelper send_code_helper_; @@ -302,9 +303,6 @@ class AuthManager final : public NetActor { static void send_ok(uint64 query_id); static void on_query_error(uint64 query_id, Status status); - static telegram_api::object_ptr get_input_email_verification( - const td_api::object_ptr &code); - void start_up() final; void tear_down() final; }; diff --git a/td/telegram/EmailVerification.cpp b/td/telegram/EmailVerification.cpp new file mode 100644 index 000000000..234190a02 --- /dev/null +++ b/td/telegram/EmailVerification.cpp @@ -0,0 +1,53 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/EmailVerification.h" + +#include "td/telegram/misc.h" + +namespace td { + +EmailVerification::EmailVerification(td_api::object_ptr &&code) { + if (code == nullptr) { + return; + } + switch (code->get_id()) { + case td_api::emailAddressAuthenticationCode::ID: + type_ = Type::Code; + code_ = static_cast(code.get())->code_; + break; + case td_api::emailAddressAuthenticationAppleId::ID: + type_ = Type::Apple; + code_ = static_cast(code.get())->token_; + break; + case td_api::emailAddressAuthenticationGoogleId::ID: + type_ = Type::Google; + code_ = static_cast(code.get())->token_; + break; + default: + UNREACHABLE(); + break; + } + if (!clean_input_string(code_)) { + *this = {}; + } +} + +telegram_api::object_ptr EmailVerification::get_input_email_verification() const { + switch (type_) { + case Type::Code: + return telegram_api::make_object(code_); + case Type::Apple: + return telegram_api::make_object(code_); + case Type::Google: + return telegram_api::make_object(code_); + default: + UNREACHABLE(); + return nullptr; + } +} + +} // namespace td diff --git a/td/telegram/EmailVerification.h b/td/telegram/EmailVerification.h new file mode 100644 index 000000000..abd4d8ed3 --- /dev/null +++ b/td/telegram/EmailVerification.h @@ -0,0 +1,37 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" + +namespace td { + +class EmailVerification { + enum class Type : int32 { None, Code, Apple, Google }; + Type type_ = Type::None; + string code_; + + public: + EmailVerification() = default; + + explicit EmailVerification(td_api::object_ptr &&code); + + telegram_api::object_ptr get_input_email_verification() const; + + bool is_empty() const { + return type_ == Type::None; + } + + bool is_email_code() const { + return type_ == Type::Code; + } +}; + +} // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f0a59d9a1..88b289db7 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4274,7 +4274,7 @@ void Td::on_request(uint64 id, const td_api::resendAuthenticationCode &request) } void Td::on_request(uint64 id, td_api::checkAuthenticationEmailCode &request) { - send_closure(auth_manager_actor_, &AuthManager::check_email_code, id, std::move(request.code_)); + send_closure(auth_manager_actor_, &AuthManager::check_email_code, id, EmailVerification(std::move(request.code_))); } void Td::on_request(uint64 id, td_api::checkAuthenticationCode &request) { From b8438b92ae1bb8305560d3f7e3f143a1ae4daeab Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 6 Sep 2022 23:47:11 +0300 Subject: [PATCH 093/200] Add td_api::premiumFeatureEmojiStatus. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/Premium.cpp | 21 +++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b2f4da9ac..4e3278605 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3059,6 +3059,9 @@ premiumFeatureAdvancedChatManagement = PremiumFeature; //@description A badge in the user's profile premiumFeatureProfileBadge = PremiumFeature; +//@description A emoji status shown along with the user's name +premiumFeatureEmojiStatus = PremiumFeature; + //@description Profile photo animation on message and chat screens premiumFeatureAnimatedProfilePhoto = PremiumFeature; diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index d42ce777a..170aaefec 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -45,7 +45,7 @@ static td_api::object_ptr get_premium_feature_object(Sli if (premium_feature == "no_ads") { return td_api::make_object(); } - if (premium_feature == "unique_reactions") { + if (premium_feature == "unique_reactions" || premium_feature == "infinite_reactions") { return td_api::make_object(); } if (premium_feature == "premium_stickers") { @@ -60,6 +60,9 @@ static td_api::object_ptr get_premium_feature_object(Sli if (premium_feature == "profile_badge") { return td_api::make_object(); } + if (premium_feature == "emoji_status") { + return td_api::make_object(); + } if (premium_feature == "animated_userpics") { return td_api::make_object(); } @@ -342,7 +345,7 @@ static string get_premium_source(const td_api::PremiumFeature *feature) { case td_api::premiumFeatureDisabledAds::ID: return "no_ads"; case td_api::premiumFeatureUniqueReactions::ID: - return "unique_reactions"; + return "infinite_reactions"; case td_api::premiumFeatureUniqueStickers::ID: return "premium_stickers"; case td_api::premiumFeatureCustomEmoji::ID: @@ -351,6 +354,8 @@ static string get_premium_source(const td_api::PremiumFeature *feature) { return "advanced_chat_management"; case td_api::premiumFeatureProfileBadge::ID: return "profile_badge"; + case td_api::premiumFeatureEmojiStatus::ID: + return "emoji_status"; case td_api::premiumFeatureAnimatedProfilePhoto::ID: return "animated_userpics"; case td_api::premiumFeatureAppIcons::ID: @@ -443,12 +448,12 @@ void get_premium_limit(const td_api::object_ptr &limit void get_premium_features(Td *td, const td_api::object_ptr &source, Promise> &&promise) { - auto premium_features = - full_split(G()->get_option_string( - "premium_features", - "double_limits,more_upload,faster_download,voice_to_text,no_ads,unique_reactions,premium_stickers," - "animated_emoji,advanced_chat_management,profile_badge,animated_userpics,app_icons"), - ','); + auto premium_features = full_split( + G()->get_option_string( + "premium_features", + "double_limits,more_upload,faster_download,voice_to_text,no_ads,infinite_reactions,premium_stickers," + "animated_emoji,advanced_chat_management,profile_badge,emoji_status,animated_userpics,app_icons"), + ','); vector> features; for (const auto &premium_feature : premium_features) { auto feature = get_premium_feature_object(premium_feature); From 14a9fda4ef113aef1e039826ad481a4761abaf8f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 10:25:21 +0300 Subject: [PATCH 094/200] Rename premiumStatus to emojiStatus. --- td/generate/scheme/td_api.tl | 34 +++++++++++------------ td/telegram/ConfigManager.cpp | 2 +- td/telegram/ContactsManager.cpp | 10 +++---- td/telegram/EmojiStatus.cpp | 48 ++++++++++++++++----------------- td/telegram/EmojiStatus.h | 8 +++--- td/telegram/OptionManager.cpp | 4 +-- td/telegram/StickersManager.cpp | 10 +++---- td/telegram/StickersManager.h | 2 +- td/telegram/Td.cpp | 12 ++++----- td/telegram/Td.h | 10 +++---- td/telegram/cli.cpp | 28 +++++++++---------- 11 files changed, 84 insertions(+), 84 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 4e3278605..42a78f5d1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -497,11 +497,11 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa //@payment_link An internal link to be opened for buying Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available premiumPaymentOption currency:string amount:int53 discount_percentage:int32 month_count:int32 store_product_id:string payment_link:InternalLinkType = PremiumPaymentOption; -//@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format. If the custom emoji belongs to the sticker set GetOption("themed_premium_statuses_sticker_set_id"), then it's color must be changed to the color of the Telegram Premium badge -premiumStatus custom_emoji_id:int64 = PremiumStatus; +//@description Describes a custom emoji to be shown instead of the Telegram Premium badge @custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format. If the custom emoji belongs to the sticker set GetOption("themed_emoji_statuses_sticker_set_id"), then it's color must be changed to the color of the Telegram Premium badge +emojiStatus custom_emoji_id:int64 = EmojiStatus; -//@description Contains a list of premium statuses @premium_statuses The list of premium statuses -premiumStatuses premium_statuses:vector = PremiumStatuses; +//@description Contains a list of emoji statuses @emoji_statuses The list of emoji statuses +emojiStatuses emoji_statuses:vector = EmojiStatuses; //@description Represents a user @@ -512,7 +512,7 @@ premiumStatuses premium_statuses:vector = PremiumStatuses; //@phone_number Phone number of the user //@status Current online status of the user //@profile_photo Profile photo of the user; may be null -//@premium_status Premium status to be shown instead of the default Telegram Premium badge; may be null. For Telegram Premium users only +//@emoji_status Emoji status to be shown instead of the default Telegram Premium badge; may be null. For Telegram Premium users only //@is_contact The user is a contact of the current user //@is_mutual_contact The user is a contact of the current user and the current user is a contact of the user //@is_verified True, if the user is verified @@ -525,7 +525,7 @@ premiumStatuses premium_statuses:vector = PremiumStatuses; //@type Type of the user //@language_code IETF language tag of the user's language; only available to bots //@added_to_attachment_menu True, if the user added the current bot to attachment menu; only available to bots -user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto premium_status:premiumStatus is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; +user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto emoji_status:emojiStatus is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; //@description Contains information about a bot @@ -5608,17 +5608,17 @@ getAttachmentMenuBot bot_user_id:int53 = AttachmentMenuBot; toggleBotIsAddedToAttachmentMenu bot_user_id:int53 is_added:Bool = Ok; -//@description Returns up to 8 themed premium statuses, which color must be changed to the color of the Telegram Premium badge -getThemedPremiumStatuses = PremiumStatuses; +//@description Returns up to 8 themed emoji statuses, which color must be changed to the color of the Telegram Premium badge +getThemedEmojiStatuses = EmojiStatuses; -//@description Returns recent premium statuses -getRecentPremiumStatuses = PremiumStatuses; +//@description Returns recent emoji statuses +getRecentEmojiStatuses = EmojiStatuses; -//@description Returns default premium statuses -getDefaultPremiumStatuses = PremiumStatuses; +//@description Returns default emoji statuses +getDefaultEmojiStatuses = EmojiStatuses; -//@description Clears recent premium statuses -clearRecentPremiumStatuses = Ok; +//@description Clears recent emoji statuses +clearRecentEmojiStatuses = Ok; //@description Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates @@ -6127,10 +6127,10 @@ setBio bio:string = Ok; //@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username setUsername username:string = Ok; -//@description Changes the premium status of the current user; for Telegram Premium users only -//@premium_status New premium status; pass null to switch to the default badge +//@description Changes the emoji status of the current user; for Telegram Premium users only +//@emoji_status New emoji status; pass null to switch to the default badge //@duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually -setPremiumStatus premium_status:premiumStatus duration:int32 = Ok; +setEmojiStatus emoji_status:emojiStatus duration:int32 = Ok; //@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user setLocation location:location = Ok; diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 2789d65d9..685c1fb6a 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1803,7 +1803,7 @@ void ConfigManager::process_app_config(tl_object_ptr &c } if (key == "default_emoji_statuses_stickerset_id") { auto setting_value = get_json_value_long(std::move(key_value->value_), key); - G()->set_option_integer("themed_premium_statuses_sticker_set_id", setting_value); + G()->set_option_integer("themed_emoji_statuses_sticker_set_id", setting_value); continue; } diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 078dafd32..dbfae900d 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -10384,7 +10384,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo auto until_date = u->emoji_status.get_until_date(); auto left_time = until_date - unix_time; if (left_time >= 0 && left_time < 30 * 86400) { - LOG(DEBUG) << "Set premium status timeout for " << user_id << " in " << left_time; + LOG(DEBUG) << "Set emoji status timeout for " << user_id << " in " << left_time; user_emoji_status_timeout_.set_timeout_in(user_id.get(), left_time); } else { user_emoji_status_timeout_.cancel_timeout(user_id.get()); @@ -11805,13 +11805,13 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, on_update_user_emoji_status(u, user_id, EmojiStatus(std::move(emoji_status))); update_user(u, user_id); } else { - LOG(INFO) << "Ignore update user premium status about unknown " << user_id; + LOG(INFO) << "Ignore update user emoji status about unknown " << user_id; } } void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { - LOG(DEBUG) << "Change premium status of " << user_id << " from " << u->emoji_status << " to " << emoji_status; + LOG(DEBUG) << "Change emoji status of " << user_id << " from " << u->emoji_status << " to " << emoji_status; u->emoji_status = emoji_status; } } @@ -16815,10 +16815,10 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } - auto premium_status = u->last_sent_emoji_status != 0 ? u->emoji_status.get_premium_status_object() : nullptr; + auto emoji_status = u->last_sent_emoji_status != 0 ? u->emoji_status.get_emoji_status_object() : nullptr; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), - get_profile_photo_object(td_->file_manager_.get(), u->photo), std::move(premium_status), u->is_contact, + get_profile_photo_object(td_->file_manager_.get(), u->photo), std::move(emoji_status), u->is_contact, u->is_mutual_contact, u->is_verified, u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, u->is_received, std::move(type), u->language_code, u->attach_menu_enabled); diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 01c4f6bd5..00de725b6 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -22,13 +22,13 @@ struct EmojiStatuses { int64 hash_ = 0; vector emoji_statuses_; - td_api::object_ptr get_premium_statuses_object() const { - auto premium_statuses = transform(emoji_statuses_, [](const EmojiStatus &emoji_status) { + td_api::object_ptr get_emoji_statuses_object() const { + auto emoji_statuses = transform(emoji_statuses_, [](const EmojiStatus &emoji_status) { CHECK(!emoji_status.is_empty()); - return emoji_status.get_premium_status_object(); + return emoji_status.get_emoji_status_object(); }); - return td_api::make_object(std::move(premium_statuses)); + return td_api::make_object(std::move(emoji_statuses)); } EmojiStatuses() = default; @@ -39,11 +39,11 @@ struct EmojiStatuses { for (auto &status : emoji_statuses->statuses_) { EmojiStatus emoji_status(std::move(status)); if (emoji_status.is_empty()) { - LOG(ERROR) << "Receive empty premium status"; + LOG(ERROR) << "Receive empty emoji status"; continue; } if (emoji_status.get_until_date() != 0) { - LOG(ERROR) << "Receive temporary premium status"; + LOG(ERROR) << "Receive temporary emoji status"; emoji_status.clear_until_date(); } emoji_statuses_.push_back(emoji_status); @@ -89,10 +89,10 @@ static void save_emoji_statuses(const string &key, const EmojiStatuses &emoji_st } class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { - Promise> promise_; + Promise> promise_; public: - explicit GetDefaultEmojiStatusesQuery(Promise> &&promise) + explicit GetDefaultEmojiStatusesQuery(Promise> &&promise) : promise_(std::move(promise)) { } @@ -121,7 +121,7 @@ class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { save_emoji_statuses(get_default_emoji_statuses_database_key(), emoji_statuses); if (promise_) { - promise_.set_value(emoji_statuses.get_premium_statuses_object()); + promise_.set_value(emoji_statuses.get_emoji_statuses_object()); } } @@ -131,10 +131,10 @@ class GetDefaultEmojiStatusesQuery final : public Td::ResultHandler { }; class GetRecentEmojiStatusesQuery final : public Td::ResultHandler { - Promise> promise_; + Promise> promise_; public: - explicit GetRecentEmojiStatusesQuery(Promise> &&promise) + explicit GetRecentEmojiStatusesQuery(Promise> &&promise) : promise_(std::move(promise)) { } @@ -163,7 +163,7 @@ class GetRecentEmojiStatusesQuery final : public Td::ResultHandler { save_emoji_statuses(get_recent_emoji_statuses_database_key(), emoji_statuses); if (promise_) { - promise_.set_value(emoji_statuses.get_premium_statuses_object()); + promise_.set_value(emoji_statuses.get_emoji_statuses_object()); } } @@ -198,12 +198,12 @@ class ClearRecentEmojiStatusesQuery final : public Td::ResultHandler { } }; -EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status, int32 duration) { - if (premium_status == nullptr) { +EmojiStatus::EmojiStatus(const td_api::object_ptr &emoji_status, int32 duration) { + if (emoji_status == nullptr) { return; } - custom_emoji_id_ = premium_status->custom_emoji_id_; + custom_emoji_id_ = emoji_status->custom_emoji_id_; if (duration != 0) { int32 current_time = G()->unix_time(); if (duration >= std::numeric_limits::max() - current_time) { @@ -247,11 +247,11 @@ tl_object_ptr EmojiStatus::get_input_emoji_status() c return make_tl_object(custom_emoji_id_); } -td_api::object_ptr EmojiStatus::get_premium_status_object() const { +td_api::object_ptr EmojiStatus::get_emoji_status_object() const { if (is_empty()) { return nullptr; } - return td_api::make_object(custom_emoji_id_); + return td_api::make_object(custom_emoji_id_); } int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const { @@ -275,20 +275,20 @@ StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoj return string_builder; } -void get_default_emoji_statuses(Td *td, Promise> &&promise) { +void get_default_emoji_statuses(Td *td, Promise> &&promise) { auto statuses = load_emoji_statuses(get_default_emoji_statuses_database_key()); if (statuses.hash_ != -1 && promise) { - promise.set_value(statuses.get_premium_statuses_object()); - promise = Promise>(); + promise.set_value(statuses.get_emoji_statuses_object()); + promise = Promise>(); } td->create_handler(std::move(promise))->send(statuses.hash_); } -void get_recent_emoji_statuses(Td *td, Promise> &&promise) { +void get_recent_emoji_statuses(Td *td, Promise> &&promise) { auto statuses = load_emoji_statuses(get_recent_emoji_statuses_database_key()); if (statuses.hash_ != -1 && promise) { - promise.set_value(statuses.get_premium_statuses_object()); - promise = Promise>(); + promise.set_value(statuses.get_emoji_statuses_object()); + promise = Promise>(); } td->create_handler(std::move(promise))->send(statuses.hash_); } @@ -299,7 +299,7 @@ void add_recent_emoji_status(Td *td, EmojiStatus emoji_status) { } if (td->stickers_manager_->is_default_emoji_status(emoji_status.get_custom_emoji_id())) { - LOG(INFO) << "Skip adding themed premium status to recents"; + LOG(INFO) << "Skip adding themed emoji status to recents"; return; } diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index cd40dea1e..877ea04af 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -29,13 +29,13 @@ class EmojiStatus { public: EmojiStatus() = default; - EmojiStatus(const td_api::object_ptr &premium_status, int32 duration); + EmojiStatus(const td_api::object_ptr &emoji_status, int32 duration); explicit EmojiStatus(tl_object_ptr &&emoji_status); tl_object_ptr get_input_emoji_status() const; - td_api::object_ptr get_premium_status_object() const; + td_api::object_ptr get_emoji_status_object() const; int64 get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const; @@ -98,9 +98,9 @@ inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status); -void get_default_emoji_statuses(Td *td, Promise> &&promise); +void get_default_emoji_statuses(Td *td, Promise> &&promise); -void get_recent_emoji_statuses(Td *td, Promise> &&promise); +void get_recent_emoji_statuses(Td *td, Promise> &&promise); void add_recent_emoji_status(Td *td, EmojiStatus emoji_status); diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 226e02ab0..36ef4daf9 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -102,10 +102,10 @@ OptionManager::OptionManager(Td *td) if (!have_option("chat_filter_chosen_chat_count_max")) { set_option_integer("chat_filter_chosen_chat_count_max", G()->is_test_dc() ? 5 : 100); } - if (!have_option("themed_premium_statuses_sticker_set_id")) { + if (!have_option("themed_emoji_statuses_sticker_set_id")) { auto sticker_set_id = G()->is_test_dc() ? static_cast(2964141614563343) : static_cast(773947703670341676); - set_option_integer("themed_premium_statuses_sticker_set_id", sticker_set_id); + set_option_integer("themed_emoji_statuses_sticker_set_id", sticker_set_id); } } diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 21e078fb1..f080cacd9 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -5460,14 +5460,14 @@ void StickersManager::get_all_animated_emojis(bool is_recursive, } void StickersManager::get_default_emoji_statuses(bool is_recursive, - Promise> &&promise) { + Promise> &&promise) { TRY_STATUS_PROMISE(promise, G()->close_status()); auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::default_statuses()); auto sticker_set = get_sticker_set(special_sticker_set.id_); if (sticker_set == nullptr || !sticker_set->was_loaded_) { if (is_recursive) { - return promise.set_value(td_api::make_object()); + return promise.set_value(td_api::make_object()); } pending_get_default_statuses_queries_.push_back(PromiseCreator::lambda( @@ -5482,19 +5482,19 @@ void StickersManager::get_default_emoji_statuses(bool is_recursive, return; } - vector> statuses; + vector> statuses; for (auto sticker_id : sticker_set->sticker_ids_) { auto custom_emoji_id = get_custom_emoji_id(sticker_id); if (custom_emoji_id == 0) { LOG(ERROR) << "Ignore wrong sticker " << sticker_id; continue; } - statuses.emplace_back(td_api::make_object(custom_emoji_id)); + statuses.emplace_back(td_api::make_object(custom_emoji_id)); if (statuses.size() >= 8) { break; } } - promise.set_value(td_api::make_object(std::move(statuses))); + promise.set_value(td_api::make_object(std::move(statuses))); } bool StickersManager::is_default_emoji_status(int64 custom_emoji_id) { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 2c0b59610..3049de68f 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -103,7 +103,7 @@ class StickersManager final : public Actor { void get_all_animated_emojis(bool is_recursive, Promise> &&promise); - void get_default_emoji_statuses(bool is_recursive, Promise> &&promise); + void get_default_emoji_statuses(bool is_recursive, Promise> &&promise); bool is_default_emoji_status(int64 custom_emoji_id); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 88b289db7..90536868f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6746,31 +6746,31 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { contacts_manager_->set_username(request.username_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { +void Td::on_request(uint64 id, const td_api::setEmojiStatus &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_, request.duration_), std::move(promise)); + contacts_manager_->set_emoji_status(EmojiStatus(request.emoji_status_, request.duration_), std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getThemedPremiumStatuses &request) { +void Td::on_request(uint64 id, const td_api::getThemedEmojiStatuses &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); stickers_manager_->get_default_emoji_statuses(false, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) { +void Td::on_request(uint64 id, const td_api::getDefaultEmojiStatuses &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); get_default_emoji_statuses(this, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getRecentPremiumStatuses &request) { +void Td::on_request(uint64 id, const td_api::getRecentEmojiStatuses &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); get_recent_emoji_statuses(this, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::clearRecentPremiumStatuses &request) { +void Td::on_request(uint64 id, const td_api::clearRecentEmojiStatuses &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); clear_recent_emoji_statuses(this, std::move(promise)); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 9b187add6..56eab346e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1016,15 +1016,15 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setUsername &request); - void on_request(uint64 id, const td_api::setPremiumStatus &request); + void on_request(uint64 id, const td_api::setEmojiStatus &request); - void on_request(uint64 id, const td_api::getThemedPremiumStatuses &request); + void on_request(uint64 id, const td_api::getThemedEmojiStatuses &request); - void on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request); + void on_request(uint64 id, const td_api::getDefaultEmojiStatuses &request); - void on_request(uint64 id, const td_api::getRecentPremiumStatuses &request); + void on_request(uint64 id, const td_api::getRecentEmojiStatuses &request); - void on_request(uint64 id, const td_api::clearRecentPremiumStatuses &request); + void on_request(uint64 id, const td_api::clearRecentEmojiStatuses &request); void on_request(uint64 id, td_api::setCommands &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index fa42fa7e0..f87db00c1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3444,7 +3444,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "gte") { send_request(td_api::make_object(args)); - } else if (op == "gtes") { + } else if (op == "gtee") { execute(td_api::make_object(args)); } else if (op == "pm") { send_request( @@ -4485,22 +4485,22 @@ class CliClient final : public Actor { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); } else if (op == "sun") { send_request(td_api::make_object(args)); - } else if (op == "spse") { - send_request(td_api::make_object(nullptr, 0)); - } else if (op == "sps") { + } else if (op == "sese") { + send_request(td_api::make_object(nullptr, 0)); + } else if (op == "ses") { int64 custom_emoji_id; int32 until_date; get_args(args, custom_emoji_id, until_date); - send_request(td_api::make_object( - td_api::make_object(custom_emoji_id), until_date)); - } else if (op == "gtps") { - send_request(td_api::make_object()); - } else if (op == "gdps") { - send_request(td_api::make_object()); - } else if (op == "grps") { - send_request(td_api::make_object()); - } else if (op == "crps") { - send_request(td_api::make_object()); + send_request(td_api::make_object( + td_api::make_object(custom_emoji_id), until_date)); + } else if (op == "gtes") { + send_request(td_api::make_object()); + } else if (op == "gdes") { + send_request(td_api::make_object()); + } else if (op == "gres") { + send_request(td_api::make_object()); + } else if (op == "cres") { + send_request(td_api::make_object()); } else if (op == "ccun") { ChatId chat_id; string username; From cac1f4cd146e4e25d6b794f82ad485a35a9b5f24 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 12:53:14 +0300 Subject: [PATCH 095/200] Add passwordState.login_email_address_pattern. --- td/generate/scheme/td_api.tl | 3 ++- td/telegram/PasswordManager.cpp | 1 + td/telegram/PasswordManager.h | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 42a78f5d1..5a4098c7d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -144,8 +144,9 @@ authorizationStateClosed = AuthorizationState; //@description Represents the current state of 2-step verification @has_password True, if a 2-step verification password is set @password_hint Hint for the password; may be empty //@has_recovery_email_address True, if a recovery email is set @has_passport_data True, if some Telegram Passport elements were saved //@recovery_email_address_code_info Information about the recovery email address to which the confirmation email was sent; may be null +//@login_email_address_pattern Pattern of the email address set up for logging in //@pending_reset_date If not 0, point in time (Unix timestamp) after which the 2-step verification password can be reset immediately using resetPassword -passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool recovery_email_address_code_info:emailAddressAuthenticationCodeInfo pending_reset_date:int32 = PasswordState; +passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool recovery_email_address_code_info:emailAddressAuthenticationCodeInfo login_email_address_pattern:string pending_reset_date:int32 = PasswordState; //@description Contains information about the current recovery email address @recovery_email_address Recovery email address recoveryEmailAddress recovery_email_address:string = RecoveryEmailAddress; diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index e27f52c93..2a3b67098 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -786,6 +786,7 @@ void PasswordManager::do_get_state(Promise promise) { send_closure(actor_id, &PasswordManager::drop_cached_secret); } state.unconfirmed_recovery_email_code = {std::move(password->email_unconfirmed_pattern_), code_length}; + state.login_email_pattern = std::move(password->login_email_pattern_); if (password->flags_ & telegram_api::account_password::PENDING_RESET_DATE_MASK) { state.pending_reset_date = td::max(password->pending_reset_date_, 0); diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 8b465bc94..45508706f 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -106,6 +106,7 @@ class PasswordManager final : public NetQueryCallback { bool has_recovery_email_address = false; bool has_secure_values = false; SentEmailCode unconfirmed_recovery_email_code; + string login_email_pattern; int32 pending_reset_date = 0; string current_client_salt; @@ -120,7 +121,8 @@ class PasswordManager final : public NetQueryCallback { State get_password_state_object() const { return td_api::make_object( has_password, password_hint, has_recovery_email_address, has_secure_values, - unconfirmed_recovery_email_code.get_email_address_authentication_code_info_object(), pending_reset_date); + unconfirmed_recovery_email_code.get_email_address_authentication_code_info_object(), login_email_pattern, + pending_reset_date); } }; From c373d14777d050422592338bafa44a393af45cfc Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 13:49:48 +0300 Subject: [PATCH 096/200] Add td_api::setLoginEmailAddress. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/PasswordManager.cpp | 14 ++++++++++++++ td/telegram/PasswordManager.h | 2 ++ td/telegram/Td.cpp | 15 +++++++++++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 38 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 5a4098c7d..8092121a0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4703,6 +4703,9 @@ getPasswordState = PasswordState; //@old_password Previous 2-step verification password of the user @new_password New 2-step verification password of the user; may be empty to remove the password @new_hint New password hint; may be empty @set_recovery_email_address Pass true to change also the recovery email address @new_recovery_email_address New recovery email address; may be empty setPassword old_password:string new_password:string new_hint:string set_recovery_email_address:Bool new_recovery_email_address:string = PasswordState; +//@description Changes the login email address of the user. The change will not be applied until the new login email address is confirmed with `checkLoginEmailAddressCode`. To use Apple ID/Google ID instead of a email address, call `checkLoginEmailAddressCode` directly @new_login_email_address New login email address +setLoginEmailAddress new_login_email_address:string = EmailAddressAuthenticationCodeInfo; + //@description Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user @password The 2-step verification password for the current user getRecoveryEmailAddress password:string = RecoveryEmailAddress; diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 2a3b67098..9a4b5f558 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -180,6 +180,20 @@ void PasswordManager::set_password(string current_password, string new_password, update_password_settings(std::move(update_settings), std::move(promise)); } +void PasswordManager::set_login_email_address(string new_login_email_address, Promise promise) { + last_verified_email_address_ = new_login_email_address; + auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode( + make_tl_object(), std::move(new_login_email_address))); + send_with_promise(std::move(query), + PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + return promise.set_value(SentEmailCode(r_result.move_as_ok())); + })); +} + void PasswordManager::set_recovery_email_address(string password, string new_recovery_email_address, Promise promise) { UpdateSettings update_settings; diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 45508706f..8ae6af8b9 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -70,6 +70,7 @@ class PasswordManager final : public NetQueryCallback { void get_state(Promise promise); void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address, string recovery_email_address, Promise promise); + void set_login_email_address(string new_login_email_address, Promise promise); void set_recovery_email_address(string password, string new_recovery_email_address, Promise promise); void get_recovery_email_address(string password, Promise> promise); void check_recovery_email_address_code(string code, Promise promise); @@ -155,6 +156,7 @@ class PasswordManager final : public NetQueryCallback { TempPasswordState temp_password_state_; Promise create_temp_password_promise_; + string last_set_login_email_address_; string last_verified_email_address_; int32 last_code_length_ = 0; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 90536868f..3035ed189 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4407,6 +4407,21 @@ void Td::on_request(uint64 id, td_api::setPassword &request) { std::move(request.new_recovery_email_address_), std::move(promise)); } +void Td::on_request(uint64 id, td_api::setLoginEmailAddress &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.new_login_email_address_); + CREATE_REQUEST_PROMISE(); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(result.ok().get_email_address_authentication_code_info_object()); + } + }); + send_closure(password_manager_, &PasswordManager::set_login_email_address, + std::move(request.new_login_email_address_), std::move(query_promise)); +} + void Td::on_request(uint64 id, td_api::setRecoveryEmailAddress &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.password_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 56eab346e..c740f4043 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -434,6 +434,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setPassword &request); + void on_request(uint64 id, td_api::setLoginEmailAddress &request); + void on_request(uint64 id, td_api::getRecoveryEmailAddress &request); void on_request(uint64 id, td_api::setRecoveryEmailAddress &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index f87db00c1..cdf50d6e6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1991,6 +1991,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "reavc" || op == "ResendEmailAddressVerificationCode") { send_request(td_api::make_object()); + } else if (op == "slea") { + send_request(td_api::make_object(args)); } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address; From cc8ef1a077286883d0787b62af603a0d0f9394a4 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 14:39:33 +0300 Subject: [PATCH 097/200] Add td_api::resendLoginEmailAddressCode. --- td/generate/scheme/td_api.tl | 11 +++++++---- td/telegram/AuthManager.cpp | 2 +- td/telegram/PasswordManager.cpp | 9 ++++++++- td/telegram/PasswordManager.h | 1 + td/telegram/Td.cpp | 13 +++++++++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8092121a0..69a065bf7 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4640,7 +4640,7 @@ setAuthenticationPhoneNumber phone_number:string settings:phoneNumberAuthenticat //@description Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress @email_address The email address of the user setAuthenticationEmailAddress email_address:string = Ok; -//@description Re-sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed +//@description Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed resendAuthenticationCode = Ok; //@description Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode @code Email address authentication to check @@ -4706,6 +4706,9 @@ setPassword old_password:string new_password:string new_hint:string set_recovery //@description Changes the login email address of the user. The change will not be applied until the new login email address is confirmed with `checkLoginEmailAddressCode`. To use Apple ID/Google ID instead of a email address, call `checkLoginEmailAddressCode` directly @new_login_email_address New login email address setLoginEmailAddress new_login_email_address:string = EmailAddressAuthenticationCodeInfo; +//@description Resends the login email address verification code +resendLoginEmailAddressCode = EmailAddressAuthenticationCodeInfo; + //@description Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user @password The 2-step verification password for the current user getRecoveryEmailAddress password:string = RecoveryEmailAddress; @@ -6143,7 +6146,7 @@ setLocation location:location = Ok; //@phone_number The new phone number of the user in international format @settings Settings for the authentication of the user's phone number; pass null to use default settings changePhoneNumber phone_number:string settings:phoneNumberAuthenticationSettings = AuthenticationCodeInfo; -//@description Re-sends the authentication code sent to confirm a new phone number for the current user. Works only if the previously received authenticationCodeInfo next_code_type was not null and the server-specified timeout has passed +//@description Resends the authentication code sent to confirm a new phone number for the current user. Works only if the previously received authenticationCodeInfo next_code_type was not null and the server-specified timeout has passed resendChangePhoneNumberCode = AuthenticationCodeInfo; //@description Checks the authentication code sent to confirm a new phone number of the user @code Authentication code to check @@ -6473,7 +6476,7 @@ getPreferredCountryLanguage country_code:string = Text; //@phone_number The phone number of the user, in international format @settings Settings for the authentication of the user's phone number; pass null to use default settings sendPhoneNumberVerificationCode phone_number:string settings:phoneNumberAuthenticationSettings = AuthenticationCodeInfo; -//@description Re-sends the code to verify a phone number to be added to a user's Telegram Passport +//@description Resends the code to verify a phone number to be added to a user's Telegram Passport resendPhoneNumberVerificationCode = AuthenticationCodeInfo; //@description Checks the phone number verification code for Telegram Passport @code Verification code to check @@ -6483,7 +6486,7 @@ checkPhoneNumberVerificationCode code:string = Ok; //@description Sends a code to verify an email address to be added to a user's Telegram Passport @email_address Email address sendEmailAddressVerificationCode email_address:string = EmailAddressAuthenticationCodeInfo; -//@description Re-sends the code to verify an email address to be added to a user's Telegram Passport +//@description Resends the code to verify an email address to be added to a user's Telegram Passport resendEmailAddressVerificationCode = EmailAddressAuthenticationCodeInfo; //@description Checks the email address verification code for Telegram Passport @code Verification code to check diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index eabd2e4ab..5ae368af3 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -457,7 +457,7 @@ void AuthManager::log_out(uint64 query_id) { } void AuthManager::send_log_out_query() { - // we can lose authorization while logging out, but still may need to re-send the request, + // we can lose authorization while logging out, but still may need to resend the request, // so we pretend that it doesn't require authorization auto query = G()->net_query_creator().create_unauth(telegram_api::auth_logOut()); query->set_priority(1); diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 9a4b5f558..63911912f 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -181,7 +181,7 @@ void PasswordManager::set_password(string current_password, string new_password, } void PasswordManager::set_login_email_address(string new_login_email_address, Promise promise) { - last_verified_email_address_ = new_login_email_address; + last_set_login_email_address_ = new_login_email_address; auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode( make_tl_object(), std::move(new_login_email_address))); send_with_promise(std::move(query), @@ -194,6 +194,13 @@ void PasswordManager::set_login_email_address(string new_login_email_address, Pr })); } +void PasswordManager::resend_login_email_address_code(Promise promise) { + if (last_set_login_email_address_.empty()) { + return promise.set_error(Status::Error(400, "No login email address code was sent")); + } + set_login_email_address(last_set_login_email_address_, std::move(promise)); +} + void PasswordManager::set_recovery_email_address(string password, string new_recovery_email_address, Promise promise) { UpdateSettings update_settings; diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 8ae6af8b9..6e1eda0bc 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -71,6 +71,7 @@ class PasswordManager final : public NetQueryCallback { void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address, string recovery_email_address, Promise promise); void set_login_email_address(string new_login_email_address, Promise promise); + void resend_login_email_address_code(Promise promise); void set_recovery_email_address(string password, string new_recovery_email_address, Promise promise); void get_recovery_email_address(string password, Promise> promise); void check_recovery_email_address_code(string code, Promise promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3035ed189..b4b583111 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4422,6 +4422,19 @@ void Td::on_request(uint64 id, td_api::setLoginEmailAddress &request) { std::move(request.new_login_email_address_), std::move(query_promise)); } +void Td::on_request(uint64 id, const td_api::resendLoginEmailAddressCode &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(result.ok().get_email_address_authentication_code_info_object()); + } + }); + send_closure(password_manager_, &PasswordManager::resend_login_email_address_code, std::move(query_promise)); +} + void Td::on_request(uint64 id, td_api::setRecoveryEmailAddress &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.password_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index c740f4043..b258c4dee 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -436,6 +436,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::setLoginEmailAddress &request); + void on_request(uint64 id, const td_api::resendLoginEmailAddressCode &request); + void on_request(uint64 id, td_api::getRecoveryEmailAddress &request); void on_request(uint64 id, td_api::setRecoveryEmailAddress &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index cdf50d6e6..dd808dbb7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1993,6 +1993,8 @@ class CliClient final : public Actor { send_request(td_api::make_object()); } else if (op == "slea") { send_request(td_api::make_object(args)); + } else if (op == "rleac") { + send_request(td_api::make_object()); } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address; From 1b7f24459f660f7e334da9843690d263109f4a20 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 15:18:43 +0300 Subject: [PATCH 098/200] Add td_api::checkLoginEmailAddressCode. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/PasswordManager.cpp | 19 +++++++++++++++++++ td/telegram/PasswordManager.h | 4 ++++ td/telegram/Td.cpp | 7 +++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 23 ++++++++++++++--------- 6 files changed, 49 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 69a065bf7..caf1b83aa 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4709,6 +4709,9 @@ setLoginEmailAddress new_login_email_address:string = EmailAddressAuthentication //@description Resends the login email address verification code resendLoginEmailAddressCode = EmailAddressAuthenticationCodeInfo; +//@description Checks the login email address authentication @code Email address authentication to check +checkLoginEmailAddressCode code:EmailAddressAuthentication = Ok; + //@description Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user @password The 2-step verification password for the current user getRecoveryEmailAddress password:string = RecoveryEmailAddress; diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 63911912f..20f44b80d 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -201,6 +201,25 @@ void PasswordManager::resend_login_email_address_code(Promise pro set_login_email_address(last_set_login_email_address_, std::move(promise)); } +void PasswordManager::check_login_email_address_code(EmailVerification &&code, Promise promise) { + if (last_set_login_email_address_.empty()) { + return promise.set_error(Status::Error(400, "No login email address code was sent")); + } + if (code.is_empty()) { + return promise.set_error(Status::Error(400, "Verification code must be non-empty")); + } + auto query = G()->net_query_creator().create(telegram_api::account_verifyEmail( + make_tl_object(), code.get_input_email_verification())); + send_with_promise(std::move(query), + PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + return promise.set_value(Unit()); + })); +} + void PasswordManager::set_recovery_email_address(string password, string new_recovery_email_address, Promise promise) { UpdateSettings update_settings; diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 6e1eda0bc..3698dca0f 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/EmailVerification.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/NewPasswordState.h" #include "td/telegram/SecureStorage.h" @@ -70,8 +71,11 @@ class PasswordManager final : public NetQueryCallback { void get_state(Promise promise); void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address, string recovery_email_address, Promise promise); + void set_login_email_address(string new_login_email_address, Promise promise); void resend_login_email_address_code(Promise promise); + void check_login_email_address_code(EmailVerification &&code, Promise promise); + void set_recovery_email_address(string password, string new_recovery_email_address, Promise promise); void get_recovery_email_address(string password, Promise> promise); void check_recovery_email_address_code(string code, Promise promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b4b583111..3c6888e7d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4435,6 +4435,13 @@ void Td::on_request(uint64 id, const td_api::resendLoginEmailAddressCode &reques send_closure(password_manager_, &PasswordManager::resend_login_email_address_code, std::move(query_promise)); } +void Td::on_request(uint64 id, td_api::checkLoginEmailAddressCode &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + send_closure(password_manager_, &PasswordManager::check_login_email_address_code, + EmailVerification(std::move(request.code_)), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setRecoveryEmailAddress &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.password_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b258c4dee..9992fd5ed 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -438,6 +438,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::resendLoginEmailAddressCode &request); + void on_request(uint64 id, td_api::checkLoginEmailAddressCode &request); + void on_request(uint64 id, td_api::getRecoveryEmailAddress &request); void on_request(uint64 id, td_api::setRecoveryEmailAddress &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index dd808dbb7..57b1ac58b 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1591,6 +1591,17 @@ class CliClient final : public Actor { return nullptr; } + static td_api::object_ptr as_email_address_authentication(Slice arg) { + if (begins_with(arg, "a ")) { + return td_api::make_object(arg.substr(2).str()); + } else if (begins_with(arg, "g ")) { + return td_api::make_object(arg.substr(2).str()); + } else if (!arg.empty()) { + return td_api::make_object(arg.str()); + } + return nullptr; + } + static td_api::object_ptr as_passport_element_type(Slice passport_element_type) { if (passport_element_type == "address" || passport_element_type == "a") { return td_api::make_object(); @@ -1851,15 +1862,7 @@ class CliClient final : public Actor { } else if (op == "sdek" || op == "SetDatabaseEncryptionKey") { send_request(td_api::make_object(args)); } else if (op == "caec") { - td_api::object_ptr code; - if (begins_with(args, "a ")) { - code = td_api::make_object(args.substr(2)); - } else if (begins_with(args, "g ")) { - code = td_api::make_object(args.substr(2)); - } else if (!args.empty()) { - code = td_api::make_object(args); - } - send_request(td_api::make_object(std::move(code))); + send_request(td_api::make_object(as_email_address_authentication(args))); } else if (op == "cac") { send_request(td_api::make_object(args)); } else if (op == "ru") { @@ -1995,6 +1998,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "rleac") { send_request(td_api::make_object()); + } else if (op == "cleac") { + send_request(td_api::make_object(as_email_address_authentication(args))); } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address; From ba547561bb53ac2485ed5679d1d9d2f7bc4c1910 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 19:42:21 +0300 Subject: [PATCH 099/200] Support resending of email authentication code. --- td/generate/scheme/td_api.tl | 2 +- td/telegram/AuthManager.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index caf1b83aa..eaa7cbe1a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4640,7 +4640,7 @@ setAuthenticationPhoneNumber phone_number:string settings:phoneNumberAuthenticat //@description Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress @email_address The email address of the user setAuthenticationEmailAddress email_address:string = Ok; -//@description Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed +//@description Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the next_code_type of the result is not null and the server-specified timeout has passed, or when the current authorization state is authorizationStateWaitEmailCode resendAuthenticationCode = Ok; //@description Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode @code Email address authentication to check diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 5ae368af3..1a80475af 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -306,6 +306,13 @@ void AuthManager::set_email_address(uint64 query_id, string email_address) { void AuthManager::resend_authentication_code(uint64 query_id) { if (state_ != State::WaitCode) { + if (state_ == State::WaitEmailCode) { + on_new_query(query_id); + start_net_query(NetQueryType::SendEmailCode, + G()->net_query_creator().create_unauth(send_code_helper_.send_verify_email_code(email_address_))); + return; + } + return on_query_error(query_id, Status::Error(400, "Call to resendAuthenticationCode unexpected")); } From 9bd566702ecc0b85d8cca7c3d8634abf802779d8 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 20:02:44 +0300 Subject: [PATCH 100/200] Add source to MessagesManager::fix_new_dialog. --- td/telegram/MessagesManager.cpp | 52 ++++++++++++++++++--------------- td/telegram/MessagesManager.h | 3 +- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index f7e560db6..554ada32d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -15450,12 +15450,16 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector full_message_id_to_dialog_date; FlatHashMap, FullMessageIdHash> full_message_id_to_message; @@ -15553,12 +15557,12 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorflags_ & DIALOG_FLAG_HAS_FOLDER_ID) != 0 ? dialog->folder_id_ : 0)); - on_update_dialog_notify_settings(dialog_id, std::move(dialog->notify_settings_), "on_get_dialogs"); + on_update_dialog_notify_settings(dialog_id, std::move(dialog->notify_settings_), source); if (!d->notification_settings.is_synchronized && !td_->auth_manager_->is_bot()) { LOG(ERROR) << "Failed to synchronize settings in " << dialog_id; d->notification_settings.is_synchronized = true; @@ -15632,21 +15636,21 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorpts == 0 || dialog->pts_ <= d->pts || d->is_channel_difference_finished) { auto last_message = std::move(it->second); auto added_full_message_id = - on_get_message(std::move(last_message), false, has_pts, false, false, false, "get chats"); + on_get_message(std::move(last_message), false, has_pts, false, false, false, source); CHECK(d->last_new_message_id == MessageId()); - set_dialog_last_new_message_id(d, last_message_id, "on_get_dialogs"); + set_dialog_last_new_message_id(d, last_message_id, source); if (d->last_new_message_id > d->last_message_id && added_full_message_id.get_message_id().is_valid()) { CHECK(added_full_message_id.get_message_id() == d->last_new_message_id); - set_dialog_last_message_id(d, d->last_new_message_id, "on_get_dialogs"); - send_update_chat_last_message(d, "on_get_dialogs"); + set_dialog_last_message_id(d, d->last_new_message_id, source); + send_update_chat_last_message(d, source); } } else { - get_channel_difference(dialog_id, d->pts, true, "on_get_dialogs"); + get_channel_difference(dialog_id, d->pts, true, source); } } if (has_pts && !running_get_channel_difference(dialog_id)) { - set_channel_pts(d, dialog->pts_, "get channel"); + set_channel_pts(d, dialog->pts_, source); } } bool is_marked_as_unread = dialog->unread_mark_; @@ -15655,7 +15659,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorauth_manager_->is_bot() && !from_pinned_dialog_list) { @@ -15701,7 +15705,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorserver_unread_count, "on_get_dialogs"); + repair_server_unread_count(dialog_id, d->server_unread_count, source); } } if (!d->need_repair_server_unread_count) { @@ -15711,7 +15715,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorlast_read_inbox_message_id == read_inbox_max_message_id) || d->last_read_inbox_message_id < read_inbox_max_message_id) { set_dialog_last_read_inbox_message_id(d, read_inbox_max_message_id, dialog->unread_count_, - d->local_unread_count, true, "on_get_dialogs"); + d->local_unread_count, true, source); } if (!d->is_last_read_inbox_message_id_inited) { d->is_last_read_inbox_message_id_inited = true; @@ -15738,13 +15742,13 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorunread_reaction_count != dialog->unread_reactions_count_) { set_dialog_unread_reaction_count(d, dialog->unread_reactions_count_); // update_dialog_mention_notification_count(d); - send_update_chat_unread_reaction_count(d, "on_get_dialogs"); + send_update_chat_unread_reaction_count(d, source); } } being_added_dialog_id_ = DialogId(); - update_dialog_lists(d, std::move(positions), true, false, "on_get_dialogs"); + update_dialog_lists(d, std::move(positions), true, false, source); } if (from_dialog_list) { @@ -15757,7 +15761,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectornotification_settings.is_synchronized && td_->contacts_manager_->get_secret_chat_state(dialog_id.get_secret_chat_id()) != SecretChatState::Closed) { @@ -36709,7 +36713,7 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr &&di fix_new_dialog(d, std::move(last_database_message), last_database_message_id, order, last_clear_history_date, last_clear_history_message_id, default_join_group_call_as_dialog_id, default_send_message_as_dialog_id, - need_drop_default_send_message_as_dialog_id, is_loaded_from_database); + need_drop_default_send_message_as_dialog_id, is_loaded_from_database, source); return d; } @@ -36719,7 +36723,8 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab MessageId last_clear_history_message_id, DialogId default_join_group_call_as_dialog_id, DialogId default_send_message_as_dialog_id, - bool need_drop_default_send_message_as_dialog_id, bool is_loaded_from_database) { + bool need_drop_default_send_message_as_dialog_id, bool is_loaded_from_database, + const char *source) { CHECK(d != nullptr); auto dialog_id = d->dialog_id; auto dialog_type = dialog_id.get_type(); @@ -37070,9 +37075,10 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab auto common_data = PSTRING() << ' ' << last_message_id << ' ' << d->last_message_id << ' ' << d->last_database_message_id << ' ' << d->debug_set_dialog_last_database_message_id << ' ' << d->messages->debug_source << ' ' - << is_loaded_from_database << ' ' << being_added_dialog_id_ << ' ' << being_added_new_dialog_id_ - << ' ' << dialog_id << ' ' << d->is_channel_difference_finished << ' ' - << debug_last_get_channel_difference_dialog_id_ << ' ' << debug_last_get_channel_difference_source_; + << is_loaded_from_database << ' ' << source << ' ' << being_added_dialog_id_ << ' ' + << being_added_new_dialog_id_ << ' ' << dialog_id << ' ' << d->is_channel_difference_finished << ' ' + << debug_last_get_channel_difference_dialog_id_ << ' ' << debug_last_get_channel_difference_source_ + << ' ' << G()->parameters().use_message_db; LOG_CHECK(d->messages->message_id == last_message_id) << d->messages->message_id << common_data; LOG_CHECK(d->messages->left == nullptr) << d->messages->left->message_id << ' ' << d->messages->message_id << ' ' << d->messages->left->message_id diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c9d126491..7dc300c78 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2733,7 +2733,8 @@ class MessagesManager final : public Actor { void fix_new_dialog(Dialog *d, unique_ptr &&last_database_message, MessageId last_database_message_id, int64 order, int32 last_clear_history_date, MessageId last_clear_history_message_id, DialogId default_join_group_call_as_dialog_id, DialogId default_send_message_as_dialog_id, - bool need_drop_default_send_message_as_dialog_id, bool is_loaded_from_database); + bool need_drop_default_send_message_as_dialog_id, bool is_loaded_from_database, + const char *source); bool add_dialog_last_database_message(Dialog *d, unique_ptr &&last_database_message); From 20767a318b5fa74077d455c209bbc1d0587cb8cf Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 21:22:21 +0300 Subject: [PATCH 101/200] Check for new code types in other phone number verifications. --- td/telegram/PhoneNumberManager.cpp | 8 ++++++++ td/telegram/SendCodeHelper.cpp | 5 ++--- td/telegram/SendCodeHelper.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/td/telegram/PhoneNumberManager.cpp b/td/telegram/PhoneNumberManager.cpp index 835ba1911..4c8742efd 100644 --- a/td/telegram/PhoneNumberManager.cpp +++ b/td/telegram/PhoneNumberManager.cpp @@ -213,6 +213,14 @@ void PhoneNumberManager::on_send_code_result(NetQueryPtr &result) { LOG(INFO) << "Receive " << to_string(sent_code); + switch (sent_code->type_->get_id()) { + case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: + case telegram_api::auth_sentCodeTypeEmailCode::ID: + return on_query_error(Status::Error(500, "Receive incorrect response")); + default: + break; + } + send_code_helper_.on_sent_code(std::move(sent_code)); state_ = State::WaitCode; diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index 993268f05..989e2a8f0 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -13,7 +13,7 @@ namespace td { void SendCodeHelper::on_sent_code(telegram_api::object_ptr sent_code) { phone_code_hash_ = std::move(sent_code->phone_code_hash_); - sent_code_info_ = get_authentication_code_info(std::move(sent_code->type_)); + sent_code_info_ = get_sent_authentication_code_info(std::move(sent_code->type_)); next_code_info_ = get_authentication_code_info(std::move(sent_code->next_type_)); next_code_timestamp_ = Timestamp::in((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); } @@ -124,7 +124,7 @@ SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_i } } -SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_info( +SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_sent_authentication_code_info( tl_object_ptr &&sent_code_type_ptr) { CHECK(sent_code_type_ptr != nullptr); switch (sent_code_type_ptr->get_id()) { @@ -151,7 +151,6 @@ SendCodeHelper::AuthenticationCodeInfo SendCodeHelper::get_authentication_code_i } case telegram_api::auth_sentCodeTypeEmailCode::ID: case telegram_api::auth_sentCodeTypeSetUpEmailRequired::ID: - return AuthenticationCodeInfo(); default: UNREACHABLE(); return AuthenticationCodeInfo(); diff --git a/td/telegram/SendCodeHelper.h b/td/telegram/SendCodeHelper.h index 6ace7fad4..e4cff30c4 100644 --- a/td/telegram/SendCodeHelper.h +++ b/td/telegram/SendCodeHelper.h @@ -87,7 +87,7 @@ class SendCodeHelper { static AuthenticationCodeInfo get_authentication_code_info( tl_object_ptr &&code_type_ptr); - static AuthenticationCodeInfo get_authentication_code_info( + static AuthenticationCodeInfo get_sent_authentication_code_info( tl_object_ptr &&sent_code_type_ptr); static td_api::object_ptr get_authentication_code_type_object( From 287cceb162a9e218193447067bca0bb40229e126 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 21:27:23 +0300 Subject: [PATCH 102/200] Remove separate authorizationStateWaitEncryptionKey. --- example/cpp/td_example.cpp | 141 ++++++++---------- example/csharp/TdExample.cs | 4 - .../org/drinkless/tdlib/example/Example.java | 3 - example/python/tdjson_example.py | 4 - example/swift/src/main.swift | 3 - example/uwp/app/MainPage.xaml.cs | 1 - td/generate/scheme/td_api.tl | 9 +- td/telegram/Td.cpp | 97 ++---------- td/telegram/Td.h | 14 +- td/telegram/cli.cpp | 7 +- test/online.cpp | 3 - test/tdclient.cpp | 3 - 12 files changed, 86 insertions(+), 203 deletions(-) diff --git a/example/cpp/td_example.cpp b/example/cpp/td_example.cpp index 773a7c443..a78d4c53c 100644 --- a/example/cpp/td_example.cpp +++ b/example/cpp/td_example.cpp @@ -238,82 +238,71 @@ class TdExample { void on_authorization_state_update() { authentication_query_id_++; - td_api::downcast_call( - *authorization_state_, - overloaded( - [this](td_api::authorizationStateReady &) { - are_authorized_ = true; - std::cout << "Got authorization" << std::endl; - }, - [this](td_api::authorizationStateLoggingOut &) { - are_authorized_ = false; - std::cout << "Logging out" << std::endl; - }, - [this](td_api::authorizationStateClosing &) { std::cout << "Closing" << std::endl; }, - [this](td_api::authorizationStateClosed &) { - are_authorized_ = false; - need_restart_ = true; - std::cout << "Terminated" << std::endl; - }, - [this](td_api::authorizationStateWaitCode &) { - std::cout << "Enter authentication code: " << std::flush; - std::string code; - std::cin >> code; - send_query(td_api::make_object(code), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitRegistration &) { - std::string first_name; - std::string last_name; - std::cout << "Enter your first name: " << std::flush; - std::cin >> first_name; - std::cout << "Enter your last name: " << std::flush; - std::cin >> last_name; - send_query(td_api::make_object(first_name, last_name), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitPassword &) { - std::cout << "Enter authentication password: " << std::flush; - std::string password; - std::getline(std::cin, password); - send_query(td_api::make_object(password), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitOtherDeviceConfirmation &state) { - std::cout << "Confirm this login link on another device: " << state.link_ << std::endl; - }, - [this](td_api::authorizationStateWaitPhoneNumber &) { - std::cout << "Enter phone number: " << std::flush; - std::string phone_number; - std::cin >> phone_number; - send_query(td_api::make_object(phone_number, nullptr), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitEncryptionKey &) { - std::cout << "Enter encryption key or DESTROY: " << std::flush; - std::string key; - std::getline(std::cin, key); - if (key == "DESTROY") { - send_query(td_api::make_object(), create_authentication_query_handler()); - } else { - send_query(td_api::make_object(std::move(key)), - create_authentication_query_handler()); - } - }, - [this](td_api::authorizationStateWaitTdlibParameters &) { - auto parameters = td_api::make_object(); - parameters->database_directory_ = "tdlib"; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = 94575; - parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->application_version_ = "1.0"; - parameters->enable_storage_optimizer_ = true; - send_query(td_api::make_object(std::move(parameters)), - create_authentication_query_handler()); - })); + td_api::downcast_call(*authorization_state_, + overloaded( + [this](td_api::authorizationStateReady &) { + are_authorized_ = true; + std::cout << "Got authorization" << std::endl; + }, + [this](td_api::authorizationStateLoggingOut &) { + are_authorized_ = false; + std::cout << "Logging out" << std::endl; + }, + [this](td_api::authorizationStateClosing &) { std::cout << "Closing" << std::endl; }, + [this](td_api::authorizationStateClosed &) { + are_authorized_ = false; + need_restart_ = true; + std::cout << "Terminated" << std::endl; + }, + [this](td_api::authorizationStateWaitCode &) { + std::cout << "Enter authentication code: " << std::flush; + std::string code; + std::cin >> code; + send_query(td_api::make_object(code), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitRegistration &) { + std::string first_name; + std::string last_name; + std::cout << "Enter your first name: " << std::flush; + std::cin >> first_name; + std::cout << "Enter your last name: " << std::flush; + std::cin >> last_name; + send_query(td_api::make_object(first_name, last_name), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitPassword &) { + std::cout << "Enter authentication password: " << std::flush; + std::string password; + std::getline(std::cin, password); + send_query(td_api::make_object(password), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitOtherDeviceConfirmation &state) { + std::cout << "Confirm this login link on another device: " << state.link_ << std::endl; + }, + [this](td_api::authorizationStateWaitPhoneNumber &) { + std::cout << "Enter phone number: " << std::flush; + std::string phone_number; + std::cin >> phone_number; + send_query( + td_api::make_object(phone_number, nullptr), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitTdlibParameters &) { + auto parameters = td_api::make_object(); + parameters->database_directory_ = "tdlib"; + parameters->use_message_database_ = true; + parameters->use_secret_chats_ = true; + parameters->api_id_ = 94575; + parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; + parameters->system_language_code_ = "en"; + parameters->device_model_ = "Desktop"; + parameters->application_version_ = "1.0"; + parameters->enable_storage_optimizer_ = true; + send_query(td_api::make_object(std::move(parameters)), + create_authentication_query_handler()); + })); } void check_authentication_error(Object object) { diff --git a/example/csharp/TdExample.cs b/example/csharp/TdExample.cs index 405def5e1..3c57a398c 100644 --- a/example/csharp/TdExample.cs +++ b/example/csharp/TdExample.cs @@ -80,10 +80,6 @@ namespace TdExample _client.Send(new TdApi.SetTdlibParameters(parameters), new AuthorizationRequestHandler()); } - else if (_authorizationState is TdApi.AuthorizationStateWaitEncryptionKey) - { - _client.Send(new TdApi.CheckDatabaseEncryptionKey(), new AuthorizationRequestHandler()); - } else if (_authorizationState is TdApi.AuthorizationStateWaitPhoneNumber) { string phoneNumber = ReadLine("Please enter phone number: "); diff --git a/example/java/org/drinkless/tdlib/example/Example.java b/example/java/org/drinkless/tdlib/example/Example.java index 486470f6e..133585904 100644 --- a/example/java/org/drinkless/tdlib/example/Example.java +++ b/example/java/org/drinkless/tdlib/example/Example.java @@ -114,9 +114,6 @@ public final class Example { client.send(new TdApi.SetTdlibParameters(parameters), new AuthorizationRequestHandler()); break; - case TdApi.AuthorizationStateWaitEncryptionKey.CONSTRUCTOR: - client.send(new TdApi.CheckDatabaseEncryptionKey(), new AuthorizationRequestHandler()); - break; case TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: { String phoneNumber = promptString("Please enter phone number: "); client.send(new TdApi.SetAuthenticationPhoneNumber(phoneNumber, null), new AuthorizationRequestHandler()); diff --git a/example/python/tdjson_example.py b/example/python/tdjson_example.py index 17efd1f42..d3e4516e5 100644 --- a/example/python/tdjson_example.py +++ b/example/python/tdjson_example.py @@ -105,10 +105,6 @@ while True: 'application_version': '1.0', 'enable_storage_optimizer': True}}) - # set an encryption key for database to let know TDLib how to open the database - if auth_state['@type'] == 'authorizationStateWaitEncryptionKey': - td_send({'@type': 'checkDatabaseEncryptionKey', 'encryption_key': ''}) - # enter phone number to log in if auth_state['@type'] == 'authorizationStateWaitPhoneNumber': phone_number = input('Please enter your phone number: ') diff --git a/example/swift/src/main.swift b/example/swift/src/main.swift index c0c6c088a..9fd9926e3 100644 --- a/example/swift/src/main.swift +++ b/example/swift/src/main.swift @@ -120,9 +120,6 @@ func updateAuthorizationState(authorizationState: Dictionary) { ] ]); - case "authorizationStateWaitEncryptionKey": - client.queryAsync(query: ["@type":"checkDatabaseEncryptionKey", "encryption_key":""]) - case "authorizationStateWaitPhoneNumber": print("Enter your phone number: ") let phone_number = myReadLine() diff --git a/example/uwp/app/MainPage.xaml.cs b/example/uwp/app/MainPage.xaml.cs index 068bf8a46..d1c39c4e3 100644 --- a/example/uwp/app/MainPage.xaml.cs +++ b/example/uwp/app/MainPage.xaml.cs @@ -46,7 +46,6 @@ namespace TdApp parameters.DeviceModel = "Desktop"; parameters.ApplicationVersion = "1.0.0"; _client.Send(new TdApi.SetTdlibParameters(parameters), null); - _client.Send(new TdApi.CheckDatabaseEncryptionKey(), null); } public void Print(String str) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index eaa7cbe1a..7fed1929d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -26,6 +26,7 @@ ok = Ok; //@use_test_dc If set to true, the Telegram test environment will be used instead of the production environment //@database_directory The path to the directory for the persistent database; if empty, the current working directory will be used //@files_directory The path to the directory for storing files; if empty, database_directory will be used +//@database_encryption_key Encryption key for the database //@use_file_database If set to true, information about downloaded and uploaded files will be saved between application restarts //@use_chat_info_database If set to true, the library will maintain a cache of users, basic groups, supergroups, channels and secret chats. Implies use_file_database //@use_message_database If set to true, the library will maintain a cache of chats and messages. Implies use_chat_info_database @@ -38,7 +39,7 @@ ok = Ok; //@application_version Application version; must be non-empty //@enable_storage_optimizer If set to true, old files will automatically be deleted //@ignore_file_names If set to true, original file names will be ignored. Otherwise, downloaded files will be saved under names as close as possible to the original name -tdlibParameters use_test_dc:Bool database_directory:string files_directory:string use_file_database:Bool use_chat_info_database:Bool use_message_database:Bool use_secret_chats:Bool api_id:int32 api_hash:string system_language_code:string device_model:string system_version:string application_version:string enable_storage_optimizer:Bool ignore_file_names:Bool = TdlibParameters; +tdlibParameters use_test_dc:Bool database_directory:string files_directory:string database_encryption_key:bytes use_file_database:Bool use_chat_info_database:Bool use_message_database:Bool use_secret_chats:Bool api_id:int32 api_hash:string system_language_code:string device_model:string system_version:string application_version:string enable_storage_optimizer:Bool ignore_file_names:Bool = TdlibParameters; //@class AuthenticationCodeType @description Provides information about the method by which an authentication code is delivered to the user @@ -98,9 +99,6 @@ termsOfService text:formattedText min_user_age:int32 show_popup:Bool = TermsOfSe //@description TDLib needs TdlibParameters for initialization authorizationStateWaitTdlibParameters = AuthorizationState; -//@description TDLib needs an encryption key to decrypt the local database @is_encrypted True, if the database is currently encrypted -authorizationStateWaitEncryptionKey is_encrypted:Bool = AuthorizationState; - //@description TDLib needs the user's phone number to authorize. Call `setAuthenticationPhoneNumber` to provide the phone number, or use `requestQrCodeAuthentication`, or `checkAuthenticationBotToken` for other authentication options authorizationStateWaitPhoneNumber = AuthorizationState; @@ -4629,9 +4627,6 @@ getAuthorizationState = AuthorizationState; //@description Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters @parameters Parameters for TDLib initialization setTdlibParameters parameters:tdlibParameters = Ok; -//@description Checks the database encryption key for correctness. Works only when the current authorization state is authorizationStateWaitEncryptionKey @encryption_key Encryption key to check or set up -checkDatabaseEncryptionKey encryption_key:bytes = Ok; - //@description Sets the phone number of the user and sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitPhoneNumber, //-or if there is no pending authentication query and the current authorization state is authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword //@phone_number The phone number of the user, in international format @settings Settings for the authentication of the user's phone number; pass null to use default settings diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3c6888e7d..ea073bc6d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2777,8 +2777,6 @@ void Td::set_is_bot_online(bool is_bot_online) { bool Td::is_authentication_request(int32 id) { switch (id) { case td_api::setTdlibParameters::ID: - case td_api::checkDatabaseEncryptionKey::ID: - case td_api::setDatabaseEncryptionKey::ID: case td_api::getAuthorizationState::ID: case td_api::setAuthenticationPhoneNumber::ID: case td_api::setAuthenticationEmailAddress::ID: @@ -2902,8 +2900,6 @@ td_api::object_ptr Td::get_fake_authorization_state_ switch (state_) { case State::WaitParameters: return td_api::make_object(); - case State::Decrypt: - return td_api::make_object(is_database_encrypted_); case State::Run: UNREACHABLE(); return nullptr; @@ -2963,10 +2959,6 @@ void Td::run_request(uint64 id, tl_object_ptr function) { pending_set_parameters_requests_.emplace_back(id, std::move(function)); return; } - if (init_request_id_ > 0) { - pending_init_requests_.emplace_back(id, std::move(function)); - return; - } int32 function_id = function->get_id(); if (state_ != State::Run) { @@ -3016,34 +3008,6 @@ void Td::run_request(uint64 id, tl_object_ptr function) { } break; } - case State::Decrypt: { - switch (function_id) { - case td_api::checkDatabaseEncryptionKey::ID: { - auto check_key = move_tl_object_as(function); - return start_init(id, std::move(check_key->encryption_key_)); - } - case td_api::setDatabaseEncryptionKey::ID: { - auto set_key = move_tl_object_as(function); - return start_init(id, std::move(set_key->new_encryption_key_)); - } - case td_api::destroy::ID: - // need to send response synchronously before actual destroying - send_closure(actor_id(this), &Td::send_result, id, td_api::make_object()); - send_closure(actor_id(this), &Td::destroy); - return; - default: - if (is_preinitialization_request(function_id)) { - break; - } - if (is_preauthentication_request(function_id)) { - pending_preauthentication_requests_.emplace_back(id, std::move(function)); - return; - } - return send_error_impl( - id, make_error(400, "Database encryption key is needed: call checkDatabaseEncryptionKey first")); - } - break; - } case State::Close: if (destroy_flag_) { return send_error_impl(id, make_error(401, "Unauthorized")); @@ -3503,11 +3467,8 @@ void Td::close_impl(bool destroy_flag) { } LOG(WARNING) << (destroy_flag ? "Destroy" : "Close") << " Td in state " << static_cast(state_); - if (state_ == State::WaitParameters || state_ == State::Decrypt) { + if (state_ == State::WaitParameters) { clear_requests(); - if (destroy_flag && state_ == State::Decrypt) { - TdDb::destroy(parameters_).ignore(); - } state_ = State::Close; close_flag_ = 4; G()->set_close_flag(); @@ -3591,14 +3552,12 @@ void Td::on_parameters_checked(Result r_checked_paramet parameters_.files_directory = std::move(checked_parameters.files_directory); is_database_encrypted_ = checked_parameters.is_database_encrypted; - state_ = State::Decrypt; - VLOG(td_init) << "Send authorizationStateWaitEncryptionKey"; - send_closure(actor_id(this), &Td::send_update, - td_api::make_object( - td_api::make_object(is_database_encrypted_))); - VLOG(td_init) << "Finish set parameters"; - send_closure(actor_id(this), &Td::send_result, set_parameters_request_id_, td_api::make_object()); - return finish_set_parameters(); + VLOG(td_init) << "Begin to init database"; + auto promise = PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { + send_closure(actor_id, &Td::init, std::move(r_opened_database)); + }); + TdDb::open(get_database_scheduler_id(), parameters_, as_db_key(std::move(database_encryption_key_)), + std::move(promise)); } void Td::finish_set_parameters() { @@ -3617,23 +3576,13 @@ void Td::finish_set_parameters() { CHECK(pending_set_parameters_requests_.size() < requests.size()); } -void Td::start_init(uint64 id, string &&key) { - VLOG(td_init) << "Begin to init database"; - init_request_id_ = id; - - auto promise = PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { - send_closure(actor_id, &Td::init, std::move(r_opened_database)); - }); - TdDb::open(get_database_scheduler_id(), parameters_, as_db_key(std::move(key)), std::move(promise)); -} - void Td::init(Result r_opened_database) { - CHECK(init_request_id_ != 0); + CHECK(set_parameters_request_id_ != 0); if (r_opened_database.is_error()) { LOG(WARNING) << "Failed to open database: " << r_opened_database.error(); - send_closure(actor_id(this), &Td::send_error, init_request_id_, + send_closure(actor_id(this), &Td::send_error, set_parameters_request_id_, Status::Error(400, r_opened_database.error().message())); - return finish_init(); + return finish_set_parameters(); } LOG(INFO) << "Successfully inited database in " << tag("database_directory", parameters_.database_directory) @@ -3776,24 +3725,8 @@ void Td::init(Result r_opened_database) { state_ = State::Run; - send_closure(actor_id(this), &Td::send_result, init_request_id_, td_api::make_object()); - return finish_init(); -} - -void Td::finish_init() { - CHECK(init_request_id_ > 0); - init_request_id_ = 0; - - if (pending_init_requests_.empty()) { - return; - } - - VLOG(td_init) << "Continue to execute " << pending_init_requests_.size() << " pending requests"; - auto requests = std::move(pending_init_requests_); - for (auto &request : requests) { - run_request(request.first, std::move(request.second)); - } - CHECK(pending_init_requests_.size() < requests.size()); + send_closure(actor_id(this), &Td::send_result, set_parameters_request_id_, td_api::make_object()); + return finish_set_parameters(); } void Td::init_options_and_network() { @@ -4238,6 +4171,8 @@ Status Td::set_parameters(td_api::object_ptr parameters options_.is_emulator = false; options_.proxy = Proxy(); + database_encryption_key_ = std::move(parameters->database_encryption_key_); + return Status::OK(); } @@ -4245,10 +4180,6 @@ void Td::on_request(uint64 id, const td_api::setTdlibParameters &request) { send_error_raw(id, 400, "Unexpected setTdlibParameters"); } -void Td::on_request(uint64 id, const td_api::checkDatabaseEncryptionKey &request) { - send_error_raw(id, 400, "Unexpected checkDatabaseEncryptionKey"); -} - void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) { CREATE_OK_REQUEST_PROMISE(); G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_)), std::move(promise)); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 9992fd5ed..2dc25d652 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -291,9 +291,9 @@ class Td final : public Actor { bool destroy_flag_ = false; int close_flag_ = 0; - enum class State : int32 { WaitParameters, Decrypt, Run, Close } state_ = State::WaitParameters; - uint64 init_request_id_ = 0; + enum class State : int32 { WaitParameters, Run, Close } state_ = State::WaitParameters; uint64 set_parameters_request_id_ = 0; + string database_encryption_key_; bool is_database_encrypted_ = false; FlatHashMap> result_handlers_; @@ -390,10 +390,6 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::setTdlibParameters &request); - void on_request(uint64 id, const td_api::checkDatabaseEncryptionKey &request); - - void on_request(uint64 id, td_api::setDatabaseEncryptionKey &request); - void on_request(uint64 id, const td_api::getAuthorizationState &request); void on_request(uint64 id, td_api::setAuthenticationPhoneNumber &request); @@ -428,6 +424,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::confirmQrCodeAuthentication &request); + void on_request(uint64 id, td_api::setDatabaseEncryptionKey &request); + void on_request(uint64 id, const td_api::getCurrentState &request); void on_request(uint64 id, td_api::getPasswordState &request); @@ -1470,8 +1468,6 @@ class Td final : public Actor { void finish_set_parameters(); - void start_init(uint64 id, string &&key); - void init(Result r_opened_database); void init_options_and_network(); @@ -1482,8 +1478,6 @@ class Td final : public Actor { void init_managers(); - void finish_init(); - void clear(); void close_impl(bool destroy_flag); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 57b1ac58b..b450d5fbf 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -415,9 +415,6 @@ class CliClient final : public Actor { send_request(td_api::make_object(std::move(parameters))); break; } - case td_api::authorizationStateWaitEncryptionKey::ID: - send_request(td_api::make_object()); - break; case td_api::authorizationStateReady::ID: LOG(INFO) << "Logged in"; break; @@ -1857,9 +1854,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "rac") { send_request(td_api::make_object()); - } else if (op == "cdek" || op == "CheckDatabaseEncryptionKey") { - send_request(td_api::make_object(args)); - } else if (op == "sdek" || op == "SetDatabaseEncryptionKey") { + } else if (op == "sdek") { send_request(td_api::make_object(args)); } else if (op == "caec") { send_request(td_api::make_object(as_email_address_authentication(args))); diff --git a/test/online.cpp b/test/online.cpp index db6832886..d4339f558 100644 --- a/test/online.cpp +++ b/test/online.cpp @@ -230,9 +230,6 @@ class InitTask : public Task { start_flag_ = true; td::tl_object_ptr function; switch (authorization_state->get_id()) { - case td::td_api::authorizationStateWaitEncryptionKey::ID: - send(td::make_tl_object()); - break; case td::td_api::authorizationStateReady::ID: promise_.set_value({}); stop(); diff --git a/test/tdclient.cpp b/test/tdclient.cpp index 81cb2aad4..fe2207b78 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -211,9 +211,6 @@ class DoAuthentication final : public TestClinetTask { start_flag_ = true; td::tl_object_ptr function; switch (authorization_state->get_id()) { - case td::td_api::authorizationStateWaitEncryptionKey::ID: - function = td::make_tl_object(); - break; case td::td_api::authorizationStateWaitPhoneNumber::ID: function = td::make_tl_object(phone_, nullptr); break; From c47da24430b543f84a49ff21c5331dcf3e7faa5b Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 21:32:40 +0300 Subject: [PATCH 103/200] Remove unused is_database_encrypted. --- td/telegram/Td.cpp | 1 - td/telegram/Td.h | 1 - td/telegram/TdDb.cpp | 9 --------- td/telegram/TdDb.h | 1 - 4 files changed, 12 deletions(-) diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index ea073bc6d..76b964f72 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3550,7 +3550,6 @@ void Td::on_parameters_checked(Result r_checked_paramet parameters_.database_directory = std::move(checked_parameters.database_directory); parameters_.files_directory = std::move(checked_parameters.files_directory); - is_database_encrypted_ = checked_parameters.is_database_encrypted; VLOG(td_init) << "Begin to init database"; auto promise = PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 2dc25d652..517d82cc4 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -294,7 +294,6 @@ class Td final : public Actor { enum class State : int32 { WaitParameters, Run, Close } state_ = State::WaitParameters; uint64 set_parameters_request_id_ = 0; string database_encryption_key_; - bool is_database_encrypted_ = false; FlatHashMap> result_handlers_; enum : int8 { RequestActorIdType = 1, ActorIdType = 2 }; diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 96eb70ab5..c1176237b 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -519,15 +519,6 @@ void TdDb::check_parameters_impl(TdParameters parameters, Promise promise); From ebb6770935882f7ffe8fca71ad64ab0fccb5da72 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 21:50:41 +0300 Subject: [PATCH 104/200] Combine TdDb::check_parameters and TdDb::open. --- td/telegram/Td.cpp | 35 ++++++++++------------------------- td/telegram/Td.h | 2 -- td/telegram/TdDb.cpp | 31 ++++++++++++------------------- td/telegram/TdDb.h | 7 ++----- 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 76b964f72..a0be1bde1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2987,13 +2987,15 @@ void Td::run_request(uint64 id, tl_object_ptr function) { return send_closure(actor_id(this), &Td::send_error, id, std::move(status)); } - VLOG(td_init) << "Begin to check parameters"; + VLOG(td_init) << "Begin to open database"; set_parameters_request_id_ = id; + auto promise = - PromiseCreator::lambda([actor_id = actor_id(this)](Result r_checked_parameters) { - send_closure(actor_id, &Td::on_parameters_checked, std::move(r_checked_parameters)); + PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { + send_closure(actor_id, &Td::init, std::move(r_opened_database)); }); - return TdDb::check_parameters(get_database_scheduler_id(), parameters_, std::move(promise)); + return TdDb::open(get_database_scheduler_id(), parameters_, as_db_key(std::move(database_encryption_key_)), + std::move(promise)); } default: if (is_preinitialization_request(function_id)) { @@ -3539,26 +3541,6 @@ int32 Td::get_database_scheduler_id() { return min(current_scheduler_id + 1, scheduler_count - 1); } -void Td::on_parameters_checked(Result r_checked_parameters) { - CHECK(set_parameters_request_id_ != 0); - if (r_checked_parameters.is_error()) { - send_closure(actor_id(this), &Td::send_error, set_parameters_request_id_, - Status::Error(400, r_checked_parameters.error().message())); - return finish_set_parameters(); - } - auto checked_parameters = r_checked_parameters.move_as_ok(); - - parameters_.database_directory = std::move(checked_parameters.database_directory); - parameters_.files_directory = std::move(checked_parameters.files_directory); - - VLOG(td_init) << "Begin to init database"; - auto promise = PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { - send_closure(actor_id, &Td::init, std::move(r_opened_database)); - }); - TdDb::open(get_database_scheduler_id(), parameters_, as_db_key(std::move(database_encryption_key_)), - std::move(promise)); -} - void Td::finish_set_parameters() { CHECK(set_parameters_request_id_ != 0); set_parameters_request_id_ = 0; @@ -3583,12 +3565,15 @@ void Td::init(Result r_opened_database) { Status::Error(400, r_opened_database.error().message())); return finish_set_parameters(); } + auto events = r_opened_database.move_as_ok(); + + parameters_.database_directory = std::move(events.database_directory); + parameters_.files_directory = std::move(events.files_directory); LOG(INFO) << "Successfully inited database in " << tag("database_directory", parameters_.database_directory) << " and " << tag("files_directory", parameters_.files_directory); VLOG(td_init) << "Successfully inited database"; - auto events = r_opened_database.move_as_ok(); G()->init(parameters_, actor_id(this), std::move(events.database)).ensure(); init_options_and_network(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 517d82cc4..9a8d3cefb 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1463,8 +1463,6 @@ class Td final : public Actor { static int32 get_database_scheduler_id(); - void on_parameters_checked(Result r_checked_parameters); - void finish_set_parameters(); void init(Result r_opened_database); diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index c1176237b..3cdbac1c7 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -385,7 +385,11 @@ void TdDb::open(int32 scheduler_id, TdParameters parameters, DbKey key, Promise< } void TdDb::open_impl(TdParameters parameters, DbKey key, Promise &&promise) { + TRY_STATUS_PROMISE(promise, check_parameters(parameters)); + OpenedDatabase result; + result.database_directory = parameters.database_directory; + result.files_directory = parameters.files_directory; // Init pmc Binlog *binlog_ptr = nullptr; @@ -478,16 +482,7 @@ void TdDb::open_impl(TdParameters parameters, DbKey key, Promise TdDb::TdDb() = default; TdDb::~TdDb() = default; -void TdDb::check_parameters(int32 scheduler_id, TdParameters parameters, Promise promise) { - Scheduler::instance()->run_on_scheduler( - scheduler_id, [parameters = std::move(parameters), promise = std::move(promise)](Unit) mutable { - TdDb::check_parameters_impl(std::move(parameters), std::move(promise)); - }); -} - -void TdDb::check_parameters_impl(TdParameters parameters, Promise promise) { - CheckedParameters result; - +Status TdDb::check_parameters(TdParameters ¶meters) { auto prepare_dir = [](string dir) -> Result { CHECK(!dir.empty()); if (dir.back() != TD_DIR_SLASH) { @@ -504,22 +499,20 @@ void TdDb::check_parameters_impl(TdParameters parameters, Promise promise) { diff --git a/td/telegram/TdDb.h b/td/telegram/TdDb.h index cf7b408aa..f249f2cc5 100644 --- a/td/telegram/TdDb.h +++ b/td/telegram/TdDb.h @@ -47,13 +47,10 @@ class TdDb { TdDb &operator=(TdDb &&) = delete; ~TdDb(); - struct CheckedParameters { + struct OpenedDatabase { string database_directory; string files_directory; - }; - static void check_parameters(int32 scheduler_id, TdParameters parameters, Promise promise); - struct OpenedDatabase { unique_ptr database; vector to_secret_chats_manager; @@ -126,7 +123,7 @@ class TdDb { static void open_impl(TdParameters parameters, DbKey key, Promise &&promise); - static void check_parameters_impl(TdParameters parameters, Promise promise); + static Status check_parameters(TdParameters ¶meters); Status init_sqlite(const TdParameters ¶meters, const DbKey &key, const DbKey &old_key, BinlogKeyValue &binlog_pmc); From f6a2ecdded78373cbde0dbac8ce5d97adb08193a Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 22:19:08 +0300 Subject: [PATCH 105/200] Inline tdlibParameters in setTdlibParameters. --- example/cpp/td_example.cpp | 23 +++++----- example/csharp/TdExample.cs | 22 +++++----- .../org/drinkless/tdlib/example/Example.java | 22 +++++----- example/python/tdjson_example.py | 20 ++++----- example/swift/src/main.swift | 20 ++++----- example/uwp/app/MainPage.xaml.cs | 20 ++++----- example/web/tdweb/src/worker.js | 12 +++--- td/generate/scheme/td_api.tl | 42 +++++++++---------- td/telegram/Td.cpp | 5 ++- td/telegram/Td.h | 2 +- td/telegram/cli.cpp | 32 +++++++------- test/online.cpp | 25 ++++++----- test/tdclient.cpp | 25 ++++++----- 13 files changed, 131 insertions(+), 139 deletions(-) diff --git a/example/cpp/td_example.cpp b/example/cpp/td_example.cpp index a78d4c53c..4ba34490f 100644 --- a/example/cpp/td_example.cpp +++ b/example/cpp/td_example.cpp @@ -290,18 +290,17 @@ class TdExample { create_authentication_query_handler()); }, [this](td_api::authorizationStateWaitTdlibParameters &) { - auto parameters = td_api::make_object(); - parameters->database_directory_ = "tdlib"; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = 94575; - parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->application_version_ = "1.0"; - parameters->enable_storage_optimizer_ = true; - send_query(td_api::make_object(std::move(parameters)), - create_authentication_query_handler()); + auto request = td_api::make_object(); + request->database_directory_ = "tdlib"; + request->use_message_database_ = true; + request->use_secret_chats_ = true; + request->api_id_ = 94575; + request->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; + request->system_language_code_ = "en"; + request->device_model_ = "Desktop"; + request->application_version_ = "1.0"; + request->enable_storage_optimizer_ = true; + send_query(std::move(request), create_authentication_query_handler()); })); } diff --git a/example/csharp/TdExample.cs b/example/csharp/TdExample.cs index 3c57a398c..469656572 100644 --- a/example/csharp/TdExample.cs +++ b/example/csharp/TdExample.cs @@ -67,18 +67,18 @@ namespace TdExample } if (_authorizationState is TdApi.AuthorizationStateWaitTdlibParameters) { - TdApi.TdlibParameters parameters = new TdApi.TdlibParameters(); - parameters.DatabaseDirectory = "tdlib"; - parameters.UseMessageDatabase = true; - parameters.UseSecretChats = true; - parameters.ApiId = 94575; - parameters.ApiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters.SystemLanguageCode = "en"; - parameters.DeviceModel = "Desktop"; - parameters.ApplicationVersion = "1.0"; - parameters.EnableStorageOptimizer = true; + TdApi.SetTdlibParameters request = new TdApi.SetTdlibParameters(); + request.DatabaseDirectory = "tdlib"; + request.UseMessageDatabase = true; + request.UseSecretChats = true; + request.ApiId = 94575; + request.ApiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; + request.SystemLanguageCode = "en"; + request.DeviceModel = "Desktop"; + request.ApplicationVersion = "1.0"; + request.EnableStorageOptimizer = true; - _client.Send(new TdApi.SetTdlibParameters(parameters), new AuthorizationRequestHandler()); + _client.Send(request, new AuthorizationRequestHandler()); } else if (_authorizationState is TdApi.AuthorizationStateWaitPhoneNumber) { diff --git a/example/java/org/drinkless/tdlib/example/Example.java b/example/java/org/drinkless/tdlib/example/Example.java index 133585904..7bda83960 100644 --- a/example/java/org/drinkless/tdlib/example/Example.java +++ b/example/java/org/drinkless/tdlib/example/Example.java @@ -101,18 +101,18 @@ public final class Example { } switch (Example.authorizationState.getConstructor()) { case TdApi.AuthorizationStateWaitTdlibParameters.CONSTRUCTOR: - TdApi.TdlibParameters parameters = new TdApi.TdlibParameters(); - parameters.databaseDirectory = "tdlib"; - parameters.useMessageDatabase = true; - parameters.useSecretChats = true; - parameters.apiId = 94575; - parameters.apiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters.systemLanguageCode = "en"; - parameters.deviceModel = "Desktop"; - parameters.applicationVersion = "1.0"; - parameters.enableStorageOptimizer = true; + TdApi.SetTdlibParameters request = new TdApi.SetTdlibParameters(); + request.databaseDirectory = "tdlib"; + request.useMessageDatabase = true; + request.useSecretChats = true; + request.apiId = 94575; + request.apiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; + request.systemLanguageCode = "en"; + request.deviceModel = "Desktop"; + request.applicationVersion = "1.0"; + request.enableStorageOptimizer = true; - client.send(new TdApi.SetTdlibParameters(parameters), new AuthorizationRequestHandler()); + client.send(parameters, new AuthorizationRequestHandler()); break; case TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: { String phoneNumber = promptString("Please enter phone number: "); diff --git a/example/python/tdjson_example.py b/example/python/tdjson_example.py index d3e4516e5..986e4a37a 100644 --- a/example/python/tdjson_example.py +++ b/example/python/tdjson_example.py @@ -94,16 +94,16 @@ while True: # you MUST obtain your own api_id and api_hash at https://my.telegram.org # and use them in the setTdlibParameters call if auth_state['@type'] == 'authorizationStateWaitTdlibParameters': - td_send({'@type': 'setTdlibParameters', 'parameters': { - 'database_directory': 'tdlib', - 'use_message_database': True, - 'use_secret_chats': True, - 'api_id': 94575, - 'api_hash': 'a3406de8d171bb422bb6ddf3bbd800e2', - 'system_language_code': 'en', - 'device_model': 'Desktop', - 'application_version': '1.0', - 'enable_storage_optimizer': True}}) + td_send({'@type': 'setTdlibParameters', + 'database_directory': 'tdlib', + 'use_message_database': True, + 'use_secret_chats': True, + 'api_id': 94575, + 'api_hash': 'a3406de8d171bb422bb6ddf3bbd800e2', + 'system_language_code': 'en', + 'device_model': 'Desktop', + 'application_version': '1.0', + 'enable_storage_optimizer': True}) # enter phone number to log in if auth_state['@type'] == 'authorizationStateWaitPhoneNumber': diff --git a/example/swift/src/main.swift b/example/swift/src/main.swift index 9fd9926e3..bbee661f7 100644 --- a/example/swift/src/main.swift +++ b/example/swift/src/main.swift @@ -107,17 +107,15 @@ func updateAuthorizationState(authorizationState: Dictionary) { case "authorizationStateWaitTdlibParameters": client.queryAsync(query:[ "@type":"setTdlibParameters", - "parameters":[ - "database_directory":"tdlib", - "use_message_database":true, - "use_secret_chats":true, - "api_id":94575, - "api_hash":"a3406de8d171bb422bb6ddf3bbd800e2", - "system_language_code":"en", - "device_model":"Desktop", - "application_version":"1.0", - "enable_storage_optimizer":true - ] + "database_directory":"tdlib", + "use_message_database":true, + "use_secret_chats":true, + "api_id":94575, + "api_hash":"a3406de8d171bb422bb6ddf3bbd800e2", + "system_language_code":"en", + "device_model":"Desktop", + "application_version":"1.0", + "enable_storage_optimizer":true ]); case "authorizationStateWaitPhoneNumber": diff --git a/example/uwp/app/MainPage.xaml.cs b/example/uwp/app/MainPage.xaml.cs index d1c39c4e3..9be3f6944 100644 --- a/example/uwp/app/MainPage.xaml.cs +++ b/example/uwp/app/MainPage.xaml.cs @@ -36,16 +36,16 @@ namespace TdApp }); _client = Td.Client.Create(_handler); - var parameters = new TdApi.TdlibParameters(); - parameters.DatabaseDirectory = Windows.Storage.ApplicationData.Current.LocalFolder.Path; - parameters.UseSecretChats = true; - parameters.UseMessageDatabase = true; - parameters.ApiId = 94575; - parameters.ApiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters.SystemLanguageCode = "en"; - parameters.DeviceModel = "Desktop"; - parameters.ApplicationVersion = "1.0.0"; - _client.Send(new TdApi.SetTdlibParameters(parameters), null); + var request = new TdApi.SetTdlibParameters(); + request.DatabaseDirectory = Windows.Storage.ApplicationData.Current.LocalFolder.Path; + request.UseSecretChats = true; + request.UseMessageDatabase = true; + request.ApiId = 94575; + request.ApiHash = "a3406de8d171bb422bb6ddf3bbd800e2"; + request.SystemLanguageCode = "en"; + request.DeviceModel = "Desktop"; + request.ApplicationVersion = "1.0.0"; + _client.Send(request, null); } public void Print(String str) diff --git a/example/web/tdweb/src/worker.js b/example/web/tdweb/src/worker.js index abc087c44..dff184512 100644 --- a/example/web/tdweb/src/worker.js +++ b/example/web/tdweb/src/worker.js @@ -734,14 +734,14 @@ class TdClient { prepareQuery(query) { if (query['@type'] === 'setTdlibParameters') { - query.parameters.database_directory = this.tdfs.dbFileSystem.root; - query.parameters.files_directory = this.tdfs.inboundFileSystem.root; + query.database_directory = this.tdfs.dbFileSystem.root; + query.files_directory = this.tdfs.inboundFileSystem.root; const useDb = this.useDatabase; - query.parameters.use_file_database = useDb; - query.parameters.use_chat_info_database = useDb; - query.parameters.use_message_database = useDb; - query.parameters.use_secret_chats = useDb; + query.use_file_database = useDb; + query.use_chat_info_database = useDb; + query.use_message_database = useDb; + query.use_secret_chats = useDb; } if (query['@type'] === 'getLanguagePackString') { query.language_pack_database_path = diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 7fed1929d..727ed25d3 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -22,26 +22,6 @@ error code:int32 message:string = Error; ok = Ok; -//@description Contains parameters for TDLib initialization -//@use_test_dc If set to true, the Telegram test environment will be used instead of the production environment -//@database_directory The path to the directory for the persistent database; if empty, the current working directory will be used -//@files_directory The path to the directory for storing files; if empty, database_directory will be used -//@database_encryption_key Encryption key for the database -//@use_file_database If set to true, information about downloaded and uploaded files will be saved between application restarts -//@use_chat_info_database If set to true, the library will maintain a cache of users, basic groups, supergroups, channels and secret chats. Implies use_file_database -//@use_message_database If set to true, the library will maintain a cache of chats and messages. Implies use_chat_info_database -//@use_secret_chats If set to true, support for secret chats will be enabled -//@api_id Application identifier for Telegram API access, which can be obtained at https://my.telegram.org -//@api_hash Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org -//@system_language_code IETF language tag of the user's operating system language; must be non-empty -//@device_model Model of the device the application is being run on; must be non-empty -//@system_version Version of the operating system the application is being run on. If empty, the version is automatically detected by TDLib -//@application_version Application version; must be non-empty -//@enable_storage_optimizer If set to true, old files will automatically be deleted -//@ignore_file_names If set to true, original file names will be ignored. Otherwise, downloaded files will be saved under names as close as possible to the original name -tdlibParameters use_test_dc:Bool database_directory:string files_directory:string database_encryption_key:bytes use_file_database:Bool use_chat_info_database:Bool use_message_database:Bool use_secret_chats:Bool api_id:int32 api_hash:string system_language_code:string device_model:string system_version:string application_version:string enable_storage_optimizer:Bool ignore_file_names:Bool = TdlibParameters; - - //@class AuthenticationCodeType @description Provides information about the method by which an authentication code is delivered to the user //@description An authentication code is delivered via a private Telegram message, which can be viewed from another active session @length Length of the code @@ -96,7 +76,7 @@ termsOfService text:formattedText min_user_age:int32 show_popup:Bool = TermsOfSe //@class AuthorizationState @description Represents the current authorization state of the TDLib client -//@description TDLib needs TdlibParameters for initialization +//@description Initializetion parameters are needed. Call `setTdlibParameters` to provide them authorizationStateWaitTdlibParameters = AuthorizationState; //@description TDLib needs the user's phone number to authorize. Call `setAuthenticationPhoneNumber` to provide the phone number, or use `requestQrCodeAuthentication`, or `checkAuthenticationBotToken` for other authentication options @@ -4624,8 +4604,24 @@ testVectorStringObject value:vector = TestVectorStringObject; getAuthorizationState = AuthorizationState; -//@description Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters @parameters Parameters for TDLib initialization -setTdlibParameters parameters:tdlibParameters = Ok; +//@description Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters +//@use_test_dc Pass true to use Telegram test environment instead of the production environment +//@database_directory The path to the directory for the persistent database; if empty, the current working directory will be used +//@files_directory The path to the directory for storing files; if empty, database_directory will be used +//@database_encryption_key Encryption key for the database +//@use_file_database Pass true to keep information about downloaded and uploaded files between application restarts +//@use_chat_info_database Pass true to keep cache of users, basic groups, supergroups, channels and secret chats between restarts. Implies use_file_database +//@use_message_database Pass true to keep cache of chats and messages between restarts. Implies use_chat_info_database +//@use_secret_chats Pass true to enable support for secret chats +//@api_id Application identifier for Telegram API access, which can be obtained at https://my.telegram.org +//@api_hash Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org +//@system_language_code IETF language tag of the user's operating system language; must be non-empty +//@device_model Model of the device the application is being run on; must be non-empty +//@system_version Version of the operating system the application is being run on. If empty, the version is automatically detected by TDLib +//@application_version Application version; must be non-empty +//@enable_storage_optimizer Pass true to automatically delete old files in background +//@ignore_file_names Pass true to ignore original file names for downloaded files. Otherwise, downloaded files are saved under names as close as possible to the original name +setTdlibParameters use_test_dc:Bool database_directory:string files_directory:string database_encryption_key:bytes use_file_database:Bool use_chat_info_database:Bool use_message_database:Bool use_secret_chats:Bool api_id:int32 api_hash:string system_language_code:string device_model:string system_version:string application_version:string enable_storage_optimizer:Bool ignore_file_names:Bool = Ok; //@description Sets the phone number of the user and sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitPhoneNumber, //-or if there is no pending authentication query and the current authorization state is authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index a0be1bde1..7fe11571d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2982,7 +2982,8 @@ void Td::run_request(uint64 id, tl_object_ptr function) { case State::WaitParameters: { switch (function_id) { case td_api::setTdlibParameters::ID: { - auto status = set_parameters(std::move(move_tl_object_as(function)->parameters_)); + auto parameters = move_tl_object_as(function); + auto status = set_parameters(std::move(parameters)); if (status.is_error()) { return send_closure(actor_id(this), &Td::send_error, id, std::move(status)); } @@ -4096,7 +4097,7 @@ Status Td::fix_parameters(TdParameters ¶meters) { return Status::OK(); } -Status Td::set_parameters(td_api::object_ptr parameters) { +Status Td::set_parameters(td_api::object_ptr parameters) { VLOG(td_init) << "Begin to set TDLib parameters"; if (parameters == nullptr) { VLOG(td_init) << "Empty parameters"; diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 9a8d3cefb..915a29ec6 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1481,7 +1481,7 @@ class Td final : public Actor { static Status fix_parameters(TdParameters ¶meters) TD_WARN_UNUSED_RESULT; - Status set_parameters(td_api::object_ptr parameters) TD_WARN_UNUSED_RESULT; + Status set_parameters(td_api::object_ptr parameters) TD_WARN_UNUSED_RESULT; static td_api::object_ptr make_error(int32 code, CSlice error) { return td_api::make_object(code, error.str()); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b450d5fbf..a1a7a5839 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -400,19 +400,19 @@ class CliClient final : public Actor { authorization_state_ = std::move(state); switch (authorization_state_->get_id()) { case td_api::authorizationStateWaitTdlibParameters::ID: { - auto parameters = td_api::make_object(); - parameters->use_test_dc_ = use_test_dc_; - parameters->use_message_database_ = true; - parameters->use_chat_info_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = api_id_; - parameters->api_hash_ = api_hash_; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->application_version_ = "1.0"; + auto request = td_api::make_object(); + request->use_test_dc_ = use_test_dc_; + request->use_message_database_ = true; + request->use_chat_info_database_ = true; + request->use_secret_chats_ = true; + request->api_id_ = api_id_; + request->api_hash_ = api_hash_; + request->system_language_code_ = "en"; + request->device_model_ = "Desktop"; + request->application_version_ = "1.0"; send_request( td_api::make_object("use_pfs", td_api::make_object(true))); - send_request(td_api::make_object(std::move(parameters))); + send_request(std::move(request)); break; } case td_api::authorizationStateReady::ID: @@ -1162,11 +1162,11 @@ class CliClient final : public Actor { td_api::make_object())); send_request(td_api::make_object(0)); - auto bad_parameters = td_api::make_object(); - bad_parameters->database_directory_ = "/.."; - bad_parameters->api_id_ = api_id_; - bad_parameters->api_hash_ = api_hash_; - send_request(td_api::make_object(std::move(bad_parameters))); + auto bad_request = td_api::make_object(); + bad_request->database_directory_ = "/.."; + bad_request->api_id_ = api_id_; + bad_request->api_hash_ = api_hash_; + send_request(std::move(bad_request)); } } diff --git a/test/online.cpp b/test/online.cpp index d4339f558..f472c6ae8 100644 --- a/test/online.cpp +++ b/test/online.cpp @@ -235,19 +235,18 @@ class InitTask : public Task { stop(); break; case td::td_api::authorizationStateWaitTdlibParameters::ID: { - auto parameters = td::td_api::make_object(); - parameters->use_test_dc_ = true; - parameters->database_directory_ = options_.name + TD_DIR_SLASH; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = options_.api_id; - parameters->api_hash_ = options_.api_hash; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->application_version_ = "tdclient-test"; - parameters->ignore_file_names_ = false; - parameters->enable_storage_optimizer_ = true; - send(td::td_api::make_object(std::move(parameters))); + auto request = td::td_api::make_object(); + request->use_test_dc_ = true; + request->database_directory_ = options_.name + TD_DIR_SLASH; + request->use_message_database_ = true; + request->use_secret_chats_ = true; + request->api_id_ = options_.api_id; + request->api_hash_ = options_.api_hash; + request->system_language_code_ = "en"; + request->device_model_ = "Desktop"; + request->application_version_ = "tdclient-test"; + request->enable_storage_optimizer_ = true; + send(std::move(request)); break; } default: diff --git a/test/tdclient.cpp b/test/tdclient.cpp index fe2207b78..862cb7903 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -221,19 +221,18 @@ class DoAuthentication final : public TestClinetTask { function = td::make_tl_object(name_, ""); break; case td::td_api::authorizationStateWaitTdlibParameters::ID: { - auto parameters = td::td_api::make_object(); - parameters->use_test_dc_ = true; - parameters->database_directory_ = name_ + TD_DIR_SLASH; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = 94575; - parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->application_version_ = "tdclient-test"; - parameters->ignore_file_names_ = false; - parameters->enable_storage_optimizer_ = true; - function = td::td_api::make_object(std::move(parameters)); + auto request = td::td_api::make_object(); + request->use_test_dc_ = true; + request->database_directory_ = name_ + TD_DIR_SLASH; + request->use_message_database_ = true; + request->use_secret_chats_ = true; + request->api_id_ = 94575; + request->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; + request->system_language_code_ = "en"; + request->device_model_ = "Desktop"; + request->application_version_ = "tdclient-test"; + request->enable_storage_optimizer_ = true; + function = std::move(request); break; } case td::td_api::authorizationStateReady::ID: From d4d746f02a5b69960a90386bdab3695aa0094eb1 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 7 Sep 2022 22:31:26 +0300 Subject: [PATCH 106/200] Pass database_encryption_key through a local variable. --- td/telegram/Td.cpp | 10 ++-------- td/telegram/Td.h | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7fe11571d..4f4299216 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2983,6 +2983,7 @@ void Td::run_request(uint64 id, tl_object_ptr function) { switch (function_id) { case td_api::setTdlibParameters::ID: { auto parameters = move_tl_object_as(function); + auto database_encryption_key = as_db_key(std::move(parameters->database_encryption_key_)); auto status = set_parameters(std::move(parameters)); if (status.is_error()) { return send_closure(actor_id(this), &Td::send_error, id, std::move(status)); @@ -2995,7 +2996,7 @@ void Td::run_request(uint64 id, tl_object_ptr function) { PromiseCreator::lambda([actor_id = actor_id(this)](Result r_opened_database) { send_closure(actor_id, &Td::init, std::move(r_opened_database)); }); - return TdDb::open(get_database_scheduler_id(), parameters_, as_db_key(std::move(database_encryption_key_)), + return TdDb::open(get_database_scheduler_id(), parameters_, std::move(database_encryption_key), std::move(promise)); } default: @@ -4099,11 +4100,6 @@ Status Td::fix_parameters(TdParameters ¶meters) { Status Td::set_parameters(td_api::object_ptr parameters) { VLOG(td_init) << "Begin to set TDLib parameters"; - if (parameters == nullptr) { - VLOG(td_init) << "Empty parameters"; - return Status::Error(400, "Parameters aren't specified"); - } - if (!clean_input_string(parameters->api_hash_) || !clean_input_string(parameters->system_language_code_) || !clean_input_string(parameters->device_model_) || !clean_input_string(parameters->system_version_) || !clean_input_string(parameters->application_version_)) { @@ -4156,8 +4152,6 @@ Status Td::set_parameters(td_api::object_ptr paramet options_.is_emulator = false; options_.proxy = Proxy(); - database_encryption_key_ = std::move(parameters->database_encryption_key_); - return Status::OK(); } diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 915a29ec6..a9384a249 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -293,7 +293,6 @@ class Td final : public Actor { enum class State : int32 { WaitParameters, Run, Close } state_ = State::WaitParameters; uint64 set_parameters_request_id_ = 0; - string database_encryption_key_; FlatHashMap> result_handlers_; enum : int8 { RequestActorIdType = 1, ActorIdType = 2 }; From 8d32a1e143c866440b5de549836e7e21c1f60efe Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 00:41:35 +0300 Subject: [PATCH 107/200] =?UTF-8?q?Update=20=D0=A1++=20example.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/cpp/td_example.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/example/cpp/td_example.cpp b/example/cpp/td_example.cpp index 4ba34490f..3b6cf42ed 100644 --- a/example/cpp/td_example.cpp +++ b/example/cpp/td_example.cpp @@ -254,6 +254,29 @@ class TdExample { need_restart_ = true; std::cout << "Terminated" << std::endl; }, + [this](td_api::authorizationStateWaitPhoneNumber &) { + std::cout << "Enter phone number: " << std::flush; + std::string phone_number; + std::cin >> phone_number; + send_query( + td_api::make_object(phone_number, nullptr), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitEmailAddress &) { + std::cout << "Enter email address: " << std::flush; + std::string email_address; + std::cin >> email_address; + send_query(td_api::make_object(email_address), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitEmailCode &) { + std::cout << "Enter email authentication code: " << std::flush; + std::string code; + std::cin >> code; + send_query(td_api::make_object( + td_api::make_object(code)), + create_authentication_query_handler()); + }, [this](td_api::authorizationStateWaitCode &) { std::cout << "Enter authentication code: " << std::flush; std::string code; @@ -281,14 +304,6 @@ class TdExample { [this](td_api::authorizationStateWaitOtherDeviceConfirmation &state) { std::cout << "Confirm this login link on another device: " << state.link_ << std::endl; }, - [this](td_api::authorizationStateWaitPhoneNumber &) { - std::cout << "Enter phone number: " << std::flush; - std::string phone_number; - std::cin >> phone_number; - send_query( - td_api::make_object(phone_number, nullptr), - create_authentication_query_handler()); - }, [this](td_api::authorizationStateWaitTdlibParameters &) { auto request = td_api::make_object(); request->database_directory_ = "tdlib"; From e8d78263b958dfe5640ee98b2e75b3f45503bccb Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 08:48:11 +0300 Subject: [PATCH 108/200] Support new authorization flow in tdclient test. --- test/tdclient.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/tdclient.cpp b/test/tdclient.cpp index 862cb7903..d2a5a3afb 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -214,6 +214,13 @@ class DoAuthentication final : public TestClinetTask { case td::td_api::authorizationStateWaitPhoneNumber::ID: function = td::make_tl_object(phone_, nullptr); break; + case td::td_api::authorizationStateWaitEmailAddress::ID: + function = td::make_tl_object("alice_test@gmail.com"); + break; + case td::td_api::authorizationStateWaitEmailCode::ID: + function = td::make_tl_object( + td::make_tl_object(code_)); + break; case td::td_api::authorizationStateWaitCode::ID: function = td::make_tl_object(code_); break; From d14e3274fd9e3de7327543ca00bada27ccdf485b Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 12:24:56 +0300 Subject: [PATCH 109/200] Update C# example. --- example/csharp/TdExample.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/example/csharp/TdExample.cs b/example/csharp/TdExample.cs index 469656572..0c07ee7c7 100644 --- a/example/csharp/TdExample.cs +++ b/example/csharp/TdExample.cs @@ -85,6 +85,16 @@ namespace TdExample string phoneNumber = ReadLine("Please enter phone number: "); _client.Send(new TdApi.SetAuthenticationPhoneNumber(phoneNumber, null), new AuthorizationRequestHandler()); } + else if (_authorizationState is TdApi.AuthorizationStateWaitEmailAddress) + { + string emailAddress = ReadLine("Please enter email address: "); + _client.Send(new TdApi.SetAuthenticationEmailAddress(emailAddress), new AuthorizationRequestHandler()); + } + else if (_authorizationState is TdApi.AuthorizationStateWaitEmailCode) + { + string code = ReadLine("Please enter email authentication code: "); + _client.Send(new TdApi.CheckAuthenticationEmailCode(new TdApi.EmailAddressAuthenticationCode(code)), new AuthorizationRequestHandler()); + } else if (_authorizationState is TdApi.AuthorizationStateWaitOtherDeviceConfirmation state) { Console.WriteLine("Please confirm this login link on another device: " + state.Link); From ffdef31e0b6193f6467d977a1907e4459869bd87 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 12:34:33 +0300 Subject: [PATCH 110/200] Update UWP example. --- example/uwp/app/MainPage.xaml.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/example/uwp/app/MainPage.xaml.cs b/example/uwp/app/MainPage.xaml.cs index 9be3f6944..4c42e2767 100644 --- a/example/uwp/app/MainPage.xaml.cs +++ b/example/uwp/app/MainPage.xaml.cs @@ -96,6 +96,18 @@ namespace TdApp AcceptCommand(command); _client.Send(new TdApi.SetAuthenticationPhoneNumber(args[1], null), _handler); } + else if (command.StartsWith("sae")) + { + var args = command.Split(" ".ToCharArray(), 2); + AcceptCommand(command); + _client.Send(new TdApi.SetAuthenticationEmailAddress(args[1]), _handler); + } + else if (command.StartsWith("caec")) + { + var args = command.Split(" ".ToCharArray(), 2); + AcceptCommand(command); + _client.Send(new TdApi.CheckAuthenticationEmailCode(new TdApi.EmailAddressAuthenticationCode(args[1])), _handler); + } else if (command.StartsWith("cac")) { var args = command.Split(" ".ToCharArray(), 2); From a81d3768b42087f2267940816083819f16c13cbd Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 13:11:08 +0300 Subject: [PATCH 111/200] Update Python example. --- example/python/tdjson_example.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/example/python/tdjson_example.py b/example/python/tdjson_example.py index 986e4a37a..ee8a92a15 100644 --- a/example/python/tdjson_example.py +++ b/example/python/tdjson_example.py @@ -110,6 +110,17 @@ while True: phone_number = input('Please enter your phone number: ') td_send({'@type': 'setAuthenticationPhoneNumber', 'phone_number': phone_number}) + # enter email address to log in + if auth_state['@type'] == 'authorizationStateWaitEmailAddress': + email_address = input('Please enter your email address: ') + td_send({'@type': 'setAuthenticationEmailAddress', 'email_address': email_address}) + + # wait for email authorization code + if auth_state['@type'] == 'authorizationStateWaitEmailCode': + code = input('Please enter the email authentication code you received: ') + td_send({'@type': 'checkAuthenticationEmailCode', + 'code': {'@type': 'emailAddressAuthenticationCode', 'code' : 'code'}}) + # wait for authorization code if auth_state['@type'] == 'authorizationStateWaitCode': code = input('Please enter the authentication code you received: ') From ed8e11774c287a710acac6cd794368d32cbba54b Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 13:11:35 +0300 Subject: [PATCH 112/200] Update Swift example. --- example/swift/src/main.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/example/swift/src/main.swift b/example/swift/src/main.swift index bbee661f7..9e3513395 100644 --- a/example/swift/src/main.swift +++ b/example/swift/src/main.swift @@ -123,6 +123,17 @@ func updateAuthorizationState(authorizationState: Dictionary) { let phone_number = myReadLine() client.queryAsync(query:["@type":"setAuthenticationPhoneNumber", "phone_number":phone_number], f:checkAuthenticationError) + case "authorizationStateWaitEmailAddress": + print("Enter your email address: ") + let email_address = myReadLine() + client.queryAsync(query:["@type":"setAuthenticationEmailAddress", "email_address":email_address], f:checkAuthenticationError) + + case "authorizationStateWaitEmailCode": + var code: String = "" + print("Enter email code: ") + code = myReadLine() + client.queryAsync(query:["@type":"checkAuthenticationEmailCode", "code":["@type":"emailAddressAuthenticationCode", "code":code]], f:checkAuthenticationError) + case "authorizationStateWaitCode": var code: String = "" print("Enter (SMS) code: ") From 612afe63feb889e2c791319bba9eecfc47daab67 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 13:47:16 +0300 Subject: [PATCH 113/200] Update Java example. --- .../java/org/drinkless/tdlib/example/Example.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/example/java/org/drinkless/tdlib/example/Example.java b/example/java/org/drinkless/tdlib/example/Example.java index 7bda83960..596cee842 100644 --- a/example/java/org/drinkless/tdlib/example/Example.java +++ b/example/java/org/drinkless/tdlib/example/Example.java @@ -112,7 +112,7 @@ public final class Example { request.applicationVersion = "1.0"; request.enableStorageOptimizer = true; - client.send(parameters, new AuthorizationRequestHandler()); + client.send(request, new AuthorizationRequestHandler()); break; case TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: { String phoneNumber = promptString("Please enter phone number: "); @@ -124,6 +124,16 @@ public final class Example { System.out.println("Please confirm this login link on another device: " + link); break; } + case TdApi.AuthorizationStateWaitEmailAddress.CONSTRUCTOR: { + String emailAddress = promptString("Please enter email address: "); + client.send(new TdApi.SetAuthenticationEmailAddress(emailAddress), new AuthorizationRequestHandler()); + break; + } + case TdApi.AuthorizationStateWaitEmailCode.CONSTRUCTOR: { + String code = promptString("Please enter email authentication code: "); + client.send(new TdApi.CheckAuthenticationEmailCode(new TdApi.EmailAddressAuthenticationCode(code)), new AuthorizationRequestHandler()); + break; + } case TdApi.AuthorizationStateWaitCode.CONSTRUCTOR: { String code = promptString("Please enter authentication code: "); client.send(new TdApi.CheckAuthenticationCode(code), new AuthorizationRequestHandler()); From 4d5625a06fbd9ea546f69e83ac6381133a998389 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 14:27:07 +0300 Subject: [PATCH 114/200] Explicitly load tdjni in Client.java and TdApi.java. --- example/java/org/drinkless/tdlib/Client.java | 8 ++++++++ example/java/org/drinkless/tdlib/example/Example.java | 8 -------- td/generate/tl_writer_java.cpp | 10 +++++++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/example/java/org/drinkless/tdlib/Client.java b/example/java/org/drinkless/tdlib/Client.java index e9cf5e180..0a58bb45a 100644 --- a/example/java/org/drinkless/tdlib/Client.java +++ b/example/java/org/drinkless/tdlib/Client.java @@ -13,6 +13,14 @@ import java.util.concurrent.atomic.AtomicLong; * Main class for interaction with the TDLib. */ public final class Client { + static { + try { + System.loadLibrary("tdjni"); + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + } + } + /** * Interface for handler for results of queries to TDLib and incoming updates from TDLib. */ diff --git a/example/java/org/drinkless/tdlib/example/Example.java b/example/java/org/drinkless/tdlib/example/Example.java index 596cee842..7e76b4227 100644 --- a/example/java/org/drinkless/tdlib/example/Example.java +++ b/example/java/org/drinkless/tdlib/example/Example.java @@ -55,14 +55,6 @@ public final class Example { private static final String commandsLine = "Enter command (gcs - GetChats, gc - GetChat, me - GetMe, sm - SendMessage, lo - LogOut, q - Quit): "; private static volatile String currentPrompt = null; - static { - try { - System.loadLibrary("tdjni"); - } catch (UnsatisfiedLinkError e) { - e.printStackTrace(); - } - } - private static void print(String str) { if (currentPrompt != null) { System.out.println(""); diff --git a/td/generate/tl_writer_java.cpp b/td/generate/tl_writer_java.cpp index e2dba8abb..3861645b6 100644 --- a/td/generate/tl_writer_java.cpp +++ b/td/generate/tl_writer_java.cpp @@ -194,7 +194,15 @@ std::string TD_TL_writer_java::gen_output_begin() const { return "package " + package_name + ";\n\n" "public class " + - tl_name + " {\n"; + tl_name + + " {\n" + " static {\n" + " try {\n" + " System.loadLibrary(\"tdjni\");\n" + " } catch (UnsatisfiedLinkError e) {\n" + " e.printStackTrace();\n" + + " }\n" + " }\n\n"; } std::string TD_TL_writer_java::gen_output_end() const { From bc950bc5432e438fb7b73a6bd7334d7d097da1d2 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 15:40:09 +0300 Subject: [PATCH 115/200] Add explicit default constructors to abstract Java classes. --- .../JavadocTlDocumentationGenerator.php | 20 +++++++++++++++++++ td/generate/tl_writer_java.cpp | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/td/generate/JavadocTlDocumentationGenerator.php b/td/generate/JavadocTlDocumentationGenerator.php index 922cf2151..103207522 100644 --- a/td/generate/JavadocTlDocumentationGenerator.php +++ b/td/generate/JavadocTlDocumentationGenerator.php @@ -141,6 +141,13 @@ EOT * This class is a base class for all TDLib interface classes. */ EOT +); + + $this->addDocumentation(" public Object() {", <<addDocumentation(' public abstract int getConstructor();', <<addDocumentation(" public Function() {", <<addDocumentation(' public static final int CONSTRUCTOR', <<addDocumentation(" public $class_name() {", <<"; } std::string result = " public " + std::string(is_proxy ? "abstract " : "") + full_class_name + " {\n"; + if (is_proxy) { + result += " public " + class_name + "() {\n }\n"; + } if (class_name == gen_base_tl_class_name() || class_name == gen_base_function_class_name()) { - result += " public native String toString();\n"; + result += "\n public native String toString();\n"; } return result; From 43109ecc9695d5e246a0368bea1922508fdc86ba Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 16:00:55 +0300 Subject: [PATCH 116/200] Improve getConstructor/toString javadoc. --- td/generate/JavadocTlDocumentationGenerator.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/td/generate/JavadocTlDocumentationGenerator.php b/td/generate/JavadocTlDocumentationGenerator.php index 103207522..e9cd2d3e6 100644 --- a/td/generate/JavadocTlDocumentationGenerator.php +++ b/td/generate/JavadocTlDocumentationGenerator.php @@ -152,14 +152,18 @@ EOT $this->addDocumentation(' public abstract int getConstructor();', <<addDocumentation(' public native String toString();', << Date: Thu, 8 Sep 2022 17:45:19 +0300 Subject: [PATCH 117/200] Remove class AvailableReaction. --- td/telegram/AvailableReaction.cpp | 19 ++++++------------- td/telegram/AvailableReaction.h | 18 ++---------------- td/telegram/MessagesManager.cpp | 23 ++++++++++++----------- td/telegram/MessagesManager.h | 9 ++++----- td/telegram/StickersManager.cpp | 3 +-- td/telegram/Td.cpp | 3 +-- td/telegram/files/FileDb.cpp | 3 +++ 7 files changed, 29 insertions(+), 49 deletions(-) diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index 91c4bcc2a..1b649aebb 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -10,20 +10,17 @@ namespace td { -AvailableReactionType get_reaction_type(const vector &available_reactions, const string &reaction) { +AvailableReactionType get_reaction_type(const vector &available_reactions, const string &reaction) { if (reaction[0] == '#') { return AvailableReactionType::NeedsPremium; } - for (auto &available_reaction : available_reactions) { - if (available_reaction.reaction_ == reaction) { - return AvailableReactionType::Available; - } + if (contains(available_reactions, reaction)) { + return AvailableReactionType::Available; } return AvailableReactionType::Unavailable; } -ChatReactions get_active_reactions(const ChatReactions &available_reactions, - const vector &active_reactions) { +ChatReactions get_active_reactions(const ChatReactions &available_reactions, const vector &active_reactions) { if (available_reactions.reactions_.empty()) { // fast path return available_reactions; @@ -33,15 +30,11 @@ ChatReactions get_active_reactions(const ChatReactions &available_reactions, vector result; for (const auto &active_reaction : active_reactions) { - if (td::contains(available_reactions.reactions_, active_reaction.reaction_)) { - result.push_back(active_reaction.reaction_); + if (td::contains(available_reactions.reactions_, active_reaction)) { + result.push_back(active_reaction); } } return ChatReactions(std::move(result)); } -bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs) { - return lhs.reaction_ == rhs.reaction_; -} - } // namespace td diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h index becd0c782..7003ed9fa 100644 --- a/td/telegram/AvailableReaction.h +++ b/td/telegram/AvailableReaction.h @@ -13,24 +13,10 @@ namespace td { -struct AvailableReaction { - string reaction_; - - explicit AvailableReaction(const string &reaction) : reaction_(reaction) { - } -}; - -bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs); - -inline bool operator!=(const AvailableReaction &lhs, const AvailableReaction &rhs) { - return !(lhs == rhs); -} - enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium }; -AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); +AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); -ChatReactions get_active_reactions(const ChatReactions &available_reactions, - const vector &active_reactions); +ChatReactions get_active_reactions(const ChatReactions &available_reactions, const vector &active_reactions); } // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 554ada32d..1b47b3ef4 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7,6 +7,7 @@ #include "td/telegram/MessagesManager.h" #include "td/telegram/AuthManager.h" +#include "td/telegram/AvailableReaction.h" #include "td/telegram/ChainId.h" #include "td/telegram/ChannelType.h" #include "td/telegram/ChatId.h" @@ -8236,7 +8237,7 @@ void MessagesManager::hide_dialog_message_reactions(Dialog *d) { } } -void MessagesManager::set_active_reactions(vector active_reactions) { +void MessagesManager::set_active_reactions(vector active_reactions) { if (active_reactions == active_reactions_) { return; } @@ -8246,8 +8247,8 @@ void MessagesManager::set_active_reactions(vector active_reac active_reaction_pos_.clear(); bool is_changed = old_active_reactions.size() != active_reactions_.size(); for (size_t i = 0; i < active_reactions_.size(); i++) { - active_reaction_pos_[active_reactions_[i].reaction_] = i; - if (!is_changed && active_reactions_[i].reaction_ != old_active_reactions[i].reaction_) { + active_reaction_pos_[active_reactions_[i]] = i; + if (!is_changed && active_reactions_[i] != old_active_reactions[i]) { is_changed = true; } } @@ -24458,7 +24459,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id set_promises(promises); } -Result> MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { +Result> MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "get_message_available_reactions"); if (d == nullptr) { @@ -24472,7 +24473,7 @@ Result> MessagesManager::get_message_available_reactio return get_message_available_reactions(d, m); } -vector MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m) { +vector MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m) { CHECK(d != nullptr); CHECK(m != nullptr); auto active_reactions = get_message_active_reactions(d, m); @@ -24490,7 +24491,7 @@ vector MessagesManager::get_message_available_reactions(const } } - vector result; + vector result; if (can_use_reactions) { int64 reactions_uniq_max = td_->option_manager_->get_option_integer("reactions_uniq_max", 11); bool can_add_new_reactions = @@ -24498,10 +24499,10 @@ vector MessagesManager::get_message_available_reactions(const // can add only active available reactions or remove previously set reaction for (const auto &active_reaction : active_reactions_) { // can add the reaction if it has already been used for the message or is available in the chat - bool is_set = (m->reactions != nullptr && m->reactions->get_reaction(active_reaction.reaction_) != nullptr); - if (is_set || (can_add_new_reactions && (active_reactions.allow_all_ || - td::contains(active_reactions.reactions_, active_reaction.reaction_)))) { - result.emplace_back(active_reaction.reaction_); + bool is_set = (m->reactions != nullptr && m->reactions->get_reaction(active_reaction) != nullptr); + if (is_set || (can_add_new_reactions && + (active_reactions.allow_all_ || td::contains(active_reactions.reactions_, active_reaction)))) { + result.push_back(active_reaction); } } } @@ -24511,7 +24512,7 @@ vector MessagesManager::get_message_available_reactions(const get_reaction_type(result, reaction.get_reaction()) == AvailableReactionType::Unavailable) { CHECK(!can_use_reactions || get_reaction_type(active_reactions_, reaction.get_reaction()) == AvailableReactionType::Unavailable); - result.emplace_back(reaction.get_reaction()); + result.push_back(reaction.get_reaction()); } } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 7dc300c78..27bfa0913 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -8,7 +8,6 @@ #include "td/telegram/AccessRights.h" #include "td/telegram/AffectedHistory.h" -#include "td/telegram/AvailableReaction.h" #include "td/telegram/ChannelId.h" #include "td/telegram/ChatReactions.h" #include "td/telegram/DialogAction.h" @@ -538,7 +537,7 @@ class MessagesManager final : public Actor { void set_dialog_description(DialogId dialog_id, const string &description, Promise &&promise); - void set_active_reactions(vector active_reactions); + void set_active_reactions(vector active_reactions); void set_dialog_available_reactions(DialogId dialog_id, td_api::object_ptr &&available_reactions_ptr, @@ -806,7 +805,7 @@ class MessagesManager final : public Actor { vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); - Result> get_message_available_reactions(FullMessageId full_message_id); + Result> get_message_available_reactions(FullMessageId full_message_id); void set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise); @@ -2688,7 +2687,7 @@ class MessagesManager final : public Actor { bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message); - vector get_message_available_reactions(const Dialog *d, const Message *m); + vector get_message_available_reactions(const Dialog *d, const Message *m); void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); @@ -3735,7 +3734,7 @@ class MessagesManager final : public Actor { }; FlatHashMap pending_reactions_; - vector active_reactions_; + vector active_reactions_; FlatHashMap active_reaction_pos_; uint32 scheduled_messages_sync_generation_ = 1; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index f080cacd9..196fec0ba 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -8,7 +8,6 @@ #include "td/telegram/AccessRights.h" #include "td/telegram/AuthManager.h" -#include "td/telegram/AvailableReaction.h" #include "td/telegram/ConfigManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DialogId.h" @@ -3699,7 +3698,7 @@ void StickersManager::load_reactions() { } void StickersManager::update_active_reactions() { - vector active_reactions; + vector active_reactions; for (auto &reaction : reactions_.reactions_) { if (reaction.is_active_) { active_reactions.emplace_back(reaction.reaction_); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 4f4299216..17fc0879d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5206,8 +5206,7 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque if (r_reactions.is_error()) { send_closure(actor_id(this), &Td::send_error, id, r_reactions.move_as_error()); } else { - auto reactions = - transform(r_reactions.ok(), [](auto &reaction) { return get_reaction_type_object(reaction.reaction_); }); + auto reactions = transform(r_reactions.ok(), [](auto &reaction) { return get_reaction_type_object(reaction); }); send_closure(actor_id(this), &Td::send_result, id, td_api::make_object(std::move(reactions))); } diff --git a/td/telegram/files/FileDb.cpp b/td/telegram/files/FileDb.cpp index efcc48b8d..d763a97bf 100644 --- a/td/telegram/files/FileDb.cpp +++ b/td/telegram/files/FileDb.cpp @@ -101,6 +101,7 @@ class FileDb final : public FileDbInterface { pmc.commit_transaction().ensure(); } + void store_file_data(FileDbId id, const string &file_data, const string &remote_key, const string &local_key, const string &generate_key) { auto &pmc = file_pmc(); @@ -125,6 +126,7 @@ class FileDb final : public FileDbInterface { pmc.commit_transaction().ensure(); } + void store_file_data_ref(FileDbId id, FileDbId new_id) { auto &pmc = file_pmc(); pmc.begin_write_transaction().ensure(); @@ -202,6 +204,7 @@ class FileDb final : public FileDbInterface { } send_closure(file_db_actor_, &FileDbActor::clear_file_data, id, remote_key, local_key, generate_key); } + void set_file_data(FileDbId id, const FileData &file_data, bool new_remote, bool new_local, bool new_generate) final { string remote_key; if (file_data.remote_.type() == RemoteFileLocation::Type::Full && new_remote) { From 81159edcd99a6894012e23160b8927998ea4c076 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 17:56:39 +0300 Subject: [PATCH 118/200] Move get_active_reactions to ChatReactions. --- td/telegram/AvailableReaction.cpp | 17 ----------------- td/telegram/AvailableReaction.h | 2 -- td/telegram/ChatReactions.cpp | 17 +++++++++++++++++ td/telegram/ChatReactions.h | 2 ++ td/telegram/MessagesManager.cpp | 6 +++--- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index 1b649aebb..10eae8663 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -20,21 +20,4 @@ AvailableReactionType get_reaction_type(const vector &available_reaction return AvailableReactionType::Unavailable; } -ChatReactions get_active_reactions(const ChatReactions &available_reactions, const vector &active_reactions) { - if (available_reactions.reactions_.empty()) { - // fast path - return available_reactions; - } - CHECK(!available_reactions.allow_all_); - CHECK(!available_reactions.allow_custom_); - - vector result; - for (const auto &active_reaction : active_reactions) { - if (td::contains(available_reactions.reactions_, active_reaction)) { - result.push_back(active_reaction); - } - } - return ChatReactions(std::move(result)); -} - } // namespace td diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h index 7003ed9fa..b0f5950e0 100644 --- a/td/telegram/AvailableReaction.h +++ b/td/telegram/AvailableReaction.h @@ -17,6 +17,4 @@ enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); -ChatReactions get_active_reactions(const ChatReactions &available_reactions, const vector &active_reactions); - } // namespace td diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index 8e9e4d87d..8dc77e621 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -60,6 +60,23 @@ ChatReactions::ChatReactions(td_api::object_ptr } } +ChatReactions ChatReactions::get_active_reactions(const vector &active_reactions) const { + if (reactions_.empty()) { + // fast path + return *this; + } + CHECK(!allow_all_); + CHECK(!allow_custom_); + + vector result; + for (const auto &active_reaction : active_reactions) { + if (td::contains(reactions_, active_reaction)) { + result.push_back(active_reaction); + } + } + return ChatReactions(std::move(result)); +} + td_api::object_ptr ChatReactions::get_chat_available_reactions_object() const { if (allow_all_) { return td_api::make_object(); diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h index 5a52c22b5..976af465f 100644 --- a/td/telegram/ChatReactions.h +++ b/td/telegram/ChatReactions.h @@ -32,6 +32,8 @@ struct ChatReactions { ChatReactions(bool allow_all, bool allow_custom) : allow_all_(allow_all), allow_custom_(allow_custom) { } + ChatReactions get_active_reactions(const vector &active_reactions) const; + telegram_api::object_ptr get_input_chat_reactions() const; td_api::object_ptr get_chat_available_reactions_object() const; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1b47b3ef4..0fc376cfd 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8263,8 +8263,8 @@ void MessagesManager::set_active_reactions(vector active_reactions) { break; case DialogType::Chat: case DialogType::Channel: { - auto old_reactions = ::td::get_active_reactions(d->available_reactions, old_active_reactions); - auto new_reactions = ::td::get_active_reactions(d->available_reactions, active_reactions_); + auto old_reactions = d->available_reactions.get_active_reactions(old_active_reactions); + auto new_reactions = d->available_reactions.get_active_reactions(active_reactions_); if (old_reactions != new_reactions) { if (old_reactions.empty() != new_reactions.empty()) { if (!old_reactions.empty()) { @@ -8287,7 +8287,7 @@ void MessagesManager::set_active_reactions(vector active_reactions) { } ChatReactions MessagesManager::get_active_reactions(const ChatReactions &available_reactions) const { - return ::td::get_active_reactions(available_reactions, active_reactions_); + return available_reactions.get_active_reactions(active_reactions_); } ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) const { From ac5e8e7eda7ae006bf88ec03726ed09bf2b4f94a Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 18:25:12 +0300 Subject: [PATCH 119/200] Remove class AvailableReactionType. --- CMakeLists.txt | 2 -- td/telegram/AvailableReaction.cpp | 23 ----------------------- td/telegram/AvailableReaction.h | 20 -------------------- td/telegram/MessagesManager.cpp | 17 ++++------------- 4 files changed, 4 insertions(+), 58 deletions(-) delete mode 100644 td/telegram/AvailableReaction.cpp delete mode 100644 td/telegram/AvailableReaction.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 218012006..779763bb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,7 +289,6 @@ set(TDLIB_SOURCE td/telegram/AudiosManager.cpp td/telegram/AuthManager.cpp td/telegram/AutoDownloadSettings.cpp - td/telegram/AvailableReaction.cpp td/telegram/BackgroundManager.cpp td/telegram/BackgroundType.cpp td/telegram/BotCommand.cpp @@ -493,7 +492,6 @@ set(TDLIB_SOURCE td/telegram/AudiosManager.h td/telegram/AuthManager.h td/telegram/AutoDownloadSettings.h - td/telegram/AvailableReaction.h td/telegram/BackgroundId.h td/telegram/BackgroundManager.h td/telegram/BackgroundType.h diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp deleted file mode 100644 index 10eae8663..000000000 --- a/td/telegram/AvailableReaction.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#include "td/telegram/AvailableReaction.h" - -#include "td/utils/algorithm.h" - -namespace td { - -AvailableReactionType get_reaction_type(const vector &available_reactions, const string &reaction) { - if (reaction[0] == '#') { - return AvailableReactionType::NeedsPremium; - } - if (contains(available_reactions, reaction)) { - return AvailableReactionType::Available; - } - return AvailableReactionType::Unavailable; -} - -} // namespace td diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h deleted file mode 100644 index b0f5950e0..000000000 --- a/td/telegram/AvailableReaction.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#pragma once - -#include "td/telegram/ChatReactions.h" -#include "td/telegram/td_api.h" - -#include "td/utils/common.h" - -namespace td { - -enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium }; - -AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); - -} // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0fc376cfd..917475e5f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7,7 +7,6 @@ #include "td/telegram/MessagesManager.h" #include "td/telegram/AuthManager.h" -#include "td/telegram/AvailableReaction.h" #include "td/telegram/ChainId.h" #include "td/telegram/ChannelType.h" #include "td/telegram/ChatId.h" @@ -24508,10 +24507,8 @@ vector MessagesManager::get_message_available_reactions(const Dialog *d, } if (m->reactions != nullptr) { for (const auto &reaction : m->reactions->reactions_) { - if (reaction.is_chosen() && - get_reaction_type(result, reaction.get_reaction()) == AvailableReactionType::Unavailable) { - CHECK(!can_use_reactions || - get_reaction_type(active_reactions_, reaction.get_reaction()) == AvailableReactionType::Unavailable); + if (reaction.is_chosen() && !td::contains(result, reaction.get_reaction())) { + CHECK(!can_use_reactions || !td::contains(active_reactions_, reaction.get_reaction())); result.push_back(reaction.get_reaction()); } } @@ -24532,14 +24529,8 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Message not found")); } - if (!reaction.empty()) { - auto reaction_type = get_reaction_type(get_message_available_reactions(d, m), reaction); - if (reaction_type == AvailableReactionType::Unavailable) { - return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); - } - if (reaction_type == AvailableReactionType::NeedsPremium) { - return promise.set_error(Status::Error(400, "The reaction is available only for Telegram Premium users")); - } + if (!reaction.empty() && !td::contains(get_message_available_reactions(d, m), reaction)) { + return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } bool can_get_added_reactions = !is_broadcast_channel(dialog_id) && dialog_id.get_type() != DialogType::User && From 148f1bf794dee65137b7bab358d585ced61eb930 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 20:04:32 +0300 Subject: [PATCH 120/200] Update get_message_available_reactions. --- td/telegram/ChatReactions.cpp | 5 ++++ td/telegram/ChatReactions.h | 2 ++ td/telegram/MessagesManager.cpp | 47 ++++++++++++++++++--------------- td/telegram/MessagesManager.h | 6 +++-- td/telegram/Td.cpp | 4 +-- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index 8dc77e621..328236f6d 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -84,6 +84,11 @@ td_api::object_ptr ChatReactions::get_chat_avail return td_api::make_object(transform(reactions_, get_reaction_type_object)); } +td_api::object_ptr ChatReactions::get_available_reactions_object() const { + CHECK(!allow_all_); + return td_api::make_object(transform(reactions_, get_reaction_type_object)); +} + telegram_api::object_ptr ChatReactions::get_input_chat_reactions() const { if (allow_all_) { int32 flags = 0; diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h index 976af465f..b2ca80c07 100644 --- a/td/telegram/ChatReactions.h +++ b/td/telegram/ChatReactions.h @@ -38,6 +38,8 @@ struct ChatReactions { td_api::object_ptr get_chat_available_reactions_object() const; + td_api::object_ptr get_available_reactions_object() const; + bool empty() const { return reactions_.empty() && !allow_all_; } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 917475e5f..8afde6666 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24458,7 +24458,11 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id set_promises(promises); } -Result> MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { +bool MessagesManager::is_active_reaction(const string &reaction) const { + return !reaction.empty() && (reaction[0] == '#' || active_reaction_pos_.count(reaction) > 0); +} + +Result MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "get_message_available_reactions"); if (d == nullptr) { @@ -24472,7 +24476,7 @@ Result> MessagesManager::get_message_available_reactions(FullMess return get_message_available_reactions(d, m); } -vector MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m) { +ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m) { CHECK(d != nullptr); CHECK(m != nullptr); auto active_reactions = get_message_active_reactions(d, m); @@ -24490,30 +24494,31 @@ vector MessagesManager::get_message_available_reactions(const Dialog *d, } } - vector result; - if (can_use_reactions) { - int64 reactions_uniq_max = td_->option_manager_->get_option_integer("reactions_uniq_max", 11); - bool can_add_new_reactions = - m->reactions == nullptr || static_cast(m->reactions->reactions_.size()) < reactions_uniq_max; - // can add only active available reactions or remove previously set reaction - for (const auto &active_reaction : active_reactions_) { - // can add the reaction if it has already been used for the message or is available in the chat - bool is_set = (m->reactions != nullptr && m->reactions->get_reaction(active_reaction) != nullptr); - if (is_set || (can_add_new_reactions && - (active_reactions.allow_all_ || td::contains(active_reactions.reactions_, active_reaction)))) { - result.push_back(active_reaction); - } - } + int64 reactions_uniq_max = td_->option_manager_->get_option_integer("reactions_uniq_max", 11); + bool can_add_new_reactions = + m->reactions == nullptr || static_cast(m->reactions->reactions_.size()) < reactions_uniq_max; + + if (!can_use_reactions || !can_add_new_reactions) { + active_reactions = ChatReactions(); + } + + if (active_reactions.allow_all_) { + active_reactions.reactions_ = active_reactions_; + active_reactions.allow_all_ = false; } if (m->reactions != nullptr) { for (const auto &reaction : m->reactions->reactions_) { - if (reaction.is_chosen() && !td::contains(result, reaction.get_reaction())) { - CHECK(!can_use_reactions || !td::contains(active_reactions_, reaction.get_reaction())); - result.push_back(reaction.get_reaction()); + // we always can remove a currently chosen reaction + // an already used reaction can be added if it is an active reaction + const string &reaction_str = reaction.get_reaction(); + if (reaction.is_chosen() || (can_use_reactions && is_active_reaction(reaction_str))) { + if (!td::contains(active_reactions.reactions_, reaction_str)) { + active_reactions.reactions_.push_back(reaction_str); + } } } } - return result; + return active_reactions; } void MessagesManager::set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, @@ -24529,7 +24534,7 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Message not found")); } - if (!reaction.empty() && !td::contains(get_message_available_reactions(d, m), reaction)) { + if (!reaction.empty() && !td::contains(get_message_available_reactions(d, m).reactions_, reaction)) { return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 27bfa0913..1fef6d2f3 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -805,7 +805,7 @@ class MessagesManager final : public Actor { vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); - Result> get_message_available_reactions(FullMessageId full_message_id); + Result get_message_available_reactions(FullMessageId full_message_id); void set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise); @@ -2687,7 +2687,9 @@ class MessagesManager final : public Actor { bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message); - vector get_message_available_reactions(const Dialog *d, const Message *m); + bool is_active_reaction(const string &reaction) const; + + ChatReactions get_message_available_reactions(const Dialog *d, const Message *m); void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 17fc0879d..1cd984baa 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5206,9 +5206,7 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque if (r_reactions.is_error()) { send_closure(actor_id(this), &Td::send_error, id, r_reactions.move_as_error()); } else { - auto reactions = transform(r_reactions.ok(), [](auto &reaction) { return get_reaction_type_object(reaction); }); - send_closure(actor_id(this), &Td::send_result, id, - td_api::make_object(std::move(reactions))); + send_closure(actor_id(this), &Td::send_result, id, r_reactions.ok().get_available_reactions_object()); } } From 4ae5b9a5336dbf0dcf24b5cdd7a8b679e703107c Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 8 Sep 2022 21:04:23 +0300 Subject: [PATCH 121/200] Consistently use is_active_reaction. --- td/telegram/ChatReactions.cpp | 22 ++++++++-------------- td/telegram/ChatReactions.h | 3 ++- td/telegram/MessageReaction.cpp | 4 ++++ td/telegram/MessageReaction.h | 2 ++ td/telegram/MessagesManager.cpp | 20 +++++++------------- td/telegram/MessagesManager.h | 2 -- 6 files changed, 23 insertions(+), 30 deletions(-) diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index 328236f6d..644e6b595 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -60,21 +60,15 @@ ChatReactions::ChatReactions(td_api::object_ptr } } -ChatReactions ChatReactions::get_active_reactions(const vector &active_reactions) const { - if (reactions_.empty()) { - // fast path - return *this; +ChatReactions ChatReactions::get_active_reactions(const FlatHashMap &active_reaction_pos) const { + ChatReactions result = *this; + if (!reactions_.empty()) { + CHECK(!allow_all_); + CHECK(!allow_custom_); + td::remove_if(result.reactions_, + [&](const string &reaction) { return !is_active_reaction(reaction, active_reaction_pos); }); } - CHECK(!allow_all_); - CHECK(!allow_custom_); - - vector result; - for (const auto &active_reaction : active_reactions) { - if (td::contains(reactions_, active_reaction)) { - result.push_back(active_reaction); - } - } - return ChatReactions(std::move(result)); + return result; } td_api::object_ptr ChatReactions::get_chat_available_reactions_object() const { diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h index b2ca80c07..b4fd358d5 100644 --- a/td/telegram/ChatReactions.h +++ b/td/telegram/ChatReactions.h @@ -10,6 +10,7 @@ #include "td/telegram/telegram_api.h" #include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" @@ -32,7 +33,7 @@ struct ChatReactions { ChatReactions(bool allow_all, bool allow_custom) : allow_all_(allow_all), allow_custom_(allow_custom) { } - ChatReactions get_active_reactions(const vector &active_reactions) const; + ChatReactions get_active_reactions(const FlatHashMap &active_reaction_pos) const; telegram_api::object_ptr get_input_chat_reactions() const; diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 1da9c2ae7..5cc15979e 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -680,6 +680,10 @@ StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr &active_reaction_pos) { + return !reaction.empty() && (reaction[0] == '#' || active_reaction_pos.count(reaction) > 0); +} + void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids) { if (!td->messages_manager_->have_input_peer(dialog_id, AccessRights::Read) || message_ids.empty()) { return; diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index eea0a108f..5fa8a2913 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -181,6 +181,8 @@ string get_message_reaction_string(const telegram_api::object_ptr &type); +bool is_active_reaction(const string &reaction, const FlatHashMap &active_reaction_pos); + void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids); void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 8afde6666..669af0eef 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8241,15 +8241,13 @@ void MessagesManager::set_active_reactions(vector active_reactions) { return; } - auto old_active_reactions = std::move(active_reactions_); + bool is_changed = active_reactions != active_reactions_; active_reactions_ = std::move(active_reactions); + + auto old_active_reaction_pos_ = std::move(active_reaction_pos_); active_reaction_pos_.clear(); - bool is_changed = old_active_reactions.size() != active_reactions_.size(); for (size_t i = 0; i < active_reactions_.size(); i++) { active_reaction_pos_[active_reactions_[i]] = i; - if (!is_changed && active_reactions_[i] != old_active_reactions[i]) { - is_changed = true; - } } dialogs_.foreach([&](const DialogId &dialog_id, unique_ptr &dialog) { @@ -8262,8 +8260,8 @@ void MessagesManager::set_active_reactions(vector active_reactions) { break; case DialogType::Chat: case DialogType::Channel: { - auto old_reactions = d->available_reactions.get_active_reactions(old_active_reactions); - auto new_reactions = d->available_reactions.get_active_reactions(active_reactions_); + auto old_reactions = d->available_reactions.get_active_reactions(old_active_reaction_pos_); + auto new_reactions = d->available_reactions.get_active_reactions(active_reaction_pos_); if (old_reactions != new_reactions) { if (old_reactions.empty() != new_reactions.empty()) { if (!old_reactions.empty()) { @@ -8286,7 +8284,7 @@ void MessagesManager::set_active_reactions(vector active_reactions) { } ChatReactions MessagesManager::get_active_reactions(const ChatReactions &available_reactions) const { - return available_reactions.get_active_reactions(active_reactions_); + return available_reactions.get_active_reactions(active_reaction_pos_); } ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) const { @@ -24458,10 +24456,6 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id set_promises(promises); } -bool MessagesManager::is_active_reaction(const string &reaction) const { - return !reaction.empty() && (reaction[0] == '#' || active_reaction_pos_.count(reaction) > 0); -} - Result MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "get_message_available_reactions"); @@ -24511,7 +24505,7 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, // we always can remove a currently chosen reaction // an already used reaction can be added if it is an active reaction const string &reaction_str = reaction.get_reaction(); - if (reaction.is_chosen() || (can_use_reactions && is_active_reaction(reaction_str))) { + if (reaction.is_chosen() || (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_))) { if (!td::contains(active_reactions.reactions_, reaction_str)) { active_reactions.reactions_.push_back(reaction_str); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 1fef6d2f3..92b234001 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2687,8 +2687,6 @@ class MessagesManager final : public Actor { bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message); - bool is_active_reaction(const string &reaction) const; - ChatReactions get_message_available_reactions(const Dialog *d, const Message *m); void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); From 6b2f6b420425f4752e998e6b99b4221032ecd2fa Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 15:56:45 +0300 Subject: [PATCH 122/200] Split setMessageReaction to addMessageReaction and removeMessageReaction. --- td/generate/scheme/td_api.tl | 12 +++-- td/telegram/MessagesManager.cpp | 83 ++++++++++++++++++++++++++------- td/telegram/MessagesManager.h | 9 +++- td/telegram/Td.cpp | 11 ++++- td/telegram/Td.h | 4 +- td/telegram/cli.cpp | 17 +++++-- 6 files changed, 105 insertions(+), 31 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 727ed25d3..01cdf79c6 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5169,13 +5169,19 @@ editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:Messa //@message_id Identifier of the message getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions; -//@description Changes chosen reaction for a message +//@description Adds a reaction to a message. Use getMessageAvailableReactions to receive the list of available reactions for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message -//@reaction_type Type of the new chosen reaction; pass null or the currently chosen non-big reaction to remove the reaction +//@reaction_type Type of the reaction to add //@is_big Pass true if the reaction is added with a big animation //@update_recent_reactions Pass true if the reaction needs to be added to recent reactions -setMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_big:Bool update_recent_reactions:Bool = Ok; +addMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType is_big:Bool update_recent_reactions:Bool = Ok; + +//@description Removes a reaction from a message. A chosen reaction can always be removed +//@chat_id Identifier of the chat to which the message belongs +//@message_id Identifier of the message +//@reaction_type Type of the reaction to remove +removeMessageReaction chat_id:int53 message_id:int53 reaction_type:ReactionType = Ok; //@description Returns reactions added for a message, along with their sender //@chat_id Identifier of the chat to which the message belongs diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 669af0eef..22c9d9bbe 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24515,10 +24515,10 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, return active_reactions; } -void MessagesManager::set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, +void MessagesManager::add_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise) { auto dialog_id = full_message_id.get_dialog_id(); - Dialog *d = get_dialog_force(dialog_id, "set_message_reaction"); + Dialog *d = get_dialog_force(dialog_id, "add_message_reaction"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat not found")); } @@ -24528,17 +24528,13 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Message not found")); } - if (!reaction.empty() && !td::contains(get_message_available_reactions(d, m).reactions_, reaction)) { + if (!td::contains(get_message_available_reactions(d, m).reactions_, reaction)) { return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } bool can_get_added_reactions = !is_broadcast_channel(dialog_id) && dialog_id.get_type() != DialogType::User && !is_discussion_message(dialog_id, m); if (m->reactions == nullptr) { - if (reaction.empty()) { - return promise.set_value(Unit()); - } - m->reactions = make_unique(); m->reactions->can_get_added_reactions_ = can_get_added_reactions; m->available_reactions_generation = d->available_reactions_generation; @@ -24549,8 +24545,7 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string auto &message_reaction = *it; if (message_reaction.is_chosen()) { if (message_reaction.get_reaction() == reaction && !is_big) { - // double set removes reaction, unless a big reaction is set - reaction = string(); + return promise.set_value(Unit()); } message_reaction.set_is_chosen(false, get_my_dialog_id(), can_get_added_reactions); } @@ -24566,32 +24561,84 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string } } - pending_reactions_[full_message_id].query_count++; - - if (!is_found && !reaction.empty()) { + if (!is_found) { vector recent_chooser_dialog_ids; if (!is_broadcast_channel(dialog_id)) { recent_chooser_dialog_ids.push_back(get_my_dialog_id()); } m->reactions->reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); } + + set_message_reactions(d, m, reaction, is_big, add_to_recent, std::move(promise)); +} + +void MessagesManager::remove_message_reaction(FullMessageId full_message_id, string reaction, Promise &&promise) { + auto dialog_id = full_message_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id, "remove_message_reaction"); + if (d == nullptr) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + + Message *m = get_message_force(d, full_message_id.get_message_id(), "set_message_reaction"); + if (m == nullptr) { + return promise.set_error(Status::Error(400, "Message not found")); + } + + bool can_get_added_reactions = !is_broadcast_channel(dialog_id) && dialog_id.get_type() != DialogType::User && + !is_discussion_message(dialog_id, m); + if (m->reactions == nullptr) { + return promise.set_value(Unit()); + } + + bool is_found = false; + for (auto it = m->reactions->reactions_.begin(); it != m->reactions->reactions_.end();) { + auto &message_reaction = *it; + if (message_reaction.get_reaction() == reaction) { + if (message_reaction.is_chosen()) { + message_reaction.set_is_chosen(false, get_my_dialog_id(), can_get_added_reactions); + is_found = true; + } else { + return promise.set_value(Unit()); + } + } + + if (message_reaction.is_empty()) { + it = m->reactions->reactions_.erase(it); + } else { + ++it; + } + } + if (!is_found) { + return promise.set_value(Unit()); + } + + set_message_reactions(d, m, reaction, false, false, std::move(promise)); +} + +void MessagesManager::set_message_reactions(Dialog *d, Message *m, string reaction, bool is_big, bool add_to_recent, + Promise &&promise) { + CHECK(m->reactions != nullptr); + + FullMessageId full_message_id{d->dialog_id, m->message_id}; + pending_reactions_[full_message_id].query_count++; + m->reactions->sort_reactions(active_reaction_pos_); - send_update_message_interaction_info(dialog_id, m); - on_message_changed(d, m, true, "set_message_reaction"); + send_update_message_interaction_info(d->dialog_id, m); + on_message_changed(d, m, true, "set_message_reactions"); - // TODO invoke_after, cancel previous queries, log event + // TODO cancel previous queries, log event auto query_promise = PromiseCreator::lambda( [actor_id = actor_id(this), full_message_id, promise = std::move(promise)](Result &&result) mutable { - send_closure(actor_id, &MessagesManager::on_set_message_reaction, full_message_id, std::move(result), + send_closure(actor_id, &MessagesManager::on_set_message_reactions, full_message_id, std::move(result), std::move(promise)); }); ::td::set_message_reaction(td_, full_message_id, std::move(reaction), is_big, add_to_recent, std::move(query_promise)); } -void MessagesManager::on_set_message_reaction(FullMessageId full_message_id, Result result, - Promise promise) { +void MessagesManager::on_set_message_reactions(FullMessageId full_message_id, Result result, + Promise promise) { TRY_STATUS_PROMISE(promise, G()->close_status()); bool need_reload = result.is_error(); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 92b234001..fe98e30eb 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -807,9 +807,11 @@ class MessagesManager final : public Actor { Result get_message_available_reactions(FullMessageId full_message_id); - void set_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, + void add_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise); + void remove_message_reaction(FullMessageId full_message_id, string reaction, Promise &&promise); + void get_message_public_forwards(FullMessageId full_message_id, string offset, int32 limit, Promise> &&promise); @@ -2689,7 +2691,10 @@ class MessagesManager final : public Actor { ChatReactions get_message_available_reactions(const Dialog *d, const Message *m); - void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); + void set_message_reactions(Dialog *d, Message *m, string reaction, bool is_big, bool add_to_recent, + Promise &&promise); + + void on_set_message_reactions(FullMessageId full_message_id, Result result, Promise promise); void set_dialog_available_reactions(Dialog *d, ChatReactions &&available_reactions); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 1cd984baa..b6036c749 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5210,14 +5210,21 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque } } -void Td::on_request(uint64 id, td_api::setMessageReaction &request) { +void Td::on_request(uint64 id, td_api::addMessageReaction &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - messages_manager_->set_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)}, + messages_manager_->add_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)}, get_message_reaction_string(request.reaction_type_), request.is_big_, request.update_recent_reactions_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::removeMessageReaction &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + messages_manager_->remove_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)}, + get_message_reaction_string(request.reaction_type_), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.offset_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index a9384a249..2e39b417f 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -658,7 +658,9 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getMessageAvailableReactions &request); - void on_request(uint64 id, td_api::setMessageReaction &request); + void on_request(uint64 id, td_api::addMessageReaction &request); + + void on_request(uint64 id, td_api::removeMessageReaction &request); void on_request(uint64 id, td_api::getMessageAddedReactions &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index a1a7a5839..9ac3342a5 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2241,14 +2241,21 @@ class CliClient final : public Actor { MessageId message_id; get_args(args, chat_id, message_id); send_request(td_api::make_object(chat_id, message_id)); - } else if (op == "react" || op == "reactr") { + } else if (op == "amr" || op == "react") { ChatId chat_id; MessageId message_id; string reaction; bool is_big; - get_args(args, chat_id, message_id, reaction, is_big); - send_request(td_api::make_object(chat_id, message_id, as_reaction_type(reaction), - is_big, op == "reactr")); + bool update_recent_reactions; + get_args(args, chat_id, message_id, reaction, is_big, update_recent_reactions); + send_request(td_api::make_object(chat_id, message_id, as_reaction_type(reaction), + is_big, update_recent_reactions)); + } else if (op == "rmr") { + ChatId chat_id; + MessageId message_id; + string reaction; + get_args(args, chat_id, message_id, reaction); + send_request(td_api::make_object(chat_id, message_id, as_reaction_type(reaction))); } else if (op == "gmars") { ChatId chat_id; MessageId message_id; @@ -4786,7 +4793,7 @@ class CliClient final : public Actor { get_args(args, chat_id, file_id, reason, text); send_request( td_api::make_object(chat_id, file_id, get_chat_report_reason(reason), text)); - } else if (op == "rmr") { + } else if (op == "reportmr") { ChatId chat_id; MessageId message_id; string sender_id; From 55ec944266d3d1edff2d9e48e969936ab10b82d2 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 16:21:00 +0300 Subject: [PATCH 123/200] Pass all chosen reactions to send_message_reaction. --- td/telegram/MessageReaction.cpp | 17 ++++++----------- td/telegram/MessageReaction.h | 4 ++-- td/telegram/MessagesManager.cpp | 19 ++++++++++++------- td/telegram/MessagesManager.h | 3 +-- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 5cc15979e..283fdd595 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -169,7 +169,7 @@ class SendReactionQuery final : public Td::ResultHandler { explicit SendReactionQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent) { + void send(FullMessageId full_message_id, vector reactions, bool is_big, bool add_to_recent) { dialog_id_ = full_message_id.get_dialog_id(); auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read); @@ -178,7 +178,7 @@ class SendReactionQuery final : public Td::ResultHandler { } int32 flags = 0; - if (!reaction.empty()) { + if (!reactions.empty()) { flags |= telegram_api::messages_sendReaction::REACTION_MASK; if (is_big) { @@ -190,15 +190,10 @@ class SendReactionQuery final : public Td::ResultHandler { } } - vector> reactions; - if (!reaction.empty()) { - reactions.push_back(get_input_reaction(reaction)); - } - send_query(G()->net_query_creator().create( telegram_api::messages_sendReaction(flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), full_message_id.get_message_id().get_server_message_id().get(), - std::move(reactions)), + transform(reactions, get_input_reaction)), {{dialog_id_}, {full_message_id}})); } @@ -697,10 +692,10 @@ void reload_message_reactions(Td *td, DialogId dialog_id, vector &&me td->create_handler()->send(dialog_id, std::move(message_ids)); } -void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, - Promise &&promise) { +void send_message_reaction(Td *td, FullMessageId full_message_id, vector reactions, bool is_big, + bool add_to_recent, Promise &&promise) { td->create_handler(std::move(promise)) - ->send(full_message_id, std::move(reaction), is_big, add_to_recent); + ->send(full_message_id, std::move(reactions), is_big, add_to_recent); } void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit, diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 5fa8a2913..855b3c6ec 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -185,8 +185,8 @@ bool is_active_reaction(const string &reaction, const FlatHashMap &&message_ids); -void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, - Promise &&promise); +void send_message_reaction(Td *td, FullMessageId full_message_id, vector reactions, bool is_big, + bool add_to_recent, Promise &&promise); void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit, Promise> &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 22c9d9bbe..cd3739006 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24569,7 +24569,7 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string m->reactions->reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); } - set_message_reactions(d, m, reaction, is_big, add_to_recent, std::move(promise)); + set_message_reactions(d, m, is_big, add_to_recent, std::move(promise)); } void MessagesManager::remove_message_reaction(FullMessageId full_message_id, string reaction, Promise &&promise) { @@ -24612,18 +24612,24 @@ void MessagesManager::remove_message_reaction(FullMessageId full_message_id, str return promise.set_value(Unit()); } - set_message_reactions(d, m, reaction, false, false, std::move(promise)); + set_message_reactions(d, m, false, false, std::move(promise)); } -void MessagesManager::set_message_reactions(Dialog *d, Message *m, string reaction, bool is_big, bool add_to_recent, +void MessagesManager::set_message_reactions(Dialog *d, Message *m, bool is_big, bool add_to_recent, Promise &&promise) { CHECK(m->reactions != nullptr); + m->reactions->sort_reactions(active_reaction_pos_); + + vector reactions; + for (auto &reaction : m->reactions->reactions_) { + if (reaction.is_chosen()) { + reactions.push_back(reaction.get_reaction()); + } + } FullMessageId full_message_id{d->dialog_id, m->message_id}; pending_reactions_[full_message_id].query_count++; - m->reactions->sort_reactions(active_reaction_pos_); - send_update_message_interaction_info(d->dialog_id, m); on_message_changed(d, m, true, "set_message_reactions"); @@ -24633,8 +24639,7 @@ void MessagesManager::set_message_reactions(Dialog *d, Message *m, string reacti send_closure(actor_id, &MessagesManager::on_set_message_reactions, full_message_id, std::move(result), std::move(promise)); }); - ::td::set_message_reaction(td_, full_message_id, std::move(reaction), is_big, add_to_recent, - std::move(query_promise)); + send_message_reaction(td_, full_message_id, std::move(reactions), is_big, add_to_recent, std::move(query_promise)); } void MessagesManager::on_set_message_reactions(FullMessageId full_message_id, Result result, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index fe98e30eb..24da0586f 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2691,8 +2691,7 @@ class MessagesManager final : public Actor { ChatReactions get_message_available_reactions(const Dialog *d, const Message *m); - void set_message_reactions(Dialog *d, Message *m, string reaction, bool is_big, bool add_to_recent, - Promise &&promise); + void set_message_reactions(Dialog *d, Message *m, bool is_big, bool add_to_recent, Promise &&promise); void on_set_message_reactions(FullMessageId full_message_id, Result result, Promise promise); From a223067cd19a162fb4c424400c1302d26fe1d2f1 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 16:28:51 +0300 Subject: [PATCH 124/200] Add availableReactions.allow_custom_emoji. --- td/generate/scheme/td_api.tl | 4 ++-- td/telegram/ChatReactions.cpp | 3 ++- td/telegram/MessagesManager.cpp | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 01cdf79c6..565976b06 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2580,8 +2580,8 @@ addedReaction type:ReactionType sender_id:MessageSender = AddedReaction; //@description Represents a list of reactions added to a message @total_count The total number of found reactions @reactions The list of added reactions @next_offset The offset for the next request. If empty, there are no more results addedReactions total_count:int32 reactions:vector next_offset:string = AddedReactions; -//@description Represents a list of available reactions @reactions List of available reactions -availableReactions reactions:vector = AvailableReactions; +//@description Represents a list of reactions that can be added to a message @reactions List of available reactions @allow_custom_emoji True, if any other custom emoji reaction can be added +availableReactions reactions:vector allow_custom_emoji:Bool = AvailableReactions; //@description Contains stickers which must be used for emoji reaction animation rendering diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index 644e6b595..44421c679 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -80,7 +80,8 @@ td_api::object_ptr ChatReactions::get_chat_avail td_api::object_ptr ChatReactions::get_available_reactions_object() const { CHECK(!allow_all_); - return td_api::make_object(transform(reactions_, get_reaction_type_object)); + return td_api::make_object(transform(reactions_, get_reaction_type_object), + allow_custom_); } telegram_api::object_ptr ChatReactions::get_input_chat_reactions() const { diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index cd3739006..089b68779 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24512,6 +24512,9 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, } } } + if (!td_->option_manager_->get_option_boolean("is_premium")) { + active_reactions.allow_custom_ = false; + } return active_reactions; } From 89a1311c91ac394104bef5efb7dbad4d3d9c02c0 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 16:34:14 +0300 Subject: [PATCH 125/200] Add ChatReactions::is_allowed_reaction. --- td/telegram/ChatReactions.cpp | 8 ++++++++ td/telegram/ChatReactions.h | 2 ++ td/telegram/MessagesManager.cpp | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index 44421c679..dc838d5b6 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -71,6 +71,14 @@ ChatReactions ChatReactions::get_active_reactions(const FlatHashMap ChatReactions::get_chat_available_reactions_object() const { if (allow_all_) { return td_api::make_object(); diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h index b4fd358d5..9e88f3244 100644 --- a/td/telegram/ChatReactions.h +++ b/td/telegram/ChatReactions.h @@ -35,6 +35,8 @@ struct ChatReactions { ChatReactions get_active_reactions(const FlatHashMap &active_reaction_pos) const; + bool is_allowed_reaction(const string &reaction) const; + telegram_api::object_ptr get_input_chat_reactions() const; td_api::object_ptr get_chat_available_reactions_object() const; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 089b68779..1335a5d26 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24531,7 +24531,7 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Message not found")); } - if (!td::contains(get_message_available_reactions(d, m).reactions_, reaction)) { + if (!get_message_available_reactions(d, m).is_allowed_reaction(reaction)) { return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } From e0699944b36a265ad8626fa50d24d0d53b7d95c2 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 17:05:27 +0300 Subject: [PATCH 126/200] Add is_custom_reaction. --- td/telegram/ChatReactions.cpp | 2 +- td/telegram/MessageReaction.cpp | 16 ++++++++++------ td/telegram/MessageReaction.h | 2 ++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index dc838d5b6..a3a6d6b64 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -73,7 +73,7 @@ ChatReactions ChatReactions::get_active_reactions(const FlatHashMap get_input_reaction(const string if (reaction.empty()) { return telegram_api::make_object(); } - if (reaction[0] == '#') { + if (is_custom_reaction(reaction)) { return telegram_api::make_object(get_custom_emoji_id(reaction)); } return telegram_api::make_object(reaction); @@ -66,7 +66,7 @@ string get_message_reaction_string(const telegram_api::object_ptr(reaction.get())->emoticon_; - if (emoji[0] == '#') { + if (is_custom_reaction(emoji)) { return string(); } return emoji; @@ -82,7 +82,7 @@ string get_message_reaction_string(const telegram_api::object_ptr get_reaction_type_object(const string &reaction) { CHECK(!reaction.empty()); - if (reaction[0] == '#') { + if (is_custom_reaction(reaction)) { return td_api::make_object(get_custom_emoji_id(reaction)); } return td_api::make_object(reaction); @@ -95,7 +95,7 @@ string get_message_reaction_string(const td_api::object_ptrget_id()) { case td_api::reactionTypeEmoji::ID: { const string &emoji = static_cast(type.get())->emoji_; - if (!check_utf8(emoji) || emoji[0] == '#') { + if (!check_utf8(emoji) || is_custom_reaction(emoji)) { return string(); } return emoji; @@ -675,8 +675,12 @@ StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr &active_reaction_pos) { - return !reaction.empty() && (reaction[0] == '#' || active_reaction_pos.count(reaction) > 0); + return !reaction.empty() && (is_custom_reaction(reaction) || active_reaction_pos.count(reaction) > 0); } void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids) { @@ -726,7 +730,7 @@ void set_default_reaction(Td *td, string reaction, Promise &&promise) { if (reaction.empty()) { return promise.set_error(Status::Error(400, "Default reaction must be non-empty")); } - if (reaction[0] != '#' && !td->stickers_manager_->is_active_reaction(reaction)) { + if (!is_custom_reaction(reaction) && !td->stickers_manager_->is_active_reaction(reaction)) { return promise.set_error(Status::Error(400, "Can't set incative reaction as default")); } diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 855b3c6ec..5e8da9939 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -181,6 +181,8 @@ string get_message_reaction_string(const telegram_api::object_ptr &type); +bool is_custom_reaction(const string &reaction); + bool is_active_reaction(const string &reaction, const FlatHashMap &active_reaction_pos); void reload_message_reactions(Td *td, DialogId dialog_id, vector &&message_ids); From 28d3d1ab375cb8181d23e04c519712ef95028147 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 17:43:21 +0300 Subject: [PATCH 127/200] Add MessageReactis::add_reaction/remove_reaction. --- td/telegram/MessageReaction.cpp | 56 +++++++++++++++++++++++++++- td/telegram/MessageReaction.h | 6 ++- td/telegram/MessagesManager.cpp | 65 ++++----------------------------- 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 441fc70a8..807aca93d 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -414,7 +414,7 @@ void MessageReaction::update_recent_chooser_dialog_ids(const MessageReaction &ol recent_chooser_min_channels_ = old_reaction.recent_chooser_min_channels_; } -void MessageReaction::set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, bool can_get_added_reactions) { +void MessageReaction::set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, bool have_recent_choosers) { if (is_chosen_ == is_chosen) { return; } @@ -423,7 +423,7 @@ void MessageReaction::set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, if (chooser_dialog_id.is_valid()) { choose_count_ += is_chosen_ ? 1 : -1; - if (can_get_added_reactions) { + if (have_recent_choosers) { remove_recent_chooser_dialog_id(chooser_dialog_id); if (is_chosen_) { add_recent_chooser_dialog_id(chooser_dialog_id); @@ -601,6 +601,58 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) { } } +bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogId chooser_dialog_id, + bool have_recent_choosers) { + bool is_found = false; + for (auto it = reactions_.begin(); it != reactions_.end();) { + auto &message_reaction = *it; + if (message_reaction.is_chosen()) { + if (message_reaction.get_reaction() == reaction && !is_big) { + return false; + } + message_reaction.set_is_chosen(false, chooser_dialog_id, have_recent_choosers); + } + if (message_reaction.get_reaction() == reaction) { + message_reaction.set_is_chosen(true, chooser_dialog_id, have_recent_choosers); + is_found = true; + } + + if (message_reaction.is_empty()) { + it = reactions_.erase(it); + } else { + ++it; + } + } + + if (!is_found) { + return true; + } + + vector recent_chooser_dialog_ids; + if (have_recent_choosers) { + recent_chooser_dialog_ids.push_back(chooser_dialog_id); + } + reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); + return true; +} + +bool MessageReactions::remove_reaction(const string &reaction, DialogId chooser_dialog_id, bool have_recent_choosers) { + for (auto it = reactions_.begin(); it != reactions_.end(); ++it) { + auto &message_reaction = *it; + if (message_reaction.get_reaction() == reaction) { + if (message_reaction.is_chosen()) { + message_reaction.set_is_chosen(false, chooser_dialog_id, have_recent_choosers); + if (message_reaction.is_empty()) { + it = reactions_.erase(it); + } + return true; + } + break; + } + } + return false; +} + void MessageReactions::sort_reactions(const FlatHashMap &active_reaction_pos) { std::sort(reactions_.begin(), reactions_.end(), [&active_reaction_pos](const MessageReaction &lhs, const MessageReaction &rhs) { diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 5e8da9939..e77243e61 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -63,7 +63,7 @@ class MessageReaction { return is_chosen_; } - void set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, bool can_get_added_reactions); + void set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, bool have_recent_choosers); int32 get_choose_count() const { return choose_count_; @@ -152,6 +152,10 @@ struct MessageReactions { void update_from(const MessageReactions &old_reactions); + bool add_reaction(const string &reaction, bool is_big, DialogId chooser_dialog_id, bool have_recent_choosers); + + bool remove_reaction(const string &reaction, DialogId chooser_dialog_id, bool have_recent_choosers); + void sort_reactions(const FlatHashMap &active_reaction_pos); void fix_chosen_reaction(DialogId my_dialog_id); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1335a5d26..d7160663b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24526,7 +24526,7 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Chat not found")); } - Message *m = get_message_force(d, full_message_id.get_message_id(), "set_message_reaction"); + Message *m = get_message_force(d, full_message_id.get_message_id(), "add_message_reaction"); if (m == nullptr) { return promise.set_error(Status::Error(400, "Message not found")); } @@ -24535,41 +24535,15 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } - bool can_get_added_reactions = !is_broadcast_channel(dialog_id) && dialog_id.get_type() != DialogType::User && - !is_discussion_message(dialog_id, m); + bool have_recent_choosers = !is_broadcast_channel(dialog_id) && !is_discussion_message(dialog_id, m); if (m->reactions == nullptr) { m->reactions = make_unique(); - m->reactions->can_get_added_reactions_ = can_get_added_reactions; + m->reactions->can_get_added_reactions_ = have_recent_choosers && dialog_id.get_type() != DialogType::User; m->available_reactions_generation = d->available_reactions_generation; } - bool is_found = false; - for (auto it = m->reactions->reactions_.begin(); it != m->reactions->reactions_.end();) { - auto &message_reaction = *it; - if (message_reaction.is_chosen()) { - if (message_reaction.get_reaction() == reaction && !is_big) { - return promise.set_value(Unit()); - } - message_reaction.set_is_chosen(false, get_my_dialog_id(), can_get_added_reactions); - } - if (message_reaction.get_reaction() == reaction) { - message_reaction.set_is_chosen(true, get_my_dialog_id(), can_get_added_reactions); - is_found = true; - } - - if (message_reaction.is_empty()) { - it = m->reactions->reactions_.erase(it); - } else { - ++it; - } - } - - if (!is_found) { - vector recent_chooser_dialog_ids; - if (!is_broadcast_channel(dialog_id)) { - recent_chooser_dialog_ids.push_back(get_my_dialog_id()); - } - m->reactions->reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); + if (!m->reactions->add_reaction(reaction, is_big, get_my_dialog_id(), have_recent_choosers)) { + return promise.set_value(Unit()); } set_message_reactions(d, m, is_big, add_to_recent, std::move(promise)); @@ -24582,36 +24556,13 @@ void MessagesManager::remove_message_reaction(FullMessageId full_message_id, str return promise.set_error(Status::Error(400, "Chat not found")); } - Message *m = get_message_force(d, full_message_id.get_message_id(), "set_message_reaction"); + Message *m = get_message_force(d, full_message_id.get_message_id(), "remove_message_reaction"); if (m == nullptr) { return promise.set_error(Status::Error(400, "Message not found")); } - bool can_get_added_reactions = !is_broadcast_channel(dialog_id) && dialog_id.get_type() != DialogType::User && - !is_discussion_message(dialog_id, m); - if (m->reactions == nullptr) { - return promise.set_value(Unit()); - } - - bool is_found = false; - for (auto it = m->reactions->reactions_.begin(); it != m->reactions->reactions_.end();) { - auto &message_reaction = *it; - if (message_reaction.get_reaction() == reaction) { - if (message_reaction.is_chosen()) { - message_reaction.set_is_chosen(false, get_my_dialog_id(), can_get_added_reactions); - is_found = true; - } else { - return promise.set_value(Unit()); - } - } - - if (message_reaction.is_empty()) { - it = m->reactions->reactions_.erase(it); - } else { - ++it; - } - } - if (!is_found) { + bool have_recent_choosers = !is_broadcast_channel(dialog_id) && !is_discussion_message(dialog_id, m); + if (m->reactions == nullptr || !m->reactions->remove_reaction(reaction, get_my_dialog_id(), have_recent_choosers)) { return promise.set_value(Unit()); } From 6fb097dfe008bcf7cb6b816f54345532db9fd3d7 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 18:15:03 +0300 Subject: [PATCH 128/200] Return only reactions that can be added in getMessageAvailableReactions. --- td/telegram/MessagesManager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d7160663b..c82fb7041 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6942,7 +6942,7 @@ td_api::object_ptr MessagesManager::get_message_ DialogId dialog_id, const Message *m) const { bool is_visible_reply_info = is_visible_message_reply_info(dialog_id, m); bool has_reactions = - is_visible_message_reactions(dialog_id, m) && m->reactions != nullptr && !m->reactions->reactions_.empty(); + m->reactions != nullptr && !m->reactions->reactions_.empty() && is_visible_message_reactions(dialog_id, m); if (m->view_count == 0 && m->forward_count == 0 && !is_visible_reply_info && !has_reactions) { return nullptr; } @@ -24502,10 +24502,9 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, } if (m->reactions != nullptr) { for (const auto &reaction : m->reactions->reactions_) { - // we always can remove a currently chosen reaction // an already used reaction can be added if it is an active reaction const string &reaction_str = reaction.get_reaction(); - if (reaction.is_chosen() || (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_))) { + if (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_)) { if (!td::contains(active_reactions.reactions_, reaction_str)) { active_reactions.reactions_.push_back(reaction_str); } From 79fcd079561bc540caaee3a0d32e203e4af7c451 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 18:24:42 +0300 Subject: [PATCH 129/200] Add internal options "reactions_user_max_*". --- td/telegram/ConfigManager.cpp | 5 +++++ td/telegram/OptionManager.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 685c1fb6a..00cd88b1d 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1806,6 +1806,11 @@ void ConfigManager::process_app_config(tl_object_ptr &c G()->set_option_integer("themed_emoji_statuses_sticker_set_id", setting_value); continue; } + if (key == "reactions_user_max_default" || key == "reactions_user_max_premium") { + auto setting_value = get_json_value_int(std::move(key_value->value_), key); + G()->set_option_integer(key, setting_value); + continue; + } new_values.push_back(std::move(key_value)); } diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 36ef4daf9..3f2e6f99b 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -272,8 +272,9 @@ bool OptionManager::is_internal_option(Slice name) { case 'p': return name == "premium_bot_username" || name == "premium_features" || name == "premium_invoice_slug"; case 'r': - return name == "rating_e_decay" || name == "reactions_uniq_max" || name == "recent_stickers_limit" || - name == "revoke_pm_inbox" || name == "revoke_time_limit" || name == "revoke_pm_time_limit"; + return name == "rating_e_decay" || name == "reactions_uniq_max" || name == "reactions_user_max_default" || + name == "reactions_user_max_premium" || name == "recent_stickers_limit" || name == "revoke_pm_inbox" || + name == "revoke_time_limit" || name == "revoke_pm_time_limit"; case 's': return name == "saved_animations_limit" || name == "saved_gifs_limit_default" || name == "saved_gifs_limit_premium" || name == "session_count" || name == "stickers_faved_limit_default" || From 52fbb073fe72d5200fc4bcc3c6c15b7699ab16db Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 19:42:02 +0300 Subject: [PATCH 130/200] Fix reaction updating. --- td/telegram/MessagesManager.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c82fb7041..37d6280cf 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7093,9 +7093,15 @@ bool MessagesManager::update_message_interaction_info(Dialog *d, Message *m, int } } } - } else if (m->available_reactions_generation != d->available_reactions_generation) { - m->available_reactions_generation = d->available_reactions_generation; - on_message_changed(d, m, false, "update_message_interaction_info"); + } else if (has_reactions) { + bool is_changed = false; + if (m->available_reactions_generation != d->available_reactions_generation) { + m->available_reactions_generation = d->available_reactions_generation; + is_changed = true; + } + if (is_changed) { + on_message_changed(d, m, false, "update_message_interaction_info"); + } } if (need_update) { send_update_message_interaction_info(dialog_id, m); @@ -7104,7 +7110,7 @@ bool MessagesManager::update_message_interaction_info(Dialog *d, Message *m, int send_update_message_unread_reactions(dialog_id, m, new_dialog_unread_reaction_count); } return true; - } else if (m->available_reactions_generation != d->available_reactions_generation) { + } else if (has_reactions && m->available_reactions_generation != d->available_reactions_generation) { m->available_reactions_generation = d->available_reactions_generation; on_message_changed(d, m, false, "update_message_interaction_info"); } From 345c930aa73f360c72cba7349353e3027065ea20 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 9 Sep 2022 19:42:14 +0300 Subject: [PATCH 131/200] Explicitly disallow removal of an empty reaction. --- td/telegram/MessagesManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 37d6280cf..d192e84e5 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24566,6 +24566,10 @@ void MessagesManager::remove_message_reaction(FullMessageId full_message_id, str return promise.set_error(Status::Error(400, "Message not found")); } + if (reaction.empty()) { + return promise.set_error(Status::Error(400, "Invalid reaction specified")); + } + bool have_recent_choosers = !is_broadcast_channel(dialog_id) && !is_discussion_message(dialog_id, m); if (m->reactions == nullptr || !m->reactions->remove_reaction(reaction, get_my_dialog_id(), have_recent_choosers)) { return promise.set_value(Unit()); From ce9175a00b5fe60c653fc36dbb4f33af8a2b0820 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 10 Sep 2022 22:48:34 +0300 Subject: [PATCH 132/200] Always use "must be non-empty". --- td/telegram/BotMenuButton.cpp | 2 +- td/telegram/InlineQueriesManager.cpp | 2 +- td/telegram/MessageContent.cpp | 2 +- td/telegram/MessagesManager.cpp | 6 +++--- td/telegram/PhoneNumberManager.cpp | 6 +++--- td/telegram/ReplyMarkup.cpp | 2 +- td/telegram/StickersManager.cpp | 10 +++++----- td/telegram/files/FileManager.cpp | 2 +- tdutils/td/utils/FileLog.cpp | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/td/telegram/BotMenuButton.cpp b/td/telegram/BotMenuButton.cpp index 32c18c418..3b997e06b 100644 --- a/td/telegram/BotMenuButton.cpp +++ b/td/telegram/BotMenuButton.cpp @@ -133,7 +133,7 @@ void set_menu_button(Td *td, UserId user_id, td_api::object_ptr(); } else if (menu_button->text_.empty()) { if (menu_button->url_ != "default") { - return promise.set_error(Status::Error(400, "Menu button text can't be empty")); + return promise.set_error(Status::Error(400, "Menu button text must be non-empty")); } input_bot_menu_button = telegram_api::make_object(); } else { diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 5aa673229..fd04b7991 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -346,7 +346,7 @@ Result> InlineQueriesManager: tl_object_ptr &&input_message_content, tl_object_ptr &&reply_markup_ptr, int32 allowed_media_content_id) const { if (input_message_content == nullptr) { - return Status::Error(400, "Inline message can't be empty"); + return Status::Error(400, "Inline message must be non-empty"); } TRY_RESULT(reply_markup, get_reply_markup(std::move(reply_markup_ptr), true, true, false, true)); auto input_reply_markup = get_input_reply_markup(td_->contacts_manager_.get(), reply_markup); diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 72b43b62b..fe198606c 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2794,7 +2794,7 @@ bool can_forward_message_content(const MessageContent *content) { auto content_type = content->get_type(); if (content_type == MessageContentType::Text) { auto *text = static_cast(content); - return !is_empty_string(text->text.text); // text can't be empty in the new message + return !is_empty_string(text->text.text); // text must be non-empty in the new message } if (content_type == MessageContentType::Poll) { auto *poll = static_cast(content); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d192e84e5..b0949c2c2 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20696,7 +20696,7 @@ DialogId MessagesManager::create_new_group_chat(const vector &user_ids, auto new_title = clean_name(title, MAX_TITLE_LENGTH); if (new_title.empty()) { - promise.set_error(Status::Error(400, "Title can't be empty")); + promise.set_error(Status::Error(400, "Title must be non-empty")); return DialogId(); } @@ -20744,7 +20744,7 @@ DialogId MessagesManager::create_new_channel_chat(const string &title, bool is_m auto new_title = clean_name(title, MAX_TITLE_LENGTH); if (new_title.empty()) { - promise.set_error(Status::Error(400, "Title can't be empty")); + promise.set_error(Status::Error(400, "Title must be non-empty")); return DialogId(); } @@ -33748,7 +33748,7 @@ void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, auto new_title = clean_name(title, MAX_TITLE_LENGTH); if (new_title.empty()) { - return promise.set_error(Status::Error(400, "Title can't be empty")); + return promise.set_error(Status::Error(400, "Title must be non-empty")); } switch (dialog_id.get_type()) { diff --git a/td/telegram/PhoneNumberManager.cpp b/td/telegram/PhoneNumberManager.cpp index 4c8742efd..8ef10aca1 100644 --- a/td/telegram/PhoneNumberManager.cpp +++ b/td/telegram/PhoneNumberManager.cpp @@ -45,7 +45,7 @@ void PhoneNumberManager::send_new_send_code_query(uint64 query_id, const telegra void PhoneNumberManager::set_phone_number(uint64 query_id, string phone_number, Settings settings) { if (phone_number.empty()) { - return on_query_error(query_id, Status::Error(400, "Phone number can't be empty")); + return on_query_error(query_id, Status::Error(400, "Phone number must be non-empty")); } switch (type_) { @@ -64,10 +64,10 @@ void PhoneNumberManager::set_phone_number(uint64 query_id, string phone_number, void PhoneNumberManager::set_phone_number_and_hash(uint64 query_id, string hash, string phone_number, Settings settings) { if (phone_number.empty()) { - return on_query_error(query_id, Status::Error(400, "Phone number can't be empty")); + return on_query_error(query_id, Status::Error(400, "Phone number must be non-empty")); } if (hash.empty()) { - return on_query_error(query_id, Status::Error(400, "Hash can't be empty")); + return on_query_error(query_id, Status::Error(400, "Hash must be non-empty")); } switch (type_) { diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index a0e42ac33..f3771a20f 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -500,7 +500,7 @@ static Result get_inline_keyboard_button(tl_object_ptrtext_); if (button->type_ == nullptr) { - return Status::Error(400, "Inline keyboard button type can't be empty"); + return Status::Error(400, "Inline keyboard button type must be non-empty"); } int32 button_type_id = button->type_->get_id(); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 196fec0ba..5810edb45 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -6995,7 +6995,7 @@ tl_object_ptr StickersManager::get_input_stic void StickersManager::get_suggested_sticker_set_name(string title, Promise &&promise) { title = strip_empty_characters(title, MAX_STICKER_SET_TITLE_LENGTH); if (title.empty()) { - return promise.set_error(Status::Error(400, "Sticker set title can't be empty")); + return promise.set_error(Status::Error(400, "Sticker set title must be non-empty")); } td_->create_handler(std::move(promise))->send(title); @@ -7052,12 +7052,12 @@ void StickersManager::create_new_sticker_set(UserId user_id, string title, strin title = strip_empty_characters(title, MAX_STICKER_SET_TITLE_LENGTH); if (title.empty()) { - return promise.set_error(Status::Error(400, "Sticker set title can't be empty")); + return promise.set_error(Status::Error(400, "Sticker set title must be non-empty")); } short_name = strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH); if (short_name.empty()) { - return promise.set_error(Status::Error(400, "Sticker set name can't be empty")); + return promise.set_error(Status::Error(400, "Sticker set name must be non-empty")); } if (stickers.empty()) { @@ -7292,7 +7292,7 @@ void StickersManager::add_sticker_to_set(UserId user_id, string short_name, short_name = clean_username(strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH)); if (short_name.empty()) { - return promise.set_error(Status::Error(400, "Sticker set name can't be empty")); + return promise.set_error(Status::Error(400, "Sticker set name must be non-empty")); } const StickerSet *sticker_set = get_sticker_set(short_name_to_sticker_set_id_.get(short_name)); @@ -7386,7 +7386,7 @@ void StickersManager::set_sticker_set_thumbnail(UserId user_id, string short_nam short_name = clean_username(strip_empty_characters(short_name, MAX_STICKER_SET_SHORT_NAME_LENGTH)); if (short_name.empty()) { - return promise.set_error(Status::Error(400, "Sticker set name can't be empty")); + return promise.set_error(Status::Error(400, "Sticker set name must be non-empty")); } const StickerSet *sticker_set = get_sticker_set(short_name_to_sticker_set_id_.get(short_name)); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 4b958b947..1119865d5 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -2913,7 +2913,7 @@ Result FileManager::from_persistent_id(CSlice persistent_id, FileType fi } auto binary = r_binary.move_as_ok(); if (binary.empty()) { - return Status::Error(400, "Remote file identifier can't be empty"); + return Status::Error(400, "Remote file identifier must be non-empty"); } if (binary.back() == FileNode::PERSISTENT_ID_VERSION_OLD) { return from_persistent_id_v2(binary, file_type); diff --git a/tdutils/td/utils/FileLog.cpp b/tdutils/td/utils/FileLog.cpp index 18b4cc1a2..16d294233 100644 --- a/tdutils/td/utils/FileLog.cpp +++ b/tdutils/td/utils/FileLog.cpp @@ -18,7 +18,7 @@ namespace td { Status FileLog::init(string path, int64 rotate_threshold, bool redirect_stderr) { if (path.empty()) { - return Status::Error("Log file path can't be empty"); + return Status::Error("Log file path must be non-empty"); } if (path == path_) { set_rotate_threshold(rotate_threshold); From e07ab8e71ae61533e7d2da5f5a9418fd73d9bba0 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 11 Sep 2022 13:35:25 +0300 Subject: [PATCH 133/200] Save chosen reaction order. --- td/telegram/MessageReaction.cpp | 15 +++++++++++++-- td/telegram/MessageReaction.h | 1 + td/telegram/MessageReaction.hpp | 10 ++++++++++ td/telegram/MessagesManager.cpp | 8 +++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 807aca93d..cb1f8f0dc 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -491,6 +491,7 @@ unique_ptr MessageReactions::get_message_reactions( result->is_min_ = reactions->min_; FlatHashSet reaction_strings; + vector> chosen_reaction_order; for (auto &reaction_count : reactions->results_) { auto reaction_str = get_message_reaction_string(reaction_count->reaction_); if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT || @@ -552,9 +553,17 @@ unique_ptr MessageReactions::get_message_reactions( } bool is_chosen = (reaction_count->flags_ & telegram_api::reactionCount::CHOSEN_ORDER_MASK) != 0; + if (is_chosen) { + chosen_reaction_order.emplace_back(reaction_count->chosen_order_, reaction_str); + } result->reactions_.emplace_back(std::move(reaction_str), reaction_count->count_, is_chosen, std::move(recent_chooser_dialog_ids), std::move(recent_chooser_min_channels)); } + if (chosen_reaction_order.size() > 1) { + std::sort(chosen_reaction_order.begin(), chosen_reaction_order.end()); + result->chosen_reaction_order_ = + transform(chosen_reaction_order, [](const std::pair &order) { return order.second; }); + } return result; } @@ -589,6 +598,7 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) { } } unread_reactions_ = old_reactions.unread_reactions_; + chosen_reaction_order_ = old_reactions.chosen_reaction_order_; } for (const auto &old_reaction : old_reactions.reactions_) { if (old_reaction.is_chosen() && @@ -700,7 +710,7 @@ bool MessageReactions::need_update_message_reactions(const MessageReactions *old return true; } - // unread_reactions_ are updated independently; compare all other fields + // unread_reactions_ and chosen_reaction_order_ are updated independently; compare all other fields return old_reactions->reactions_ != new_reactions->reactions_ || old_reactions->is_min_ != new_reactions->is_min_ || old_reactions->can_get_added_reactions_ != new_reactions->can_get_added_reactions_ || old_reactions->need_polling_ != new_reactions->need_polling_; @@ -716,7 +726,8 @@ bool MessageReactions::need_update_unread_reactions(const MessageReactions *old_ StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions &reactions) { return string_builder << (reactions.is_min_ ? "Min" : "") << "MessageReactions{" << reactions.reactions_ - << " with unread " << reactions.unread_reactions_ + << " with unread " << reactions.unread_reactions_ << ", reaction order " + << reactions.chosen_reaction_order_ << " and can_get_added_reactions = " << reactions.can_get_added_reactions_; } diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index e77243e61..7c7d35957 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -136,6 +136,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const UnreadMessageReac struct MessageReactions { vector reactions_; vector unread_reactions_; + vector chosen_reaction_order_; bool is_min_ = false; bool need_polling_ = true; bool can_get_added_reactions_ = false; diff --git a/td/telegram/MessageReaction.hpp b/td/telegram/MessageReaction.hpp index 4c8e7f8a3..040604b58 100644 --- a/td/telegram/MessageReaction.hpp +++ b/td/telegram/MessageReaction.hpp @@ -77,12 +77,14 @@ template void MessageReactions::store(StorerT &storer) const { bool has_reactions = !reactions_.empty(); bool has_unread_reactions = !unread_reactions_.empty(); + bool has_chosen_reaction_order = !chosen_reaction_order_.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_min_); STORE_FLAG(need_polling_); STORE_FLAG(can_get_added_reactions_); STORE_FLAG(has_unread_reactions); STORE_FLAG(has_reactions); + STORE_FLAG(has_chosen_reaction_order); END_STORE_FLAGS(); if (has_reactions) { td::store(reactions_, storer); @@ -90,18 +92,23 @@ void MessageReactions::store(StorerT &storer) const { if (has_unread_reactions) { td::store(unread_reactions_, storer); } + if (has_chosen_reaction_order) { + td::store(chosen_reaction_order_, storer); + } } template void MessageReactions::parse(ParserT &parser) { bool has_reactions; bool has_unread_reactions; + bool has_chosen_reaction_order; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_min_); PARSE_FLAG(need_polling_); PARSE_FLAG(can_get_added_reactions_); PARSE_FLAG(has_unread_reactions); PARSE_FLAG(has_reactions); + PARSE_FLAG(has_chosen_reaction_order); END_PARSE_FLAGS(); if (has_reactions) { td::parse(reactions_, parser); @@ -109,6 +116,9 @@ void MessageReactions::parse(ParserT &parser) { if (has_unread_reactions) { td::parse(unread_reactions_, parser); } + if (has_chosen_reaction_order) { + td::parse(chosen_reaction_order_, parser); + } } } // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b0949c2c2..6afa68b95 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7032,8 +7032,10 @@ bool MessagesManager::update_message_interaction_info(Dialog *d, Message *m, int has_reactions && MessageReactions::need_update_message_reactions(m->reactions.get(), reactions.get()); bool need_update_unread_reactions = has_reactions && MessageReactions::need_update_unread_reactions(m->reactions.get(), reactions.get()); + bool need_update_chosen_reaction_order = has_reactions && reactions != nullptr && m->reactions != nullptr && + m->reactions->chosen_reaction_order_ != reactions->chosen_reaction_order_; if (view_count > m->view_count || forward_count > m->forward_count || need_update_reply_info || - need_update_reactions || need_update_unread_reactions) { + need_update_reactions || need_update_unread_reactions || need_update_chosen_reaction_order) { LOG(DEBUG) << "Update interaction info of " << FullMessageId{dialog_id, m->message_id} << " from " << m->view_count << '/' << m->forward_count << '/' << m->reply_info << '/' << m->reactions << " to " << view_count << '/' << forward_count << '/' << reply_info << '/' << reactions; @@ -7099,6 +7101,10 @@ bool MessagesManager::update_message_interaction_info(Dialog *d, Message *m, int m->available_reactions_generation = d->available_reactions_generation; is_changed = true; } + if (need_update_chosen_reaction_order) { + m->reactions->chosen_reaction_order_ = std::move(reactions->chosen_reaction_order_); + is_changed = true; + } if (is_changed) { on_message_changed(d, m, false, "update_message_interaction_info"); } From 2ee994aed19f09b19a518664d3b084eeecf743d9 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 11 Sep 2022 14:06:01 +0300 Subject: [PATCH 134/200] Add MessageReactions::get_chosen_reactions. --- td/telegram/MessageReaction.cpp | 14 ++++++++++++++ td/telegram/MessageReaction.h | 2 ++ td/telegram/MessagesManager.cpp | 10 ++-------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index cb1f8f0dc..c50df327e 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -699,6 +699,20 @@ void MessageReactions::fix_chosen_reaction(DialogId my_dialog_id) { } } +vector MessageReactions::get_chosen_reactions() const { + if (!chosen_reaction_order_.empty()) { + return chosen_reaction_order_; + } + + vector reaction_order; + for (auto &reaction : reactions_) { + if (reaction.is_chosen()) { + reaction_order.push_back(reaction.get_reaction()); + } + } + return reaction_order; +} + bool MessageReactions::need_update_message_reactions(const MessageReactions *old_reactions, const MessageReactions *new_reactions) { if (old_reactions == nullptr) { diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 7c7d35957..70d900058 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -161,6 +161,8 @@ struct MessageReactions { void fix_chosen_reaction(DialogId my_dialog_id); + vector get_chosen_reactions() const; + static bool need_update_message_reactions(const MessageReactions *old_reactions, const MessageReactions *new_reactions); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 6afa68b95..0a4529cd5 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24589,13 +24589,6 @@ void MessagesManager::set_message_reactions(Dialog *d, Message *m, bool is_big, CHECK(m->reactions != nullptr); m->reactions->sort_reactions(active_reaction_pos_); - vector reactions; - for (auto &reaction : m->reactions->reactions_) { - if (reaction.is_chosen()) { - reactions.push_back(reaction.get_reaction()); - } - } - FullMessageId full_message_id{d->dialog_id, m->message_id}; pending_reactions_[full_message_id].query_count++; @@ -24608,7 +24601,8 @@ void MessagesManager::set_message_reactions(Dialog *d, Message *m, bool is_big, send_closure(actor_id, &MessagesManager::on_set_message_reactions, full_message_id, std::move(result), std::move(promise)); }); - send_message_reaction(td_, full_message_id, std::move(reactions), is_big, add_to_recent, std::move(query_promise)); + send_message_reaction(td_, full_message_id, m->reactions->get_chosen_reactions(), is_big, add_to_recent, + std::move(query_promise)); } void MessagesManager::on_set_message_reactions(FullMessageId full_message_id, Result result, From f119e867df4fd7b655cd356fa4795eb1967f6ff4 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 11 Sep 2022 15:10:56 +0300 Subject: [PATCH 135/200] Update chosen reaction order when reactions are added or removed. --- td/telegram/MessageReaction.cpp | 61 ++++++++++++++++++++------------- td/telegram/MessageReaction.h | 3 ++ td/telegram/MessagesManager.cpp | 2 ++ 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index c50df327e..7a790e6c1 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -613,40 +613,55 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) { bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogId chooser_dialog_id, bool have_recent_choosers) { - bool is_found = false; - for (auto it = reactions_.begin(); it != reactions_.end();) { - auto &message_reaction = *it; - if (message_reaction.is_chosen()) { - if (message_reaction.get_reaction() == reaction && !is_big) { - return false; - } - message_reaction.set_is_chosen(false, chooser_dialog_id, have_recent_choosers); - } - if (message_reaction.get_reaction() == reaction) { - message_reaction.set_is_chosen(true, chooser_dialog_id, have_recent_choosers); - is_found = true; - } + vector new_chosen_reaction_order = get_chosen_reactions(); - if (message_reaction.is_empty()) { - it = reactions_.erase(it); - } else { - ++it; + auto added_reaction = get_reaction(reaction); + if (added_reaction == nullptr) { + vector recent_chooser_dialog_ids; + if (have_recent_choosers) { + recent_chooser_dialog_ids.push_back(chooser_dialog_id); } + reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); + new_chosen_reaction_order.emplace_back(reaction); + } else if (!added_reaction->is_chosen()) { + added_reaction->set_is_chosen(true, chooser_dialog_id, have_recent_choosers); + new_chosen_reaction_order.emplace_back(reaction); + } else if (!is_big) { + return false; } - if (!is_found) { - return true; + bool is_premium = G()->get_option_boolean("is_premium"); + auto option_key = is_premium ? Slice("reactions_user_max_premium") : Slice("reactions_user_max_default"); + int32 max_reaction_count = max(1, static_cast(G()->get_option_integer(option_key, is_premium ? 3 : 1))); + if (new_chosen_reaction_order.size() > static_cast(max_reaction_count)) { + bool is_removed = do_remove_reaction(new_chosen_reaction_order[0], chooser_dialog_id, have_recent_choosers); + CHECK(is_removed); + new_chosen_reaction_order.erase(new_chosen_reaction_order.begin()); } - vector recent_chooser_dialog_ids; - if (have_recent_choosers) { - recent_chooser_dialog_ids.push_back(chooser_dialog_id); + if (new_chosen_reaction_order.size() == 1) { + new_chosen_reaction_order.clear(); } - reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); + chosen_reaction_order_ = std::move(new_chosen_reaction_order); return true; } bool MessageReactions::remove_reaction(const string &reaction, DialogId chooser_dialog_id, bool have_recent_choosers) { + if (do_remove_reaction(reaction, chooser_dialog_id, have_recent_choosers)) { + if (!chosen_reaction_order_.empty()) { + bool is_removed = td::remove(chosen_reaction_order_, reaction); + CHECK(is_removed); + if (chosen_reaction_order_.size() <= 1) { + reset_to_empty(chosen_reaction_order_); + } + } + return true; + } + return false; +} + +bool MessageReactions::do_remove_reaction(const string &reaction, DialogId chooser_dialog_id, + bool have_recent_choosers) { for (auto it = reactions_.begin(); it != reactions_.end(); ++it) { auto &message_reaction = *it; if (message_reaction.get_reaction() == reaction) { diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 70d900058..dda90a1f6 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -174,6 +174,9 @@ struct MessageReactions { template void parse(ParserT &parser); + + private: + bool do_remove_reaction(const string &reaction, DialogId chooser_dialog_id, bool have_recent_choosers); }; StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions &reactions); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0a4529cd5..5a13af7c0 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24589,6 +24589,8 @@ void MessagesManager::set_message_reactions(Dialog *d, Message *m, bool is_big, CHECK(m->reactions != nullptr); m->reactions->sort_reactions(active_reaction_pos_); + LOG(INFO) << "Update message reactions to " << *m->reactions; + FullMessageId full_message_id{d->dialog_id, m->message_id}; pending_reactions_[full_message_id].query_count++; From d29d3674ba4ff673369cf39b746c8388f394fda5 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 01:35:47 +0300 Subject: [PATCH 136/200] Replace updateReactions with updateActiveEmojiReactions. --- td/generate/scheme/td_api.tl | 6 ++-- td/telegram/StickersManager.cpp | 52 +++++++++++++++++++++++---------- td/telegram/StickersManager.h | 7 ++++- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 565976b06..1fddcc358 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4489,8 +4489,8 @@ updateAttachmentMenuBots bots:vector = Update; //@description A message was sent by an opened Web App, so the Web App needs to be closed @web_app_launch_id Identifier of Web App launch updateWebAppMessageSent web_app_launch_id:int64 = Update; -//@description The list of supported reactions has changed @reactions The new list of supported reactions -updateReactions reactions:vector = Update; +//@description The list of active emoji reactions has changed @emojis The new list of active emoji reactions +updateActiveEmojiReactions emojis:vector = Update; //@description The type of default reaction has changed @reaction_type The new type of the default reaction updateDefaultReactionType reaction_type:ReactionType = Update; @@ -5164,7 +5164,7 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok; -//@description Returns reactions, which can be added to a message. The list can change after updateReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message +//@description Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 5810edb45..b50a7ea30 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1450,7 +1450,7 @@ void StickersManager::init() { } send_closure(G()->td(), &Td::send_update, get_update_dice_emojis_object()); - send_closure_later(actor_id(this), &StickersManager::load_reactions); + load_active_reactions(); on_update_dice_success_values(); on_update_dice_emojis(); @@ -3654,15 +3654,14 @@ void StickersManager::on_get_special_sticker_set(const SpecialStickerSetType &ty on_load_special_sticker_set(type, Status::OK()); } -td_api::object_ptr StickersManager::get_update_reactions_object() const { - auto reactions = transform(reactions_.reactions_, [this](const Reaction &reaction) { - return td_api::make_object( - reaction.reaction_, reaction.title_, reaction.is_active_, get_sticker_object(reaction.static_icon_), - get_sticker_object(reaction.appear_animation_), get_sticker_object(reaction.select_animation_), - get_sticker_object(reaction.activate_animation_), get_sticker_object(reaction.effect_animation_), - get_sticker_object(reaction.around_animation_), get_sticker_object(reaction.center_animation_)); - }); - return td_api::make_object(std::move(reactions)); +td_api::object_ptr StickersManager::get_update_active_emoji_reactions_object() + const { + return td_api::make_object(vector(active_reactions_)); +} + +void StickersManager::save_active_reactions() { + LOG(INFO) << "Save active reactions"; + G()->td_db()->get_binlog_pmc()->set("active_reactions", log_event_store(active_reactions_).as_slice().str()); } void StickersManager::save_reactions() { @@ -3670,6 +3669,23 @@ void StickersManager::save_reactions() { G()->td_db()->get_binlog_pmc()->set("reactions", log_event_store(reactions_).as_slice().str()); } +void StickersManager::load_active_reactions() { + string active_reactions = G()->td_db()->get_binlog_pmc()->get("active_reactions"); + if (active_reactions.empty()) { + return reload_reactions(); + } + + auto status = log_event_parse(active_reactions_, active_reactions); + if (status.is_error()) { + LOG(ERROR) << "Can't load active reactions: " << status; + active_reactions_ = {}; + return reload_reactions(); + } + + LOG(INFO) << "Successfully loaded " << active_reactions_.size() << " active reactions"; + send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object()); +} + void StickersManager::load_reactions() { string reactions = G()->td_db()->get_binlog_pmc()->get("reactions"); if (reactions.empty()) { @@ -3691,8 +3707,6 @@ void StickersManager::load_reactions() { } LOG(INFO) << "Successfully loaded " << reactions_.reactions_.size() << " available reactions"; - send_closure(G()->td(), &Td::send_update, get_update_reactions_object()); - LOG(INFO) << "Successfully sent updateReactions"; update_active_reactions(); } @@ -3704,6 +3718,15 @@ void StickersManager::update_active_reactions() { active_reactions.emplace_back(reaction.reaction_); } } + if (active_reactions == active_reactions_) { + return; + } + active_reactions_ = active_reactions; + + save_active_reactions(); + + send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object()); + td_->messages_manager_->set_active_reactions(std::move(active_reactions)); } @@ -3760,7 +3783,6 @@ void StickersManager::on_get_available_reactions( } reactions_.reactions_ = std::move(new_reactions); reactions_.hash_ = available_reactions->hash_; - send_closure(G()->td(), &Td::send_update, get_update_reactions_object()); save_reactions(); @@ -8985,8 +9007,8 @@ void StickersManager::get_current_state(vector get_update_reactions_object() const; + td_api::object_ptr get_update_active_emoji_reactions_object() const; SpecialStickerSet &add_special_sticker_set(const SpecialStickerSetType &type); @@ -1004,6 +1008,7 @@ class StickersManager final : public Actor { FlatHashMap>, FileIdHash> being_uploaded_files_; Reactions reactions_; + vector active_reactions_; FlatHashMap> emoji_language_codes_; FlatHashMap emoji_language_code_versions_; From a33eb5233c4cb4c4a075d0d4c75cae3e748a4a90 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 15:03:35 +0300 Subject: [PATCH 137/200] Add td_api::getEmojiReaction. --- td/generate/scheme/td_api.tl | 12 +++++++----- td/telegram/StickersManager.cpp | 28 ++++++++++++++++++++++++---- td/telegram/StickersManager.h | 3 +++ td/telegram/Td.cpp | 5 +++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 4 ++++ 6 files changed, 45 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 1fddcc358..ed14f50c1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2583,9 +2583,8 @@ addedReactions total_count:int32 reactions:vector next_offset:str //@description Represents a list of reactions that can be added to a message @reactions List of available reactions @allow_custom_emoji True, if any other custom emoji reaction can be added availableReactions reactions:vector allow_custom_emoji:Bool = AvailableReactions; - -//@description Contains stickers which must be used for emoji reaction animation rendering -//@reaction Text representation of the reaction +//@description Contains information about a emoji reaction +//@emoji Text representation of the reaction //@title Reaction title //@is_active True, if the reaction can be added to new messages and enabled in chats //@static_icon Static icon for the reaction @@ -2595,7 +2594,7 @@ availableReactions reactions:vector allow_custom_emoji:Bool = Avai //@effect_animation Effect animation for the reaction //@around_animation Around animation for the reaction; may be null //@center_animation Center animation for the reaction; may be null -reaction reaction:string title:string is_active:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = Reaction; +emojiReaction emoji:string title:string is_active:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = EmojiReaction; //@description Represents a list of animations @animations List of animations @@ -5164,6 +5163,9 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok; +//@description Returns information about a emoji reaction. Returns a 404 error if the reaction is not found @emoji Text representation of the reaction +getEmojiReaction emoji:string = EmojiReaction; + //@description Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message @@ -6392,7 +6394,7 @@ reportChat chat_id:int53 message_ids:vector reason:ChatReportReason text: reportChatPhoto chat_id:int53 file_id:int32 reason:ChatReportReason text:string = Ok; //@description Reports reactions set on a message to the Telegram moderators. Reactions on a message can be reported only if message.can_report_reactions -//@chat_id Chat identifier @message_id Message identifier @sender_id Identifier of the sender, added the reaction +//@chat_id Chat identifier @message_id Message identifier @sender_id Identifier of the sender, which added the reaction reportMessageReactions chat_id:int53 message_id:int53 sender_id:MessageSender = Ok; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index b50a7ea30..a4c2be352 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1482,12 +1482,27 @@ void StickersManager::init() { td_->option_manager_->set_option_empty("animated_emoji_sticker_set_name"); // legacy } +td_api::object_ptr StickersManager::get_emoji_reaction_object(const string &emoji) { + load_reactions(); + for (auto &reaction : reactions_.reactions_) { + if (reaction.reaction_ == emoji) { + return td_api::make_object( + reaction.reaction_, reaction.title_, reaction.is_active_, get_sticker_object(reaction.static_icon_), + get_sticker_object(reaction.appear_animation_), get_sticker_object(reaction.select_animation_), + get_sticker_object(reaction.activate_animation_), get_sticker_object(reaction.effect_animation_), + get_sticker_object(reaction.around_animation_), get_sticker_object(reaction.center_animation_)); + } + } + return nullptr; +} + void StickersManager::reload_reactions() { if (G()->close_flag() || reactions_.are_being_reloaded_) { return; } CHECK(!td_->auth_manager_->is_bot()); reactions_.are_being_reloaded_ = true; + load_reactions(); // must be after are_being_reloaded_ is set to true to avoid recursion td_->create_handler()->send(reactions_.hash_); } @@ -3687,24 +3702,29 @@ void StickersManager::load_active_reactions() { } void StickersManager::load_reactions() { + if (are_reactions_loaded_from_database_) { + return; + } + are_reactions_loaded_from_database_ = true; + string reactions = G()->td_db()->get_binlog_pmc()->get("reactions"); if (reactions.empty()) { return reload_reactions(); } - auto status = log_event_parse(reactions_, reactions); + auto new_reactions = reactions_; + auto status = log_event_parse(new_reactions, reactions); if (status.is_error()) { LOG(ERROR) << "Can't load available reactions: " << status; - reactions_ = {}; return reload_reactions(); } - for (auto &reaction : reactions_.reactions_) { + for (auto &reaction : new_reactions.reactions_) { if (!reaction.is_valid()) { LOG(ERROR) << "Loaded invalid reaction"; - reactions_ = {}; return reload_reactions(); } } + reactions_ = std::move(new_reactions); LOG(INFO) << "Successfully loaded " << reactions_.reactions_.size() << " available reactions"; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index f9d6e91ae..5e96746bd 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -168,6 +168,8 @@ class StickersManager final : public Actor { void view_featured_sticker_sets(const vector &sticker_set_ids); + td_api::object_ptr get_emoji_reaction_object(const string &emoji); + void reload_reactions(); void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false); @@ -1009,6 +1011,7 @@ class StickersManager final : public Actor { Reactions reactions_; vector active_reactions_; + bool are_reactions_loaded_from_database_ = false; FlatHashMap> emoji_language_codes_; FlatHashMap emoji_language_code_versions_; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b6036c749..e99fdd8eb 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5199,6 +5199,11 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request) CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_); } +void Td::on_request(uint64 id, const td_api::getEmojiReaction &request) { + CHECK_IS_USER(); + send_closure(actor_id(this), &Td::send_result, id, stickers_manager_->get_emoji_reaction_object(request.emoji_)); +} + void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &request) { CHECK_IS_USER(); auto r_reactions = diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 2e39b417f..e1e792a1a 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -656,6 +656,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getChatScheduledMessages &request); + void on_request(uint64 id, const td_api::getEmojiReaction &request); + void on_request(uint64 id, const td_api::getMessageAvailableReactions &request); void on_request(uint64 id, td_api::addMessageReaction &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 9ac3342a5..ea35247b0 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2236,6 +2236,10 @@ class CliClient final : public Actor { string reaction; get_args(args, reaction); send_request(td_api::make_object(as_reaction_type(reaction))); + } else if (op == "ger") { + string emoji; + get_args(args, emoji); + send_request(td_api::make_object(emoji)); } else if (op == "gmar") { ChatId chat_id; MessageId message_id; From de1ed3275f972fab34887307e112ad96a6722488 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 15:44:37 +0300 Subject: [PATCH 138/200] Add td_api::getCustomEmojiReactionAnimations. --- td/generate/scheme/td_api.tl | 6 ++++++ td/telegram/StickersManager.cpp | 30 ++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 5 ++++- td/telegram/Td.cpp | 6 ++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index ed14f50c1..b3bf3a726 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -163,6 +163,9 @@ remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_comp //@remote Information about the remote copy of the file file id:int32 size:int53 expected_size:int53 local:localFile remote:remoteFile = File; +//@description Represents a list of files @files List of files +files files:vector = Files; + //@class InputFile @description Points to a file @@ -5166,6 +5169,9 @@ editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:Messa //@description Returns information about a emoji reaction. Returns a 404 error if the reaction is not found @emoji Text representation of the reaction getEmojiReaction emoji:string = EmojiReaction; +//@description Returns TGS files with generic animations for custom emoji reactions +getCustomEmojiReactionAnimations = Files; + //@description Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index a4c2be352..5c9c02be8 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1678,6 +1678,7 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t return; } if (type == SpecialStickerSetType::generic_animations()) { + set_promises(pending_get_generic_animations_queries_); return; } if (type == SpecialStickerSetType::default_statuses()) { @@ -5500,6 +5501,35 @@ void StickersManager::get_all_animated_emojis(bool is_recursive, promise.set_value(td_api::make_object(std::move(emojis))); } +void StickersManager::get_custom_emoji_reaction_generic_animations( + bool is_recursive, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::generic_animations()); + auto sticker_set = get_sticker_set(special_sticker_set.id_); + if (sticker_set == nullptr || !sticker_set->was_loaded_) { + if (is_recursive) { + return promise.set_value(td_api::make_object()); + } + + pending_get_generic_animations_queries_.push_back(PromiseCreator::lambda( + [actor_id = actor_id(this), promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + send_closure(actor_id, &StickersManager::get_custom_emoji_reaction_generic_animations, true, + std::move(promise)); + } + })); + load_special_sticker_set(special_sticker_set); + return; + } + + auto files = transform(sticker_set->sticker_ids_, + [&](FileId sticker_id) { return td_->file_manager_->get_file_object(sticker_id); }); + promise.set_value(td_api::make_object(std::move(files))); +} + void StickersManager::get_default_emoji_statuses(bool is_recursive, Promise> &&promise) { TRY_STATUS_PROMISE(promise, G()->close_status()); diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 5e96746bd..5751cc15b 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -103,6 +103,9 @@ class StickersManager final : public Actor { void get_all_animated_emojis(bool is_recursive, Promise> &&promise); + void get_custom_emoji_reaction_generic_animations(bool is_recursive, + Promise> &&promise); + void get_default_emoji_statuses(bool is_recursive, Promise> &&promise); bool is_default_emoji_status(int64 custom_emoji_id); @@ -986,7 +989,7 @@ class StickersManager final : public Actor { vector> pending_get_animated_emoji_queries_; vector> pending_get_premium_gift_option_sticker_queries_; - + vector> pending_get_generic_animations_queries_; vector> pending_get_default_statuses_queries_; double next_click_animated_emoji_message_time_ = 0; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e99fdd8eb..b5a9b6f7b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5204,6 +5204,12 @@ void Td::on_request(uint64 id, const td_api::getEmojiReaction &request) { send_closure(actor_id(this), &Td::send_result, id, stickers_manager_->get_emoji_reaction_object(request.emoji_)); } +void Td::on_request(uint64 id, const td_api::getCustomEmojiReactionAnimations &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + stickers_manager_->get_custom_emoji_reaction_generic_animations(false, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &request) { CHECK_IS_USER(); auto r_reactions = diff --git a/td/telegram/Td.h b/td/telegram/Td.h index e1e792a1a..433860e10 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -658,6 +658,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getEmojiReaction &request); + void on_request(uint64 id, const td_api::getCustomEmojiReactionAnimations &request); + void on_request(uint64 id, const td_api::getMessageAvailableReactions &request); void on_request(uint64 id, td_api::addMessageReaction &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ea35247b0..1b9d08200 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2240,6 +2240,8 @@ class CliClient final : public Actor { string emoji; get_args(args, emoji); send_request(td_api::make_object(emoji)); + } else if (op == "gcera") { + send_request(td_api::make_object()); } else if (op == "gmar") { ChatId chat_id; MessageId message_id; From 7b6d0ea6b4c87d34208f7649eccb75f1b28ffa24 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 17:28:58 +0300 Subject: [PATCH 139/200] Load top reactions from server. --- td/telegram/ContactsManager.cpp | 1 + td/telegram/StickersManager.cpp | 91 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 24 +++++++++ td/telegram/StickersManager.hpp | 24 +++++++++ td/telegram/UpdatesManager.cpp | 1 + 5 files changed, 141 insertions(+) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index dbfae900d..c62c5dbae 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -10304,6 +10304,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo if (td_->option_manager_->get_option_boolean("is_premium") != u->is_premium) { td_->option_manager_->set_option_boolean("is_premium", u->is_premium); send_closure(td_->config_manager_, &ConfigManager::request_config, true); + td_->stickers_manager_->reload_top_reactions(); } } if (u->is_name_changed || u->is_username_changed || u->is_is_contact_changed) { diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 5c9c02be8..15497570f 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -21,6 +21,7 @@ #include "td/telegram/LanguagePackManager.h" #include "td/telegram/logevent/LogEvent.h" #include "td/telegram/logevent/LogEventHelper.h" +#include "td/telegram/MessageReaction.h" #include "td/telegram/MessagesManager.h" #include "td/telegram/misc.h" #include "td/telegram/net/DcId.h" @@ -92,6 +93,29 @@ class GetAvailableReactionsQuery final : public Td::ResultHandler { } }; +class GetTopReactionsQuery final : public Td::ResultHandler { + public: + void send(int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::messages_getTopReactions(50, hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetTopReactionsQuery: " << to_string(ptr); + td_->stickers_manager_->on_get_top_reactions(std::move(ptr)); + } + + void on_error(Status status) final { + LOG(INFO) << "Receive error for GetTopReactionsQuery: " << status; + td_->stickers_manager_->on_get_top_reactions(nullptr); + } +}; + class GetAllStickersQuery final : public Td::ResultHandler { StickerType sticker_type_; @@ -1506,6 +1530,16 @@ void StickersManager::reload_reactions() { td_->create_handler()->send(reactions_.hash_); } +void StickersManager::reload_top_reactions() { + if (G()->close_flag() || top_reactions_.is_being_reloaded_) { + return; + } + CHECK(!td_->auth_manager_->is_bot()); + top_reactions_.is_being_reloaded_ = true; + load_top_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion + td_->create_handler()->send(top_reactions_.hash_); +} + StickersManager::SpecialStickerSet &StickersManager::add_special_sticker_set(const SpecialStickerSetType &type) { CHECK(!type.is_empty()); auto &result_ptr = special_sticker_sets_[type]; @@ -3685,6 +3719,11 @@ void StickersManager::save_reactions() { G()->td_db()->get_binlog_pmc()->set("reactions", log_event_store(reactions_).as_slice().str()); } +void StickersManager::save_top_reactions() { + LOG(INFO) << "Save top reactions"; + G()->td_db()->get_binlog_pmc()->set("top_reactions", log_event_store(top_reactions_).as_slice().str()); +} + void StickersManager::load_active_reactions() { string active_reactions = G()->td_db()->get_binlog_pmc()->get("active_reactions"); if (active_reactions.empty()) { @@ -3732,6 +3771,27 @@ void StickersManager::load_reactions() { update_active_reactions(); } +void StickersManager::load_top_reactions() { + if (are_top_reactions_loaded_from_database_) { + return; + } + are_top_reactions_loaded_from_database_ = true; + + string top_reactions = G()->td_db()->get_binlog_pmc()->get("top_reactions"); + if (top_reactions.empty()) { + return reload_top_reactions(); + } + + auto status = log_event_parse(top_reactions_, top_reactions); + if (status.is_error()) { + LOG(ERROR) << "Can't load top reactions: " << status; + top_reactions_ = {}; + return reload_top_reactions(); + } + + LOG(INFO) << "Successfully loaded " << top_reactions_.reactions_.size() << " top reactions"; +} + void StickersManager::update_active_reactions() { vector active_reactions; for (auto &reaction : reactions_.reactions_) { @@ -3810,6 +3870,37 @@ void StickersManager::on_get_available_reactions( update_active_reactions(); } +void StickersManager::on_get_top_reactions(tl_object_ptr &&reactions_ptr) { + CHECK(top_reactions_.is_being_reloaded_); + top_reactions_.is_being_reloaded_ = false; + + if (reactions_ptr == nullptr) { + // failed to get top reactions + return; + } + + int32 constructor_id = reactions_ptr->get_id(); + if (constructor_id == telegram_api::messages_reactionsNotModified::ID) { + LOG(INFO) << "Top reactions are not modified"; + return; + } + + CHECK(constructor_id == telegram_api::messages_reactions::ID); + auto reactions = move_tl_object_as(reactions_ptr); + auto new_reactions = + transform(reactions->reactions_, [](const telegram_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + if (new_reactions == top_reactions_.reactions_ && top_reactions_.hash_ == reactions->hash_) { + LOG(INFO) << "Top reactions are not modified"; + return; + } + top_reactions_.reactions_ = std::move(new_reactions); + top_reactions_.hash_ = reactions->hash_; + + save_top_reactions(); +} + void StickersManager::on_get_installed_sticker_sets(StickerType sticker_type, tl_object_ptr &&stickers_ptr) { auto type = static_cast(sticker_type); diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 5751cc15b..b0fb9c38d 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -175,10 +175,14 @@ class StickersManager final : public Actor { void reload_reactions(); + void reload_top_reactions(); + void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false); void on_get_available_reactions(tl_object_ptr &&available_reactions_ptr); + void on_get_top_reactions(tl_object_ptr &&reactions_ptr); + void on_get_installed_sticker_sets(StickerType sticker_type, tl_object_ptr &&stickers_ptr); @@ -551,6 +555,18 @@ class StickersManager final : public Actor { void parse(ParserT &parser); }; + struct ReactionList { + int64 hash_ = 0; + bool is_being_reloaded_ = false; + vector reactions_; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); + }; + class CustomEmojiLogEvent; class StickerListLogEvent; class StickerSetListLogEvent; @@ -830,10 +846,14 @@ class StickersManager final : public Actor { void save_reactions(); + void save_top_reactions(); + void load_active_reactions(); void load_reactions(); + void load_top_reactions(); + void update_active_reactions(); td_api::object_ptr get_update_active_emoji_reactions_object() const; @@ -1014,7 +1034,11 @@ class StickersManager final : public Actor { Reactions reactions_; vector active_reactions_; + + ReactionList top_reactions_; + bool are_reactions_loaded_from_database_ = false; + bool are_top_reactions_loaded_from_database_ = false; FlatHashMap> emoji_language_codes_; FlatHashMap emoji_language_code_versions_; diff --git a/td/telegram/StickersManager.hpp b/td/telegram/StickersManager.hpp index b425488ff..ababf8bbe 100644 --- a/td/telegram/StickersManager.hpp +++ b/td/telegram/StickersManager.hpp @@ -516,4 +516,28 @@ void StickersManager::Reactions::parse(ParserT &parser) { } } +template +void StickersManager::ReactionList::store(StorerT &storer) const { + bool has_reactions = !reactions_.empty(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_reactions); + END_STORE_FLAGS(); + if (has_reactions) { + td::store(reactions_, storer); + td::store(hash_, storer); + } +} + +template +void StickersManager::ReactionList::parse(ParserT &parser) { + bool has_reactions; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_reactions); + END_PARSE_FLAGS(); + if (has_reactions) { + td::parse(reactions_, parser); + td::parse(hash_, parser); + } +} + } // namespace td diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 98c9f61da..b65cc8db1 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1710,6 +1710,7 @@ void UpdatesManager::try_reload_data() { td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Auto()); td_->stickers_manager_->reload_reactions(); + td_->stickers_manager_->reload_top_reactions(); for (int32 type = 0; type < MAX_STICKER_TYPE; type++) { auto sticker_type = static_cast(type); td_->stickers_manager_->get_installed_sticker_sets(sticker_type, Auto()); From ece581b797570b97009418804f33c3f4514e6de2 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 19:14:02 +0300 Subject: [PATCH 140/200] Load recent reactions. --- td/telegram/StickersManager.cpp | 90 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 10 ++++ td/telegram/UpdatesManager.cpp | 1 + 3 files changed, 101 insertions(+) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 15497570f..5812c106f 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -93,6 +93,29 @@ class GetAvailableReactionsQuery final : public Td::ResultHandler { } }; +class GetRecentReactionsQuery final : public Td::ResultHandler { + public: + void send(int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::messages_getRecentReactions(50, hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetRecentReactionsQuery: " << to_string(ptr); + td_->stickers_manager_->on_get_recent_reactions(std::move(ptr)); + } + + void on_error(Status status) final { + LOG(INFO) << "Receive error for GetRecentReactionsQuery: " << status; + td_->stickers_manager_->on_get_recent_reactions(nullptr); + } +}; + class GetTopReactionsQuery final : public Td::ResultHandler { public: void send(int64 hash) { @@ -1530,6 +1553,16 @@ void StickersManager::reload_reactions() { td_->create_handler()->send(reactions_.hash_); } +void StickersManager::reload_recent_reactions() { + if (G()->close_flag() || recent_reactions_.is_being_reloaded_) { + return; + } + CHECK(!td_->auth_manager_->is_bot()); + recent_reactions_.is_being_reloaded_ = true; + load_recent_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion + td_->create_handler()->send(recent_reactions_.hash_); +} + void StickersManager::reload_top_reactions() { if (G()->close_flag() || top_reactions_.is_being_reloaded_) { return; @@ -3719,6 +3752,11 @@ void StickersManager::save_reactions() { G()->td_db()->get_binlog_pmc()->set("reactions", log_event_store(reactions_).as_slice().str()); } +void StickersManager::save_recent_reactions() { + LOG(INFO) << "Save recent reactions"; + G()->td_db()->get_binlog_pmc()->set("recent_reactions", log_event_store(recent_reactions_).as_slice().str()); +} + void StickersManager::save_top_reactions() { LOG(INFO) << "Save top reactions"; G()->td_db()->get_binlog_pmc()->set("top_reactions", log_event_store(top_reactions_).as_slice().str()); @@ -3771,6 +3809,27 @@ void StickersManager::load_reactions() { update_active_reactions(); } +void StickersManager::load_recent_reactions() { + if (are_recent_reactions_loaded_from_database_) { + return; + } + are_recent_reactions_loaded_from_database_ = true; + + string recent_reactions = G()->td_db()->get_binlog_pmc()->get("recent_reactions"); + if (recent_reactions.empty()) { + return reload_recent_reactions(); + } + + auto status = log_event_parse(recent_reactions_, recent_reactions); + if (status.is_error()) { + LOG(ERROR) << "Can't load recent reactions: " << status; + recent_reactions_ = {}; + return reload_recent_reactions(); + } + + LOG(INFO) << "Successfully loaded " << recent_reactions_.reactions_.size() << " recent reactions"; +} + void StickersManager::load_top_reactions() { if (are_top_reactions_loaded_from_database_) { return; @@ -3870,6 +3929,37 @@ void StickersManager::on_get_available_reactions( update_active_reactions(); } +void StickersManager::on_get_recent_reactions(tl_object_ptr &&reactions_ptr) { + CHECK(recent_reactions_.is_being_reloaded_); + recent_reactions_.is_being_reloaded_ = false; + + if (reactions_ptr == nullptr) { + // failed to get recent reactions + return; + } + + int32 constructor_id = reactions_ptr->get_id(); + if (constructor_id == telegram_api::messages_reactionsNotModified::ID) { + LOG(INFO) << "Top reactions are not modified"; + return; + } + + CHECK(constructor_id == telegram_api::messages_reactions::ID); + auto reactions = move_tl_object_as(reactions_ptr); + auto new_reactions = + transform(reactions->reactions_, [](const telegram_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + if (new_reactions == recent_reactions_.reactions_ && recent_reactions_.hash_ == reactions->hash_) { + LOG(INFO) << "Top reactions are not modified"; + return; + } + recent_reactions_.reactions_ = std::move(new_reactions); + recent_reactions_.hash_ = reactions->hash_; + + save_recent_reactions(); +} + void StickersManager::on_get_top_reactions(tl_object_ptr &&reactions_ptr) { CHECK(top_reactions_.is_being_reloaded_); top_reactions_.is_being_reloaded_ = false; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index b0fb9c38d..faf02a79f 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -175,12 +175,16 @@ class StickersManager final : public Actor { void reload_reactions(); + void reload_recent_reactions(); + void reload_top_reactions(); void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false); void on_get_available_reactions(tl_object_ptr &&available_reactions_ptr); + void on_get_recent_reactions(tl_object_ptr &&reactions_ptr); + void on_get_top_reactions(tl_object_ptr &&reactions_ptr); void on_get_installed_sticker_sets(StickerType sticker_type, @@ -846,12 +850,16 @@ class StickersManager final : public Actor { void save_reactions(); + void save_recent_reactions(); + void save_top_reactions(); void load_active_reactions(); void load_reactions(); + void load_recent_reactions(); + void load_top_reactions(); void update_active_reactions(); @@ -1035,9 +1043,11 @@ class StickersManager final : public Actor { Reactions reactions_; vector active_reactions_; + ReactionList recent_reactions_; ReactionList top_reactions_; bool are_reactions_loaded_from_database_ = false; + bool are_recent_reactions_loaded_from_database_ = false; bool are_top_reactions_loaded_from_database_ = false; FlatHashMap> emoji_language_codes_; diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index b65cc8db1..a691042a1 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1710,6 +1710,7 @@ void UpdatesManager::try_reload_data() { td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Auto()); td_->stickers_manager_->reload_reactions(); + td_->stickers_manager_->reload_recent_reactions(); td_->stickers_manager_->reload_top_reactions(); for (int32 type = 0; type < MAX_STICKER_TYPE; type++) { auto sticker_type = static_cast(type); From f85b79d9bc7aae00eafc097240a25c7224aa702c Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 19:37:45 +0300 Subject: [PATCH 141/200] Add td_api::clearRecentReactions. --- td/generate/scheme/td_api.tl | 5 +++- td/telegram/StickersManager.cpp | 43 +++++++++++++++++++++++++++++++++ td/telegram/StickersManager.h | 2 ++ td/telegram/Td.cpp | 6 +++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b3bf3a726..797ee1779 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5177,6 +5177,9 @@ getCustomEmojiReactionAnimations = Files; //@message_id Identifier of the message getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions; +//@description Clears the list of recently used reactions +clearRecentReactions = Ok; + //@description Adds a reaction to a message. Use getMessageAvailableReactions to receive the list of available reactions for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message @@ -5632,7 +5635,7 @@ getRecentEmojiStatuses = EmojiStatuses; //@description Returns default emoji statuses getDefaultEmojiStatuses = EmojiStatuses; -//@description Clears recent emoji statuses +//@description Clears the list of recently used emoji statuses clearRecentEmojiStatuses = Ok; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 5812c106f..16e8d68db 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -139,6 +139,36 @@ class GetTopReactionsQuery final : public Td::ResultHandler { } }; +class ClearRecentReactionsQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit ClearRecentReactionsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create(telegram_api::messages_clearRecentReactions())); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + td_->stickers_manager_->reload_recent_reactions(); + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + if (!G()->is_expected_error(status)) { + LOG(ERROR) << "Receive error for clear recent reactions: " << status; + } + td_->stickers_manager_->reload_recent_reactions(); + promise_.set_error(std::move(status)); + } +}; + class GetAllStickersQuery final : public Td::ResultHandler { StickerType sticker_type_; @@ -1543,6 +1573,19 @@ td_api::object_ptr StickersManager::get_emoji_reaction_ob return nullptr; } +void StickersManager::clear_recent_reactions(Promise &&promise) { + load_recent_reactions(); + + if (recent_reactions_.reactions_.empty()) { + return promise.set_value(Unit()); + } + + recent_reactions_.hash_ = 0; + recent_reactions_.reactions_.clear(); + + td_->create_handler(std::move(promise))->send(); +} + void StickersManager::reload_reactions() { if (G()->close_flag() || reactions_.are_being_reloaded_) { return; diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index faf02a79f..6a2c1c165 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -173,6 +173,8 @@ class StickersManager final : public Actor { td_api::object_ptr get_emoji_reaction_object(const string &emoji); + void clear_recent_reactions(Promise &&promise); + void reload_reactions(); void reload_recent_reactions(); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b5a9b6f7b..6c0fc3542 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5221,6 +5221,12 @@ void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &reque } } +void Td::on_request(uint64 id, const td_api::clearRecentReactions &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + stickers_manager_->clear_recent_reactions(std::move(promise)); +} + void Td::on_request(uint64 id, td_api::addMessageReaction &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 433860e10..d63ebabda 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -662,6 +662,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getMessageAvailableReactions &request); + void on_request(uint64 id, const td_api::clearRecentReactions &request); + void on_request(uint64 id, td_api::addMessageReaction &request); void on_request(uint64 id, td_api::removeMessageReaction &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 1b9d08200..e5ba1374d 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2247,6 +2247,8 @@ class CliClient final : public Actor { MessageId message_id; get_args(args, chat_id, message_id); send_request(td_api::make_object(chat_id, message_id)); + } else if (op == "crr") { + send_request(td_api::make_object()); } else if (op == "amr" || op == "react") { ChatId chat_id; MessageId message_id; From 164f5e97fd9ae7d4846006b003026ba8c115bffb Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 19:52:08 +0300 Subject: [PATCH 142/200] Support telegram_api::updateRecentReactions. --- td/telegram/UpdatesManager.cpp | 9 +++++---- td/telegram/UpdatesManager.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index a691042a1..4a99e2e82 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -2949,6 +2949,11 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + td_->stickers_manager_->reload_recent_reactions(); + promise.set_value(Unit()); +} + void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { td_->attach_menu_manager_->reload_attach_menu_bots(std::move(promise)); } @@ -3590,8 +3595,4 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { - promise.set_value(Unit()); -} - } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 8535fd6f4..0d2c008a1 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -406,6 +406,8 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); + void on_update(tl_object_ptr update, Promise &&promise); + void on_update(tl_object_ptr update, Promise &&promise); void on_update(tl_object_ptr update, Promise &&promise); @@ -538,8 +540,6 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); // unsupported updates - - void on_update(tl_object_ptr update, Promise &&promise); }; } // namespace td From 999326d56a289e3504bbba7f559d35fd442a2071 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 20:17:14 +0300 Subject: [PATCH 143/200] Locally add reaction to recent. --- td/telegram/MessageReaction.cpp | 4 ++++ td/telegram/MessageReaction.h | 2 ++ td/telegram/MessagesManager.cpp | 4 ++++ td/telegram/StickersManager.cpp | 28 +++++++++++++++++++++++++--- td/telegram/StickersManager.h | 4 ++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 7a790e6c1..e10a5ecc8 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -877,4 +877,8 @@ void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId ch td->create_handler(std::move(promise))->send(dialog_id, message_id, chooser_dialog_id); } +void add_recent_reaction(Td *td, const string &reaction) { + td->stickers_manager_->add_recent_reaction(reaction); +} + } // namespace td diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index dda90a1f6..334ee66be 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -212,4 +212,6 @@ void send_update_default_reaction_type(const string &default_reaction); void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id, Promise &&promise); +void add_recent_reaction(Td *td, const string &reaction); + } // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5a13af7c0..fae45a07c 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24557,6 +24557,10 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string return promise.set_value(Unit()); } + if (add_to_recent) { + add_recent_reaction(td_, reaction); + } + set_message_reactions(d, m, is_big, add_to_recent, std::move(promise)); } diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 16e8d68db..5eec4af01 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -95,8 +95,8 @@ class GetAvailableReactionsQuery final : public Td::ResultHandler { class GetRecentReactionsQuery final : public Td::ResultHandler { public: - void send(int64 hash) { - send_query(G()->net_query_creator().create(telegram_api::messages_getRecentReactions(50, hash))); + void send(int32 limit, int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::messages_getRecentReactions(limit, hash))); } void on_result(BufferSlice packet) final { @@ -1573,6 +1573,28 @@ td_api::object_ptr StickersManager::get_emoji_reaction_ob return nullptr; } +void StickersManager::add_recent_reaction(const string &reaction) { + load_recent_reactions(); + + auto &reactions = recent_reactions_.reactions_; + if (!reactions.empty() && reactions[0] == reaction) { + return; + } + + auto it = std::find(reactions.begin(), reactions.end(), reaction); + if (it == reactions.end()) { + if (static_cast(reactions.size()) == MAX_RECENT_REACTIONS) { + reactions.back() = reaction; + } else { + reactions.push_back(reaction); + } + it = reactions.end() - 1; + } + std::rotate(reactions.begin(), it, it + 1); + + recent_reactions_.hash_ = 0; +} + void StickersManager::clear_recent_reactions(Promise &&promise) { load_recent_reactions(); @@ -1603,7 +1625,7 @@ void StickersManager::reload_recent_reactions() { CHECK(!td_->auth_manager_->is_bot()); recent_reactions_.is_being_reloaded_ = true; load_recent_reactions(); // must be after is_being_reloaded_ is set to true to avoid recursion - td_->create_handler()->send(recent_reactions_.hash_); + td_->create_handler()->send(MAX_RECENT_REACTIONS, recent_reactions_.hash_); } void StickersManager::reload_top_reactions() { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 6a2c1c165..21b022716 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -173,6 +173,8 @@ class StickersManager final : public Actor { td_api::object_ptr get_emoji_reaction_object(const string &emoji); + void add_recent_reaction(const string &reaction); + void clear_recent_reactions(Promise &&promise); void reload_reactions(); @@ -403,6 +405,8 @@ class StickersManager final : public Actor { static constexpr int32 EMOJI_KEYWORDS_UPDATE_DELAY = 3600; static constexpr double MIN_ANIMATED_EMOJI_CLICK_DELAY = 0.2; + static constexpr int32 MAX_RECENT_REACTIONS = 100; // some reasonable value + class Sticker { public: StickerSetId set_id_; From 8e5dccbdb5586e7ab6255f213dd3fd14ce00e1c8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 21:39:23 +0300 Subject: [PATCH 144/200] Fix updating of active reactions in MessagesManager. --- td/telegram/MessagesManager.cpp | 1 + td/telegram/StickersManager.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index fae45a07c..02e9ee001 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8253,6 +8253,7 @@ void MessagesManager::set_active_reactions(vector active_reactions) { return; } + LOG(INFO) << "Set active reactions to " << active_reactions; bool is_changed = active_reactions != active_reactions_; active_reactions_ = std::move(active_reactions); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 5eec4af01..79c58f423 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -3841,6 +3841,9 @@ void StickersManager::load_active_reactions() { } LOG(INFO) << "Successfully loaded " << active_reactions_.size() << " active reactions"; + + td_->messages_manager_->set_active_reactions(vector(active_reactions_)); + send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object()); } From 38fbd00e993d4d513748c41713eb51343c9a53da Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 12 Sep 2022 21:55:30 +0300 Subject: [PATCH 145/200] Add and use get_reactions_hash. --- td/telegram/MessageReaction.cpp | 25 +++++++++++++++++++++++++ td/telegram/MessageReaction.h | 2 ++ td/telegram/StickersManager.cpp | 8 +++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index e10a5ecc8..4b7ed22e7 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -12,6 +12,7 @@ #include "td/telegram/Global.h" #include "td/telegram/MessageSender.h" #include "td/telegram/MessagesManager.h" +#include "td/telegram/misc.h" #include "td/telegram/OptionManager.h" #include "td/telegram/ServerMessageId.h" #include "td/telegram/StickersManager.h" @@ -24,6 +25,8 @@ #include "td/utils/as.h" #include "td/utils/base64.h" #include "td/utils/buffer.h" +#include "td/utils/crypto.h" +#include "td/utils/emoji.h" #include "td/utils/FlatHashSet.h" #include "td/utils/logging.h" #include "td/utils/Status.h" @@ -881,4 +884,26 @@ void add_recent_reaction(Td *td, const string &reaction) { td->stickers_manager_->add_recent_reaction(reaction); } +int64 get_reactions_hash(const vector &reactions) { + vector numbers; + for (auto &reaction : reactions) { + if (is_custom_reaction(reaction)) { + auto custom_emoji_id = static_cast(get_custom_emoji_id(reaction)); + numbers.push_back(custom_emoji_id >> 32); + numbers.push_back(custom_emoji_id & 0xFFFFFFFF); + } else { + auto emoji = remove_emoji_selectors(reaction); + unsigned char hash[16]; + md5(emoji, {hash, sizeof(hash)}); + auto get = [hash](int num) { + return static_cast(hash[num]); + }; + + numbers.push_back(0); + numbers.push_back(static_cast((get(0) << 24) + (get(1) << 16) + (get(2) << 8) + get(3))); + } + } + return get_vector_hash(numbers); +} + } // namespace td diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 334ee66be..45867e7a5 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -214,4 +214,6 @@ void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId ch void add_recent_reaction(Td *td, const string &reaction); +int64 get_reactions_hash(const vector &reactions); + } // namespace td diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 79c58f423..a50ce18dc 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1592,7 +1592,7 @@ void StickersManager::add_recent_reaction(const string &reaction) { } std::rotate(reactions.begin(), it, it + 1); - recent_reactions_.hash_ = 0; + recent_reactions_.hash_ = get_reactions_hash(reactions); } void StickersManager::clear_recent_reactions(Promise &&promise) { @@ -4025,6 +4025,12 @@ void StickersManager::on_get_recent_reactions(tl_object_ptrhash_; + auto expected_hash = get_reactions_hash(recent_reactions_.reactions_); + if (recent_reactions_.hash_ != expected_hash) { + LOG(ERROR) << "Receive hash " << recent_reactions_.hash_ << " instead of " << expected_hash << " for reactions " + << recent_reactions_.reactions_; + } + save_recent_reactions(); } From 5213561096c9a9a20ac0335a30bc6d12bf8a8375 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 13 Sep 2022 15:35:18 +0300 Subject: [PATCH 146/200] Make non-const MessageReaction functions private. --- td/telegram/MessageReaction.cpp | 6 +++--- td/telegram/MessageReaction.h | 32 +++++++++++++++++--------------- td/telegram/MessagesManager.cpp | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 4b7ed22e7..8d128b055 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -559,8 +559,8 @@ unique_ptr MessageReactions::get_message_reactions( if (is_chosen) { chosen_reaction_order.emplace_back(reaction_count->chosen_order_, reaction_str); } - result->reactions_.emplace_back(std::move(reaction_str), reaction_count->count_, is_chosen, - std::move(recent_chooser_dialog_ids), std::move(recent_chooser_min_channels)); + result->reactions_.push_back({std::move(reaction_str), reaction_count->count_, is_chosen, + std::move(recent_chooser_dialog_ids), std::move(recent_chooser_min_channels)}); } if (chosen_reaction_order.size() > 1) { std::sort(chosen_reaction_order.begin(), chosen_reaction_order.end()); @@ -624,7 +624,7 @@ bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogI if (have_recent_choosers) { recent_chooser_dialog_ids.push_back(chooser_dialog_id); } - reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()); + reactions_.push_back({reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto()}); new_chosen_reaction_order.emplace_back(reaction); } else if (!added_reaction->is_chosen()) { added_reaction->set_is_chosen(true, chooser_dialog_id, have_recent_choosers); diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 45867e7a5..f33e60f26 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -36,11 +36,7 @@ class MessageReaction { friend StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &message_reaction); - public: - static constexpr size_t MAX_RECENT_CHOOSERS = 3; - static constexpr int32 MAX_CHOOSE_COUNT = 2147483640; - - MessageReaction() = default; + friend struct MessageReactions; MessageReaction(string reaction, int32 choose_count, bool is_chosen, vector &&recent_chooser_dialog_ids, vector> &&recent_chooser_min_channels) @@ -55,16 +51,28 @@ class MessageReaction { return choose_count_ <= 0; } - const string &get_reaction() const { - return reaction_; - } - bool is_chosen() const { return is_chosen_; } void set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, bool have_recent_choosers); + void add_recent_chooser_dialog_id(DialogId dialog_id); + + bool remove_recent_chooser_dialog_id(DialogId dialog_id); + + void update_recent_chooser_dialog_ids(const MessageReaction &old_reaction); + + public: + static constexpr size_t MAX_RECENT_CHOOSERS = 3; + static constexpr int32 MAX_CHOOSE_COUNT = 2147483640; + + MessageReaction() = default; + + const string &get_reaction() const { + return reaction_; + } + int32 get_choose_count() const { return choose_count_; } @@ -77,12 +85,6 @@ class MessageReaction { return recent_chooser_min_channels_; } - void add_recent_chooser_dialog_id(DialogId dialog_id); - - bool remove_recent_chooser_dialog_id(DialogId dialog_id); - - void update_recent_chooser_dialog_ids(const MessageReaction &old_reaction); - td_api::object_ptr get_message_reaction_object(Td *td) const; template diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 02e9ee001..3ffc74deb 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6736,7 +6736,7 @@ void MessagesManager::on_get_message_reaction_list(FullMessageId full_message_id }; // it's impossible to use received reactions to update message reactions, because there is no way to find, - // which reaction is chosen by the current user, so just reload message reactions for consistency + // which reactions are chosen by the current user, so just reload message reactions for consistency bool need_reload = false; if (reaction.empty()) { // received list and total_count for all reactions From 30b961aebf1f711a58d700e785edbfc8f221bb96 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 13 Sep 2022 19:19:35 +0300 Subject: [PATCH 147/200] Sort reactions returned in getMessageAvailableReactions. --- td/generate/scheme/td_api.tl | 14 +++- td/telegram/ChatReactions.cpp | 6 -- td/telegram/ChatReactions.h | 2 - td/telegram/MessageReaction.cpp | 8 +++ td/telegram/MessageReaction.h | 4 ++ td/telegram/MessagesManager.cpp | 109 +++++++++++++++++++++++++++++--- td/telegram/MessagesManager.h | 6 +- td/telegram/StickersManager.cpp | 10 +++ td/telegram/StickersManager.h | 4 ++ td/telegram/Td.cpp | 6 +- td/telegram/cli.cpp | 2 +- 11 files changed, 145 insertions(+), 26 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 797ee1779..6414fbeb3 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2583,8 +2583,15 @@ addedReaction type:ReactionType sender_id:MessageSender = AddedReaction; //@description Represents a list of reactions added to a message @total_count The total number of found reactions @reactions The list of added reactions @next_offset The offset for the next request. If empty, there are no more results addedReactions total_count:int32 reactions:vector next_offset:string = AddedReactions; -//@description Represents a list of reactions that can be added to a message @reactions List of available reactions @allow_custom_emoji True, if any other custom emoji reaction can be added -availableReactions reactions:vector allow_custom_emoji:Bool = AvailableReactions; +//@description Represents an available reaction @type Type of the reaction @needs_premium True, if Telegram Premium is needed to send the reaction +availableReaction type:ReactionType needs_premium:Bool = AvailableReaction; + +//@description Represents a list of reactions that can be added to a message +//@top_reactions List of reactions to be shown at the top +//@recent_reactions List of recently used reactions +//@popular_reactions List of popular reactions +//@allow_custom_emoji True, if any other custom emoji reaction could be added by Telegram Premium subscribers +availableReactions top_reactions:vector recent_reactions:vector popular_reactions:vector allow_custom_emoji:Bool = AvailableReactions; //@description Contains information about a emoji reaction //@emoji Text representation of the reaction @@ -5175,7 +5182,8 @@ getCustomEmojiReactionAnimations = Files; //@description Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message -getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions; +//@row_size Number of reaction per row, 5-25 +getMessageAvailableReactions chat_id:int53 message_id:int53 row_size:int32 = AvailableReactions; //@description Clears the list of recently used reactions clearRecentReactions = Ok; diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp index a3a6d6b64..93a0c77e1 100644 --- a/td/telegram/ChatReactions.cpp +++ b/td/telegram/ChatReactions.cpp @@ -86,12 +86,6 @@ td_api::object_ptr ChatReactions::get_chat_avail return td_api::make_object(transform(reactions_, get_reaction_type_object)); } -td_api::object_ptr ChatReactions::get_available_reactions_object() const { - CHECK(!allow_all_); - return td_api::make_object(transform(reactions_, get_reaction_type_object), - allow_custom_); -} - telegram_api::object_ptr ChatReactions::get_input_chat_reactions() const { if (allow_all_) { int32 flags = 0; diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h index 9e88f3244..78594fd37 100644 --- a/td/telegram/ChatReactions.h +++ b/td/telegram/ChatReactions.h @@ -41,8 +41,6 @@ struct ChatReactions { td_api::object_ptr get_chat_available_reactions_object() const; - td_api::object_ptr get_available_reactions_object() const; - bool empty() const { return reactions_.empty() && !allow_all_; } diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 8d128b055..8073c4f23 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -880,6 +880,14 @@ void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId ch td->create_handler(std::move(promise))->send(dialog_id, message_id, chooser_dialog_id); } +vector get_recent_reactions(Td *td) { + return td->stickers_manager_->get_recent_reactions(); +} + +vector get_top_reactions(Td *td) { + return td->stickers_manager_->get_top_reactions(); +} + void add_recent_reaction(Td *td, const string &reaction) { td->stickers_manager_->add_recent_reaction(reaction); } diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index f33e60f26..6c30a8a4e 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -214,6 +214,10 @@ void send_update_default_reaction_type(const string &default_reaction); void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id, Promise &&promise); +vector get_recent_reactions(Td *td); + +vector get_top_reactions(Td *td); + void add_recent_reaction(Td *td, const string &reaction); int64 get_reactions_hash(const vector &reactions); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 3ffc74deb..279ab2d84 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24469,7 +24469,12 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id set_promises(promises); } -Result MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { +Result> MessagesManager::get_message_available_reactions( + FullMessageId full_message_id, int32 row_size) { + if (row_size < 5 || row_size > 25) { + row_size = 8; + } + auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "get_message_available_reactions"); if (d == nullptr) { @@ -24480,10 +24485,97 @@ Result MessagesManager::get_message_available_reactions(FullMessa if (m == nullptr) { return Status::Error(400, "Message not found"); } - return get_message_available_reactions(d, m); + + auto available_reactions = get_message_available_reactions(d, m, false); + bool is_premium = td_->option_manager_->get_option_boolean("is_premium"); + bool show_premium = is_premium; + + auto recent_reactions = get_recent_reactions(td_); + auto top_reactions = get_top_reactions(td_); + auto active_reactions = get_message_active_reactions(d, m); + LOG(INFO) << "Have available reactions " << available_reactions << " to be sorted by top reactions " << top_reactions + << " and recent reactions " << recent_reactions; + if (active_reactions.allow_custom_ && active_reactions.allow_all_) { + for (auto &reaction : recent_reactions) { + if (is_custom_reaction(reaction)) { + show_premium = true; + } + } + for (auto &reaction : top_reactions) { + if (is_custom_reaction(reaction)) { + show_premium = true; + } + } + } + + FlatHashSet all_available_reactions; + for (const auto &reaction : available_reactions.reactions_) { + all_available_reactions.insert(reaction); + } + + vector> top_reaction_objects; + vector> recent_reaction_objects; + vector> popular_reaction_objects; + vector> last_reaction_objects; + + auto add_reactions = [&](vector> &reaction_objects, + const vector &reactions) { + for (auto &reaction : reactions) { + if (all_available_reactions.erase(reaction) != 0) { + // add available reaction + reaction_objects.push_back( + td_api::make_object(get_reaction_type_object(reaction), false)); + } else if (is_custom_reaction(reaction) && available_reactions.allow_custom_) { + // add implicitly available custom reaction + reaction_objects.push_back( + td_api::make_object(get_reaction_type_object(reaction), !is_premium)); + } else { + // skip the reaction + } + } + }; + if (show_premium) { + if (top_reactions.size() > 2 * static_cast(row_size)) { + top_reactions.resize(2 * static_cast(row_size)); + } + add_reactions(top_reaction_objects, top_reactions); + + if (!recent_reactions.empty()) { + add_reactions(recent_reaction_objects, recent_reactions); + } + } else { + add_reactions(top_reaction_objects, top_reactions); + } + add_reactions(last_reaction_objects, active_reactions_); + add_reactions(last_reaction_objects, available_reactions.reactions_); + + if (show_premium) { + if (recent_reactions.empty()) { + popular_reaction_objects = std::move(last_reaction_objects); + } else { + auto max_objects = 10 * static_cast(row_size); + if (recent_reaction_objects.size() + last_reaction_objects.size() > max_objects) { + if (last_reaction_objects.size() < max_objects) { + recent_reaction_objects.resize(max_objects - last_reaction_objects.size()); + } else { + recent_reaction_objects.clear(); + } + } + append(recent_reaction_objects, std::move(last_reaction_objects)); + } + } else { + append(top_reaction_objects, std::move(last_reaction_objects)); + } + + CHECK(all_available_reactions.empty()); + + return td_api::make_object( + std::move(top_reaction_objects), std::move(recent_reaction_objects), std::move(popular_reaction_objects), + available_reactions.allow_custom_); } -ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m) { +ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m, + bool dissalow_custom_for_non_premium) { CHECK(d != nullptr); CHECK(m != nullptr); auto active_reactions = get_message_active_reactions(d, m); @@ -24517,14 +24609,13 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, for (const auto &reaction : m->reactions->reactions_) { // an already used reaction can be added if it is an active reaction const string &reaction_str = reaction.get_reaction(); - if (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_)) { - if (!td::contains(active_reactions.reactions_, reaction_str)) { - active_reactions.reactions_.push_back(reaction_str); - } + if (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_) && + !td::contains(active_reactions.reactions_, reaction_str)) { + active_reactions.reactions_.push_back(reaction_str); } } } - if (!td_->option_manager_->get_option_boolean("is_premium")) { + if (dissalow_custom_for_non_premium && !td_->option_manager_->get_option_boolean("is_premium")) { active_reactions.allow_custom_ = false; } return active_reactions; @@ -24543,7 +24634,7 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string return promise.set_error(Status::Error(400, "Message not found")); } - if (!get_message_available_reactions(d, m).is_allowed_reaction(reaction)) { + if (!get_message_available_reactions(d, m, true).is_allowed_reaction(reaction)) { return promise.set_error(Status::Error(400, "The reaction isn't available for the message")); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 24da0586f..98ab7117c 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -805,7 +805,8 @@ class MessagesManager final : public Actor { vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); - Result get_message_available_reactions(FullMessageId full_message_id); + Result> get_message_available_reactions(FullMessageId full_message_id, + int32 row_size); void add_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent, Promise &&promise); @@ -2689,7 +2690,8 @@ class MessagesManager final : public Actor { bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message); - ChatReactions get_message_available_reactions(const Dialog *d, const Message *m); + ChatReactions get_message_available_reactions(const Dialog *d, const Message *m, + bool dissalow_custom_for_non_premium); void set_message_reactions(Dialog *d, Message *m, bool is_big, bool add_to_recent, Promise &&promise); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index a50ce18dc..adb7954b3 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1573,6 +1573,16 @@ td_api::object_ptr StickersManager::get_emoji_reaction_ob return nullptr; } +vector StickersManager::get_recent_reactions() { + load_recent_reactions(); + return recent_reactions_.reactions_; +} + +vector StickersManager::get_top_reactions() { + load_top_reactions(); + return top_reactions_.reactions_; +} + void StickersManager::add_recent_reaction(const string &reaction) { load_recent_reactions(); diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 21b022716..43a5a3e2a 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -173,6 +173,10 @@ class StickersManager final : public Actor { td_api::object_ptr get_emoji_reaction_object(const string &emoji); + vector get_recent_reactions(); + + vector get_top_reactions(); + void add_recent_reaction(const string &reaction); void clear_recent_reactions(Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 6c0fc3542..9bb8a2649 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5212,12 +5212,12 @@ void Td::on_request(uint64 id, const td_api::getCustomEmojiReactionAnimations &r void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &request) { CHECK_IS_USER(); - auto r_reactions = - messages_manager_->get_message_available_reactions({DialogId(request.chat_id_), MessageId(request.message_id_)}); + auto r_reactions = messages_manager_->get_message_available_reactions( + {DialogId(request.chat_id_), MessageId(request.message_id_)}, request.row_size_); if (r_reactions.is_error()) { send_closure(actor_id(this), &Td::send_error, id, r_reactions.move_as_error()); } else { - send_closure(actor_id(this), &Td::send_result, id, r_reactions.ok().get_available_reactions_object()); + send_closure(actor_id(this), &Td::send_result, id, r_reactions.move_as_ok()); } } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e5ba1374d..ec4fb0c6b 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2246,7 +2246,7 @@ class CliClient final : public Actor { ChatId chat_id; MessageId message_id; get_args(args, chat_id, message_id); - send_request(td_api::make_object(chat_id, message_id)); + send_request(td_api::make_object(chat_id, message_id, 8)); } else if (op == "crr") { send_request(td_api::make_object()); } else if (op == "amr" || op == "react") { From 124b0dee6ceb2cad723cae9645edefad3729f35c Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 13 Sep 2022 19:39:35 +0300 Subject: [PATCH 148/200] Ensure that custom reactions aren't added twice. --- td/telegram/MessagesManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 279ab2d84..b8cf9e6d5 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24518,14 +24518,19 @@ Result> MessagesManager::get_mess vector> popular_reaction_objects; vector> last_reaction_objects; + FlatHashSet added_custom_reactions; auto add_reactions = [&](vector> &reaction_objects, const vector &reactions) { for (auto &reaction : reactions) { if (all_available_reactions.erase(reaction) != 0) { // add available reaction + if (is_custom_reaction(reaction)) { + added_custom_reactions.insert(reaction); + } reaction_objects.push_back( td_api::make_object(get_reaction_type_object(reaction), false)); - } else if (is_custom_reaction(reaction) && available_reactions.allow_custom_) { + } else if (is_custom_reaction(reaction) && available_reactions.allow_custom_ && + added_custom_reactions.insert(reaction).second) { // add implicitly available custom reaction reaction_objects.push_back( td_api::make_object(get_reaction_type_object(reaction), !is_premium)); From 03db53281cd724480151ef7d4f516ccd082fe71a Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 14:10:33 +0300 Subject: [PATCH 149/200] Remove this_thread::yield for TD_THREAD_UNSUPPORTED. --- tdutils/td/utils/port/thread.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/tdutils/td/utils/port/thread.h b/tdutils/td/utils/port/thread.h index e1b7b167f..35053a32f 100644 --- a/tdutils/td/utils/port/thread.h +++ b/tdutils/td/utils/port/thread.h @@ -22,9 +22,6 @@ namespace td { using thread = detail::ThreadStl; namespace this_thread = detail::this_thread_stl; #elif TD_THREAD_UNSUPPORTED - namespace this_thread { - inline void yield() {} - } #else #error "Thread's implementation is not defined" #endif From 273ae92a14061946616f4ba891d03c25ecbc4681 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 14:18:42 +0300 Subject: [PATCH 150/200] Use HANDLE as thread id on Windows. --- tdutils/td/utils/port/detail/ThreadStl.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadStl.h b/tdutils/td/utils/port/detail/ThreadStl.h index 474ef6ecc..a15dd6bda 100644 --- a/tdutils/td/utils/port/detail/ThreadStl.h +++ b/tdutils/td/utils/port/detail/ThreadStl.h @@ -65,7 +65,11 @@ class ThreadStl { return std::thread::hardware_concurrency(); } +#if TD_WINDOWS + using id = HANDLE; +#else using id = std::thread::id; +#endif static void send_real_time_signal(id thread_id, int real_time_signal_number) { // not supported @@ -81,7 +85,13 @@ class ThreadStl { }; namespace this_thread_stl { +#if TD_WINDOWS +inline ThreadStl::id get_id() { + return GetCurrentThread(); +} +#else using std::this_thread::get_id; +#endif } // namespace this_thread_stl } // namespace detail From 5f98548e02a83bd4b6bf184d7b451d3387ba76fb Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 14:19:09 +0300 Subject: [PATCH 151/200] Use STL thread only on Windows. --- tdutils/td/utils/port/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tdutils/td/utils/port/config.h b/tdutils/td/utils/port/config.h index bd3a1593d..59fd94bf0 100644 --- a/tdutils/td/utils/port/config.h +++ b/tdutils/td/utils/port/config.h @@ -46,10 +46,10 @@ #if TD_EMSCRIPTEN #define TD_THREAD_UNSUPPORTED 1 -#elif TD_TIZEN || TD_LINUX || TD_DARWIN - #define TD_THREAD_PTHREAD 1 -#else +#elif TD_WINDOWS #define TD_THREAD_STL 1 +#else + #define TD_THREAD_PTHREAD 1 #endif #if TD_LINUX From 0eddd8d4058a6420ea41b21f27dede4717e3d56f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 14:38:14 +0300 Subject: [PATCH 152/200] Add thread::set_affinity_mask/get_affinity_mask. --- .../td/utils/port/detail/ThreadPthread.cpp | 8 +++++ tdutils/td/utils/port/detail/ThreadPthread.h | 5 ++++ tdutils/td/utils/port/detail/ThreadStl.h | 30 +++++++++++++++++++ tdutils/test/port.cpp | 27 +++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index 64ea20dc0..91bbf8ca7 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -94,6 +94,14 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at return pthread_create(thread, attr, start_routine, arg); } +Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { + return Status::Error("Unsupported"); +} + +uint64 ThreadPthread::get_affinity_mask(id thread_id) { + return 0; +} + namespace this_thread_pthread { ThreadPthread::id get_id() { return pthread_self(); diff --git a/tdutils/td/utils/port/detail/ThreadPthread.h b/tdutils/td/utils/port/detail/ThreadPthread.h index ff54633c6..a0f15d1a5 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.h +++ b/tdutils/td/utils/port/detail/ThreadPthread.h @@ -17,6 +17,7 @@ #include "td/utils/port/detail/ThreadIdGuard.h" #include "td/utils/port/thread_local.h" #include "td/utils/Slice.h" +#include "td/utils/Status.h" #include #include @@ -66,6 +67,10 @@ class ThreadPthread { static void send_real_time_signal(id thread_id, int real_time_signal_number); + static Status set_affinity_mask(id thread_id, uint64 mask); + + static uint64 get_affinity_mask(id thread_id); + private: MovableValue is_inited_; pthread_t thread_; diff --git a/tdutils/td/utils/port/detail/ThreadStl.h b/tdutils/td/utils/port/detail/ThreadStl.h index a15dd6bda..ce6ac27fe 100644 --- a/tdutils/td/utils/port/detail/ThreadStl.h +++ b/tdutils/td/utils/port/detail/ThreadStl.h @@ -15,6 +15,7 @@ #include "td/utils/port/detail/ThreadIdGuard.h" #include "td/utils/port/thread_local.h" #include "td/utils/Slice.h" +#include "td/utils/Status.h" #include #include @@ -75,6 +76,35 @@ class ThreadStl { // not supported } + static Status set_affinity_mask(id thread_id, uint64 mask) { +#if TD_WINDOWS + if (static_cast(mask) != mask) { + return Status::Error("Invalid thread affinity mask specified"); + } + if (SetThreadAffinityMask(thread_id, static_cast(mask))) { + return Status::OK(); + } + return OS_ERROR("Failed to set thread affinity mask"); +#else + return Status::Error("Unsupported"); +#endif + } + + static uint64 get_affinity_mask(id thread_id) { +#if TD_WINDOWS + DWORD_PTR process_mask = 0; + DWORD_PTR system_mask = 0; + if (GetProcessAffinityMask(GetCurrentProcess(), &process_mask, &system_mask)) { + auto result = SetThreadAffinityMask(thread_id, process_mask); + if (result != 0 && result != process_mask) { + SetThreadAffinityMask(thread_id, result); + } + return result; + } +#endif + return 0; + } + private: std::thread thread_; diff --git a/tdutils/test/port.cpp b/tdutils/test/port.cpp index a7c673e18..79a41596c 100644 --- a/tdutils/test/port.cpp +++ b/tdutils/test/port.cpp @@ -284,3 +284,30 @@ TEST(Port, EventFdAndSignals) { } #endif #endif + +#if !TD_THREAD_UNSUPPORTED +TEST(Port, ThreadAffinityMask) { + auto thread_id = td::this_thread::get_id(); + auto old_mask = td::thread::get_affinity_mask(thread_id); + LOG(INFO) << "Initial thread affinity mask: " << old_mask; + for (size_t i = 0; i < 64; i++) { + auto mask = td::thread::get_affinity_mask(thread_id); + LOG(INFO) << mask; + auto result = td::thread::set_affinity_mask(thread_id, static_cast(1) << i); + LOG(INFO) << i << ": " << result; + mask = td::thread::get_affinity_mask(thread_id); + LOG(INFO) << mask; + + if (i <= 1) { + td::thread thread([] { + auto mask = td::thread::get_affinity_mask(td::this_thread::get_id()); + LOG(INFO) << "New thread affinity mask: " << mask; + }); + } + } + auto result = td::thread::set_affinity_mask(thread_id, old_mask); + LOG(INFO) << result; + old_mask = td::thread::get_affinity_mask(thread_id); + LOG(INFO) << old_mask; +} +#endif From 70e3586626f8fe3edb878eb94b36abb1dafdf0cb Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 14:49:48 +0300 Subject: [PATCH 153/200] Allow to specify affinity mask for concurrent scheduler threads. --- benchmark/bench_http_server.cpp | 2 +- benchmark/bench_http_server_cheat.cpp | 2 +- benchmark/bench_http_server_fast.cpp | 2 +- td/telegram/Client.cpp | 4 ++-- tdactor/example/example.cpp | 2 +- tdactor/td/actor/ConcurrentScheduler.cpp | 22 +++++++++++++--------- tdactor/td/actor/ConcurrentScheduler.h | 3 ++- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/benchmark/bench_http_server.cpp b/benchmark/bench_http_server.cpp index ded5cfa81..7ce892a48 100644 --- a/benchmark/bench_http_server.cpp +++ b/benchmark/bench_http_server.cpp @@ -75,7 +75,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); auto scheduler = td::make_unique(); - scheduler->init(N); + scheduler->init(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/benchmark/bench_http_server_cheat.cpp b/benchmark/bench_http_server_cheat.cpp index fe145f326..8661ba4c1 100644 --- a/benchmark/bench_http_server_cheat.cpp +++ b/benchmark/bench_http_server_cheat.cpp @@ -122,7 +122,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); auto scheduler = td::make_unique(); - scheduler->init(N); + scheduler->init(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/benchmark/bench_http_server_fast.cpp b/benchmark/bench_http_server_fast.cpp index d46273cab..1c272d96b 100644 --- a/benchmark/bench_http_server_fast.cpp +++ b/benchmark/bench_http_server_fast.cpp @@ -107,7 +107,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); auto scheduler = td::make_unique(); - scheduler->init(N); + scheduler->init(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/td/telegram/Client.cpp b/td/telegram/Client.cpp index 101f54c23..00003d933 100644 --- a/td/telegram/Client.cpp +++ b/td/telegram/Client.cpp @@ -99,7 +99,7 @@ class ClientManager::Impl final { CHECK(options_.net_query_stats == nullptr); options_.net_query_stats = std::make_shared(); concurrent_scheduler_ = make_unique(); - concurrent_scheduler_->init(0); + concurrent_scheduler_->init(0, 0); concurrent_scheduler_->start(); } tds_[client_id] = @@ -355,7 +355,7 @@ class MultiImpl { explicit MultiImpl(std::shared_ptr net_query_stats) { concurrent_scheduler_ = std::make_shared(); - concurrent_scheduler_->init(ADDITIONAL_THREAD_COUNT); + concurrent_scheduler_->init(ADDITIONAL_THREAD_COUNT, 0); concurrent_scheduler_->start(); { diff --git a/tdactor/example/example.cpp b/tdactor/example/example.cpp index ef85aad6b..fb5ea6507 100644 --- a/tdactor/example/example.cpp +++ b/tdactor/example/example.cpp @@ -37,7 +37,7 @@ class MainActor final : public td::Actor { int main() { td::ConcurrentScheduler scheduler; - scheduler.init(4 /*threads_count*/); + scheduler.init(4 /*thread_count*/, 0); scheduler.start(); { auto guard = scheduler.get_main_guard(); diff --git a/tdactor/td/actor/ConcurrentScheduler.cpp b/tdactor/td/actor/ConcurrentScheduler.cpp index f944eb459..eb4557452 100644 --- a/tdactor/td/actor/ConcurrentScheduler.cpp +++ b/tdactor/td/actor/ConcurrentScheduler.cpp @@ -15,18 +15,19 @@ namespace td { -void ConcurrentScheduler::init(int32 threads_n) { +void ConcurrentScheduler::init(int32 additional_thread_count, uint64 thread_affinity_mask) { #if TD_THREAD_UNSUPPORTED || TD_EVENTFD_UNSUPPORTED - threads_n = 0; + additional_thread_count = 0; #endif - threads_n++; - std::vector>> outbound(threads_n); + additional_thread_count++; + std::vector>> outbound(additional_thread_count); #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED - for (int32 i = 0; i < threads_n; i++) { + for (int32 i = 0; i < additional_thread_count; i++) { auto queue = std::make_shared>(); queue->init(); outbound[i] = queue; } + thread_affinity_mask_ = thread_affinity_mask; #endif // +1 for extra scheduler for IOCP and send_closure from unrelated threads @@ -37,13 +38,13 @@ void ConcurrentScheduler::init(int32 threads_n) { extra_scheduler_ = 0; #endif - schedulers_.resize(threads_n + extra_scheduler_); - for (int32 i = 0; i < threads_n + extra_scheduler_; i++) { + schedulers_.resize(additional_thread_count + extra_scheduler_); + for (int32 i = 0; i < additional_thread_count + extra_scheduler_; i++) { auto &sched = schedulers_[i]; sched = make_unique(); #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED - if (i >= threads_n) { + if (i >= additional_thread_count) { auto queue = std::make_shared>(); queue->init(); outbound.push_back(std::move(queue)); @@ -75,10 +76,13 @@ void ConcurrentScheduler::start() { #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED for (size_t i = 1; i + extra_scheduler_ < schedulers_.size(); i++) { auto &sched = schedulers_[i]; - threads_.push_back(td::thread([&] { + threads_.push_back(td::thread([&, thread_affinity_mask = thread_affinity_mask_] { #if TD_PORT_WINDOWS detail::Iocp::Guard iocp_guard(iocp_.get()); #endif + if (thread_affinity_mask != 0) { + thread::set_affinity_mask(this_thread::get_id(), thread_affinity_mask); + } while (!is_finished()) { sched->run(Timestamp::in(10)); } diff --git a/tdactor/td/actor/ConcurrentScheduler.h b/tdactor/td/actor/ConcurrentScheduler.h index 0cf8c9a2c..f833848d2 100644 --- a/tdactor/td/actor/ConcurrentScheduler.h +++ b/tdactor/td/actor/ConcurrentScheduler.h @@ -26,7 +26,7 @@ namespace td { class ConcurrentScheduler final : private Scheduler::Callback { public: - void init(int32 threads_n); + void init(int32 additional_thread_count, uint64 thread_affinity_mask = 0); void finish_async() { schedulers_[0]->finish(); @@ -90,6 +90,7 @@ class ConcurrentScheduler final : private Scheduler::Callback { std::atomic is_finished_{false}; #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED vector threads_; + uint64 thread_affinity_mask_ = 0; #endif #if TD_PORT_WINDOWS unique_ptr iocp_; From 1ac2dfef30d53183ade197fdac26e05720214a39 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 15:06:52 +0300 Subject: [PATCH 154/200] Replace ConcurrentScheduler::init with constructor. --- benchmark/bench_actor.cpp | 9 +++---- benchmark/bench_db.cpp | 6 ++--- benchmark/bench_http.cpp | 3 +-- benchmark/bench_http_server.cpp | 3 +-- benchmark/bench_http_server_cheat.cpp | 3 +-- benchmark/bench_http_server_fast.cpp | 3 +-- benchmark/bench_tddb.cpp | 3 +-- benchmark/wget.cpp | 3 +-- td/telegram/Client.cpp | 7 +++--- td/telegram/cli.cpp | 3 +-- tdactor/example/example.cpp | 3 +-- tdactor/td/actor/ConcurrentScheduler.cpp | 2 +- tdactor/td/actor/ConcurrentScheduler.h | 2 +- tdactor/test/actors_bugs.cpp | 8 ++----- tdactor/test/actors_main.cpp | 15 ++++-------- tdactor/test/actors_simple.cpp | 30 ++++++++---------------- tdactor/test/actors_workers.cpp | 3 +-- test/db.cpp | 3 +-- test/mtproto.cpp | 21 ++++++----------- test/online.cpp | 3 +-- test/secret.cpp | 4 +--- test/tdclient.cpp | 3 +-- 22 files changed, 47 insertions(+), 93 deletions(-) diff --git a/benchmark/bench_actor.cpp b/benchmark/bench_actor.cpp index b3a04f592..afe94ca3c 100644 --- a/benchmark/bench_actor.cpp +++ b/benchmark/bench_actor.cpp @@ -46,10 +46,9 @@ class ActorTraits { } // namespace td class CreateActorBench final : public td::Benchmark { - td::ConcurrentScheduler scheduler_; + td::ConcurrentScheduler scheduler_{0, 0}; void start_up() final { - scheduler_.init(0); scheduler_.start(); } @@ -140,8 +139,7 @@ class RingBench final : public td::Benchmark { } void start_up() final { - scheduler_ = new td::ConcurrentScheduler(); - scheduler_->init(thread_n_); + scheduler_ = new td::ConcurrentScheduler(thread_n_, 0); actor_array_ = td::vector>(actor_n_); for (int i = 0; i < actor_n_; i++) { @@ -293,8 +291,7 @@ class QueryBench final : public td::Benchmark { }; void start_up() final { - scheduler_ = new td::ConcurrentScheduler(); - scheduler_->init(0); + scheduler_ = new td::ConcurrentScheduler(0, 0); server_ = scheduler_->create_actor_unsafe(0, "Server"); scheduler_->start(); diff --git a/benchmark/bench_db.cpp b/benchmark/bench_db.cpp index b257951c5..822a91593 100644 --- a/benchmark/bench_db.cpp +++ b/benchmark/bench_db.cpp @@ -29,7 +29,7 @@ template class TdKvBench final : public td::Benchmark { - td::ConcurrentScheduler sched; + td::ConcurrentScheduler sched{1, 0}; td::string name_; public: @@ -72,7 +72,6 @@ class TdKvBench final : public td::Benchmark { }; void start_up_n(int n) final { - sched.init(1); sched.create_actor_unsafe
(1, "Main", n).release(); } @@ -179,8 +178,7 @@ class SqliteKeyValueAsyncBench final : public td::Benchmark { td::unique_ptr sqlite_kv_async_; td::Status do_start_up() { - scheduler_ = td::make_unique(); - scheduler_->init(1); + scheduler_ = td::make_unique(1, 0); auto guard = scheduler_->get_main_guard(); diff --git a/benchmark/bench_http.cpp b/benchmark/bench_http.cpp index fe90d32a2..70fdb909c 100644 --- a/benchmark/bench_http.cpp +++ b/benchmark/bench_http.cpp @@ -66,8 +66,7 @@ class HttpClient final : public td::HttpOutboundConnection::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - auto scheduler = td::make_unique(); - scheduler->init(0); + auto scheduler = td::make_unique(0, 0); scheduler->create_actor_unsafe(0, "Client1").release(); scheduler->create_actor_unsafe(0, "Client2").release(); scheduler->start(); diff --git a/benchmark/bench_http_server.cpp b/benchmark/bench_http_server.cpp index 7ce892a48..33cde9ef8 100644 --- a/benchmark/bench_http_server.cpp +++ b/benchmark/bench_http_server.cpp @@ -74,8 +74,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - auto scheduler = td::make_unique(); - scheduler->init(N, 0); + auto scheduler = td::make_unique(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/benchmark/bench_http_server_cheat.cpp b/benchmark/bench_http_server_cheat.cpp index 8661ba4c1..8bbd768b4 100644 --- a/benchmark/bench_http_server_cheat.cpp +++ b/benchmark/bench_http_server_cheat.cpp @@ -121,8 +121,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - auto scheduler = td::make_unique(); - scheduler->init(N, 0); + auto scheduler = td::make_unique(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/benchmark/bench_http_server_fast.cpp b/benchmark/bench_http_server_fast.cpp index 1c272d96b..4b140422f 100644 --- a/benchmark/bench_http_server_fast.cpp +++ b/benchmark/bench_http_server_fast.cpp @@ -106,8 +106,7 @@ class Server final : public td::TcpListener::Callback { int main() { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - auto scheduler = td::make_unique(); - scheduler->init(N, 0); + auto scheduler = td::make_unique(N, 0); scheduler->create_actor_unsafe(0, "Server").release(); scheduler->start(); while (scheduler->run_main(10)) { diff --git a/benchmark/bench_tddb.cpp b/benchmark/bench_tddb.cpp index eb6880359..b41033c6e 100644 --- a/benchmark/bench_tddb.cpp +++ b/benchmark/bench_tddb.cpp @@ -87,8 +87,7 @@ class MessagesDbBench final : public td::Benchmark { std::shared_ptr messages_db_async_; td::Status do_start_up() { - scheduler_ = td::make_unique(); - scheduler_->init(1); + scheduler_ = td::make_unique(1, 0); auto guard = scheduler_->get_main_guard(); diff --git a/benchmark/wget.cpp b/benchmark/wget.cpp index 1fdfc2af1..5145f317f 100644 --- a/benchmark/wget.cpp +++ b/benchmark/wget.cpp @@ -23,8 +23,7 @@ int main(int argc, char *argv[]) { auto timeout = 10; auto ttl = 3; auto prefer_ipv6 = (argc > 2 && td::string(argv[2]) == "-6"); - auto scheduler = td::make_unique(); - scheduler->init(0); + auto scheduler = td::make_unique(0, 0); scheduler ->create_actor_unsafe(0, "Client", td::PromiseCreator::lambda([](td::Result> res) { diff --git a/td/telegram/Client.cpp b/td/telegram/Client.cpp index 00003d933..f9fcb5894 100644 --- a/td/telegram/Client.cpp +++ b/td/telegram/Client.cpp @@ -98,8 +98,7 @@ class ClientManager::Impl final { CHECK(concurrent_scheduler_ == nullptr); CHECK(options_.net_query_stats == nullptr); options_.net_query_stats = std::make_shared(); - concurrent_scheduler_ = make_unique(); - concurrent_scheduler_->init(0, 0); + concurrent_scheduler_ = make_unique(0, 0); concurrent_scheduler_->start(); } tds_[client_id] = @@ -354,8 +353,7 @@ class MultiImpl { static constexpr int32 ADDITIONAL_THREAD_COUNT = 3; explicit MultiImpl(std::shared_ptr net_query_stats) { - concurrent_scheduler_ = std::make_shared(); - concurrent_scheduler_->init(ADDITIONAL_THREAD_COUNT, 0); + concurrent_scheduler_ = std::make_shared(ADDITIONAL_THREAD_COUNT, 0); concurrent_scheduler_->start(); { @@ -423,6 +421,7 @@ class MultiImpl { static std::atomic current_id_; }; +constexpr int32 MultiImpl::ADDITIONAL_THREAD_COUNT; std::atomic MultiImpl::current_id_{1}; class MultiImplPool { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ec4fb0c6b..5c622950a 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -5257,8 +5257,7 @@ void main(int argc, char **argv) { } { - ConcurrentScheduler scheduler; - scheduler.init(3); + ConcurrentScheduler scheduler(3, 0); class CreateClient final : public Actor { public: diff --git a/tdactor/example/example.cpp b/tdactor/example/example.cpp index fb5ea6507..8f182d835 100644 --- a/tdactor/example/example.cpp +++ b/tdactor/example/example.cpp @@ -36,8 +36,7 @@ class MainActor final : public td::Actor { }; int main() { - td::ConcurrentScheduler scheduler; - scheduler.init(4 /*thread_count*/, 0); + td::ConcurrentScheduler scheduler(4 /*thread_count*/, 0); scheduler.start(); { auto guard = scheduler.get_main_guard(); diff --git a/tdactor/td/actor/ConcurrentScheduler.cpp b/tdactor/td/actor/ConcurrentScheduler.cpp index eb4557452..f5ffe10a2 100644 --- a/tdactor/td/actor/ConcurrentScheduler.cpp +++ b/tdactor/td/actor/ConcurrentScheduler.cpp @@ -15,7 +15,7 @@ namespace td { -void ConcurrentScheduler::init(int32 additional_thread_count, uint64 thread_affinity_mask) { +ConcurrentScheduler::ConcurrentScheduler(int32 additional_thread_count, uint64 thread_affinity_mask) { #if TD_THREAD_UNSUPPORTED || TD_EVENTFD_UNSUPPORTED additional_thread_count = 0; #endif diff --git a/tdactor/td/actor/ConcurrentScheduler.h b/tdactor/td/actor/ConcurrentScheduler.h index f833848d2..490deb218 100644 --- a/tdactor/td/actor/ConcurrentScheduler.h +++ b/tdactor/td/actor/ConcurrentScheduler.h @@ -26,7 +26,7 @@ namespace td { class ConcurrentScheduler final : private Scheduler::Callback { public: - void init(int32 additional_thread_count, uint64 thread_affinity_mask = 0); + explicit ConcurrentScheduler(int32 additional_thread_count, uint64 thread_affinity_mask = 0); void finish_async() { schedulers_[0]->finish(); diff --git a/tdactor/test/actors_bugs.cpp b/tdactor/test/actors_bugs.cpp index 9f3841430..0720f0ed6 100644 --- a/tdactor/test/actors_bugs.cpp +++ b/tdactor/test/actors_bugs.cpp @@ -14,9 +14,7 @@ #include "td/utils/tests.h" TEST(MultiTimeout, bug) { - td::ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(0, 0); sched.start(); td::unique_ptr multi_timeout; @@ -91,9 +89,7 @@ class TimeoutManager final : public td::Actor { td::int32 TimeoutManager::count; TEST(MultiTimeout, Destroy) { - td::ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(0, 0); auto timeout_manager = sched.create_actor_unsafe(0, "TimeoutManager"); TimeoutManager *manager = timeout_manager.get().get_actor_unsafe(); diff --git a/tdactor/test/actors_main.cpp b/tdactor/test/actors_main.cpp index 4bb9ac54b..628b74a94 100644 --- a/tdactor/test/actors_main.cpp +++ b/tdactor/test/actors_main.cpp @@ -394,9 +394,8 @@ class SendToDead final : public td::Actor { TEST(Actors, send_to_dead) { //TODO: fix CHECK(storage_count_.load() == 0) return; - td::ConcurrentScheduler sched; int threads_n = 5; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe(0, "SendToDead").release(); sched.start(); @@ -407,9 +406,8 @@ TEST(Actors, send_to_dead) { } TEST(Actors, main_simple) { - td::ConcurrentScheduler sched; int threads_n = 3; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe(threads_n > 1 ? 1 : 0, "simple", threads_n).release(); sched.start(); @@ -420,9 +418,8 @@ TEST(Actors, main_simple) { } TEST(Actors, main) { - td::ConcurrentScheduler sched; int threads_n = 9; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe(threads_n > 1 ? 1 : 0, "MainQuery", threads_n).release(); sched.start(); @@ -446,9 +443,8 @@ class DoAfterStop final : public td::Actor { }; TEST(Actors, do_after_stop) { - td::ConcurrentScheduler sched; int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe(0, "DoAfterStop").release(); sched.start(); @@ -492,9 +488,8 @@ static void check_context() { } TEST(Actors, context_during_destruction) { - td::ConcurrentScheduler sched; int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); { auto guard = sched.get_main_guard(); diff --git a/tdactor/test/actors_simple.cpp b/tdactor/test/actors_simple.cpp index 58f14ac48..78d32d543 100644 --- a/tdactor/test/actors_simple.cpp +++ b/tdactor/test/actors_simple.cpp @@ -256,8 +256,7 @@ TEST(Actors, simple_migrate) { sb.clear(); sb2.clear(); - td::ConcurrentScheduler scheduler; - scheduler.init(2); + td::ConcurrentScheduler scheduler(2, 0); auto pong = scheduler.create_actor_unsafe(2, "Pong").release(); scheduler.create_actor_unsafe(1, "Ping", pong).release(); scheduler.start(); @@ -300,8 +299,7 @@ class OpenClose final : public td::Actor { }; TEST(Actors, open_close) { - td::ConcurrentScheduler scheduler; - scheduler.init(2); + td::ConcurrentScheduler scheduler(2, 0); int cnt = 10000; // TODO(perf) optimize scheduler.create_actor_unsafe(1, "A", cnt).release(); scheduler.create_actor_unsafe(2, "B", cnt).release(); @@ -425,8 +423,7 @@ class LinkTokenMasterActor final : public td::Actor { }; TEST(Actors, link_token) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); auto cnt = 100000; scheduler.create_actor_unsafe(0, "A", cnt).release(); scheduler.start(); @@ -485,8 +482,7 @@ class LaterMasterActor final : public td::Actor { TEST(Actors, later) { sb.clear(); - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); while (scheduler.run_main(10)) { @@ -524,8 +520,7 @@ class MultiPromise1 final : public td::Actor { }; TEST(Actors, MultiPromise) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); while (scheduler.run_main(10)) { @@ -546,8 +541,7 @@ class FastPromise final : public td::Actor { }; TEST(Actors, FastPromise) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); while (scheduler.run_main(10)) { @@ -566,8 +560,7 @@ class StopInTeardown final : public td::Actor { }; TEST(Actors, stop_in_teardown) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); while (scheduler.run_main(10)) { @@ -601,8 +594,7 @@ class AlwaysWaitForMailbox final : public td::Actor { }; TEST(Actors, always_wait_for_mailbox) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); while (scheduler.run_main(10)) { @@ -612,8 +604,7 @@ TEST(Actors, always_wait_for_mailbox) { #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED TEST(Actors, send_from_other_threads) { - td::ConcurrentScheduler scheduler; - scheduler.init(1); + td::ConcurrentScheduler scheduler(1, 0); int thread_n = 10; class Listener final : public td::Actor { public: @@ -680,8 +671,7 @@ class MultiPromiseSendClosureLaterTest final : public td::Actor { }; TEST(Actors, MultiPromiseSendClosureLater) { - td::ConcurrentScheduler scheduler; - scheduler.init(0); + td::ConcurrentScheduler scheduler(0, 0); scheduler.create_actor_unsafe(0, "MultiPromiseSendClosureLaterTest").release(); scheduler.start(); while (scheduler.run_main(1)) { diff --git a/tdactor/test/actors_workers.cpp b/tdactor/test/actors_workers.cpp index 748edd4e8..bac42e3fd 100644 --- a/tdactor/test/actors_workers.cpp +++ b/tdactor/test/actors_workers.cpp @@ -106,8 +106,7 @@ class Manager final : public td::Actor { }; static void test_workers(int threads_n, int workers_n, int queries_n, int query_size) { - td::ConcurrentScheduler sched; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); td::vector> workers; for (int i = 0; i < workers_n; i++) { diff --git a/test/db.cpp b/test/db.cpp index b51a8cf20..61757e989 100644 --- a/test/db.cpp +++ b/test/db.cpp @@ -684,8 +684,7 @@ TEST(DB, persistent_key_value) { int ref_cnt_; }; - td::ConcurrentScheduler sched; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe
(0, "Main", threads_n, &queries, &res).release(); sched.start(); while (sched.run_main(10)) { diff --git a/test/mtproto.cpp b/test/mtproto.cpp index f15c5ca10..89f5441ab 100644 --- a/test/mtproto.cpp +++ b/test/mtproto.cpp @@ -47,9 +47,8 @@ #include "td/utils/Time.h" TEST(Mtproto, GetHostByNameActor) { - td::ConcurrentScheduler sched; int threads_n = 1; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); int cnt = 1; td::vector> actors; @@ -139,9 +138,8 @@ TEST(Time, parse_http_date) { } TEST(Mtproto, config) { - td::ConcurrentScheduler sched; int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); int cnt = 1; { @@ -273,7 +271,6 @@ class Mtproto_ping final : public td::Test { using Test::Test; bool step() final { if (!is_inited_) { - sched_.init(0); sched_.create_actor_unsafe(0, "Pinger", get_default_ip_address(), &result_).release(); sched_.start(); is_inited_ = true; @@ -292,7 +289,7 @@ class Mtproto_ping final : public td::Test { private: bool is_inited_ = false; - td::ConcurrentScheduler sched_; + td::ConcurrentScheduler sched_{0, 0}; td::Status result_; }; td::RegisterTest mtproto_ping("Mtproto_ping"); @@ -416,7 +413,6 @@ class Mtproto_handshake final : public td::Test { using Test::Test; bool step() final { if (!is_inited_) { - sched_.init(0); sched_.create_actor_unsafe(0, "HandshakeTestActor", get_default_dc_id(), &result_).release(); sched_.start(); is_inited_ = true; @@ -435,7 +431,7 @@ class Mtproto_handshake final : public td::Test { private: bool is_inited_ = false; - td::ConcurrentScheduler sched_; + td::ConcurrentScheduler sched_{0, 0}; td::Status result_; }; td::RegisterTest mtproto_handshake("Mtproto_handshake"); @@ -484,9 +480,8 @@ class Socks5TestActor final : public td::Actor { TEST(Mtproto, socks5) { return; - td::ConcurrentScheduler sched; int threads_n = 0; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); sched.create_actor_unsafe(0, "Socks5TestActor").release(); sched.start(); @@ -640,7 +635,6 @@ class Mtproto_FastPing final : public td::Test { using Test::Test; bool step() final { if (!is_inited_) { - sched_.init(0); sched_.create_actor_unsafe(0, "FastPingTestActor", &result_).release(); sched_.start(); is_inited_ = true; @@ -659,7 +653,7 @@ class Mtproto_FastPing final : public td::Test { private: bool is_inited_ = false; - td::ConcurrentScheduler sched_; + td::ConcurrentScheduler sched_{0, 0}; td::Status result_; }; td::RegisterTest mtproto_fastping("Mtproto_FastPing"); @@ -676,9 +670,8 @@ TEST(Mtproto, Grease) { } TEST(Mtproto, TlsTransport) { - td::ConcurrentScheduler sched; int threads_n = 1; - sched.init(threads_n); + td::ConcurrentScheduler sched(threads_n, 0); { auto guard = sched.get_main_guard(); class RunTest final : public td::Actor { diff --git a/test/online.cpp b/test/online.cpp index f472c6ae8..6bcdcec83 100644 --- a/test/online.cpp +++ b/test/online.cpp @@ -617,8 +617,7 @@ int main(int argc, char **argv) { } SET_VERBOSITY_LEVEL(new_verbosity_level); - td::ConcurrentScheduler sched; - sched.init(4); + td::ConcurrentScheduler sched(4, 0); sched.create_actor_unsafe(0, "TestTd", std::move(test_options)).release(); sched.start(); while (sched.run_main(10)) { diff --git a/test/secret.cpp b/test/secret.cpp index 3c1d351ea..5a602fe85 100644 --- a/test/secret.cpp +++ b/test/secret.cpp @@ -999,9 +999,7 @@ void FakeSecretChatContext::on_read_message(int64, Promise<> promise) { TEST(Secret, go) { return; - ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); + ConcurrentScheduler sched(0, 0); Status result; sched.create_actor_unsafe(0, "HandshakeTestActor", &result).release(); diff --git a/test/tdclient.cpp b/test/tdclient.cpp index d2a5a3afb..ca95fa4d8 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -832,7 +832,6 @@ class Tdclient_login final : public td::Test { using Test::Test; bool step() final { if (!is_inited_) { - sched_.init(4); sched_.create_actor_unsafe(0, "LoginTestActor", &result_).release(); sched_.start(); is_inited_ = true; @@ -852,7 +851,7 @@ class Tdclient_login final : public td::Test { private: bool is_inited_ = false; - td::ConcurrentScheduler sched_; + td::ConcurrentScheduler sched_{4, 0}; td::Status result_; }; //RegisterTest Tdclient_login("Tdclient_login"); From b49b669ac127d06aea34ef32799dac44538dcae7 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 15:33:16 +0300 Subject: [PATCH 155/200] Support affinity mask on Linux. --- .../td/utils/port/detail/ThreadPthread.cpp | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index 91bbf8ca7..a6ed9fa67 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -11,6 +11,7 @@ char disable_linker_warning_about_empty_file_thread_pthread_cpp TD_UNUSED; #if TD_THREAD_PTHREAD #include "td/utils/misc.h" +#include "td/utils/port/detail/skip_eintr.h" #include #include @@ -95,11 +96,44 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at } Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { +#if TD_LINUX + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + for (int j = 0; j < 64 && j < CPU_SETSIZE; j++) { + if ((mask >> j) & 1) { + CPU_SET(j, &cpuset); + } + } + + auto res = skip_eintr([&] { return pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); }); + if (res) { + return OS_ERROR("Failed to set thread affinity mask"); + } + return Status::OK(); +#else return Status::Error("Unsupported"); +#endif } uint64 ThreadPthread::get_affinity_mask(id thread_id) { +#if TD_LINUX + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + auto res = skip_eintr([&] { return pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); }); + if (res) { + return 0; + } + + uint64 mask = 0; + for (int j = 0; j < 64 && j < CPU_SETSIZE; j++) { + if (CPU_ISSET(j, &cpuset)) { + mask |= static_cast(1) << j; + } + } + return mask; +#else return 0; +#endif } namespace this_thread_pthread { From c646e43e3714e362d5c3ae3fa20fd9fd9792b8a6 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 16:31:47 +0300 Subject: [PATCH 156/200] Minor improvements. --- td/generate/scheme/td_api.tl | 2 +- td/telegram/MessageReaction.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 6414fbeb3..3f802c80a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2590,7 +2590,7 @@ availableReaction type:ReactionType needs_premium:Bool = AvailableReaction; //@top_reactions List of reactions to be shown at the top //@recent_reactions List of recently used reactions //@popular_reactions List of popular reactions -//@allow_custom_emoji True, if any other custom emoji reaction could be added by Telegram Premium subscribers +//@allow_custom_emoji True, if custom emoji reactions could be added by Telegram Premium subscribers availableReactions top_reactions:vector recent_reactions:vector popular_reactions:vector allow_custom_emoji:Bool = AvailableReactions; //@description Contains information about a emoji reaction diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 8073c4f23..f9dc4bf76 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -331,8 +331,6 @@ class SetDefaultReactionQuery final : public Td::ResultHandler { } auto default_reaction = td_->option_manager_->get_option_string("default_reaction", "-"); - LOG(INFO) << "Successfully set reaction " << reaction_ << " as default, current default is " << default_reaction; - if (default_reaction != reaction_) { send_set_default_reaction_query(td_); } else { @@ -345,7 +343,7 @@ class SetDefaultReactionQuery final : public Td::ResultHandler { return; } - LOG(INFO) << "Failed to set default reaction: " << status; + LOG(INFO) << "Receive error for SetDefaultReactionQuery: " << status; td_->option_manager_->set_option_empty("default_reaction_needs_sync"); send_closure(G()->config_manager(), &ConfigManager::request_config, false); } From 534f17e784802c9a3c3779c90faf93de277dbfd5 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 16:41:59 +0300 Subject: [PATCH 157/200] Randomize delays between failed getChannelDifference. --- td/telegram/MessagesManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b8cf9e6d5..541197a34 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -38805,7 +38805,8 @@ void MessagesManager::on_get_channel_difference( if (delay == 0) { delay = 1; } - channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), delay); + channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), + Random::fast(delay * 1000, delay * 1500) * 1e-3); delay *= 2; if (delay > 60) { delay = Random::fast(60, 80); From cef7ca17f3f8de3099686f1f67c01d99a4e26cb7 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 17:15:12 +0300 Subject: [PATCH 158/200] Always show all reaction choosers in private chats. --- td/telegram/MessageReaction.cpp | 31 ++++++++++++++++++++++++------- td/telegram/MessageReaction.h | 3 ++- td/telegram/MessagesManager.cpp | 10 ++++++++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index f9dc4bf76..39e4e7038 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -433,16 +433,33 @@ void MessageReaction::set_is_chosen(bool is_chosen, DialogId chooser_dialog_id, } } -td_api::object_ptr MessageReaction::get_message_reaction_object(Td *td) const { +td_api::object_ptr MessageReaction::get_message_reaction_object(Td *td, UserId my_user_id, + UserId peer_user_id) const { CHECK(!is_empty()); vector> recent_choosers; - for (auto dialog_id : recent_chooser_dialog_ids_) { - auto recent_chooser = get_min_message_sender_object(td, dialog_id, "get_message_reaction_object"); - if (recent_chooser != nullptr) { - recent_choosers.push_back(std::move(recent_chooser)); - if (recent_choosers.size() == MAX_RECENT_CHOOSERS) { - break; + if (my_user_id.is_valid()) { + CHECK(peer_user_id.is_valid()); + if (is_chosen()) { + auto recent_chooser = get_min_message_sender_object(td, DialogId(my_user_id), "get_message_reaction_object"); + if (recent_chooser != nullptr) { + recent_choosers.push_back(std::move(recent_chooser)); + } + } + if (choose_count_ >= (is_chosen() ? 2 : 1)) { + auto recent_chooser = get_min_message_sender_object(td, DialogId(peer_user_id), "get_message_reaction_object"); + if (recent_chooser != nullptr) { + recent_choosers.push_back(std::move(recent_chooser)); + } + } + } else { + for (auto dialog_id : recent_chooser_dialog_ids_) { + auto recent_chooser = get_min_message_sender_object(td, dialog_id, "get_message_reaction_object"); + if (recent_chooser != nullptr) { + recent_choosers.push_back(std::move(recent_chooser)); + if (recent_choosers.size() == MAX_RECENT_CHOOSERS) { + break; + } } } } diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 6c30a8a4e..9051a8a99 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -85,7 +85,8 @@ class MessageReaction { return recent_chooser_min_channels_; } - td_api::object_ptr get_message_reaction_object(Td *td) const; + td_api::object_ptr get_message_reaction_object(Td *td, UserId my_user_id, + UserId peer_user_id) const; template void store(StorerT &storer) const; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 541197a34..e0532471b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6961,8 +6961,14 @@ td_api::object_ptr MessagesManager::get_message_ vector> reactions; if (has_reactions) { - reactions = transform(m->reactions->reactions_, [td = td_](const MessageReaction &reaction) { - return reaction.get_message_reaction_object(td); + UserId my_user_id; + UserId peer_user_id; + if (dialog_id.get_type() == DialogType::User) { + my_user_id = td_->contacts_manager_->get_my_id(); + peer_user_id = dialog_id.get_user_id(); + } + reactions = transform(m->reactions->reactions_, [td = td_, my_user_id, peer_user_id](const MessageReaction &reaction) { + return reaction.get_message_reaction_object(td, my_user_id, peer_user_id); }); } From e5fbb3355560858516d61058f3e3f6c6a70fd39a Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 17:55:02 +0300 Subject: [PATCH 159/200] Remove all chosen reactions, exceeding reaction limit. --- td/telegram/MessageReaction.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index 39e4e7038..2678bfc52 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -37,6 +37,13 @@ namespace td { +static size_t get_max_reaction_count() { + bool is_premium = G()->get_option_boolean("is_premium"); + auto option_key = is_premium ? Slice("reactions_user_max_premium") : Slice("reactions_user_max_default"); + return static_cast( + max(static_cast(1), static_cast(G()->get_option_integer(option_key, is_premium ? 3 : 1)))); +} + static int64 get_custom_emoji_id(const string &reaction) { auto r_decoded = base64_decode(Slice(&reaction[1], reaction.size() - 1)); CHECK(r_decoded.is_ok()); @@ -648,13 +655,13 @@ bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogI return false; } - bool is_premium = G()->get_option_boolean("is_premium"); - auto option_key = is_premium ? Slice("reactions_user_max_premium") : Slice("reactions_user_max_default"); - int32 max_reaction_count = max(1, static_cast(G()->get_option_integer(option_key, is_premium ? 3 : 1))); - if (new_chosen_reaction_order.size() > static_cast(max_reaction_count)) { - bool is_removed = do_remove_reaction(new_chosen_reaction_order[0], chooser_dialog_id, have_recent_choosers); + auto max_reaction_count = get_max_reaction_count(); + while (new_chosen_reaction_order.size() > max_reaction_count) { + auto index = new_chosen_reaction_order[0] == reaction ? 1 : 0; + CHECK(static_cast(index) < new_chosen_reaction_order.size()); + bool is_removed = do_remove_reaction(new_chosen_reaction_order[index], chooser_dialog_id, have_recent_choosers); CHECK(is_removed); - new_chosen_reaction_order.erase(new_chosen_reaction_order.begin()); + new_chosen_reaction_order.erase(new_chosen_reaction_order.begin() + index); } if (new_chosen_reaction_order.size() == 1) { @@ -669,10 +676,19 @@ bool MessageReactions::remove_reaction(const string &reaction, DialogId chooser_ if (!chosen_reaction_order_.empty()) { bool is_removed = td::remove(chosen_reaction_order_, reaction); CHECK(is_removed); + + auto max_reaction_count = get_max_reaction_count(); + while (chosen_reaction_order_.size() > max_reaction_count) { + is_removed = do_remove_reaction(chosen_reaction_order_[0], chooser_dialog_id, have_recent_choosers); + CHECK(is_removed); + chosen_reaction_order_.erase(chosen_reaction_order_.begin()); + } + if (chosen_reaction_order_.size() <= 1) { reset_to_empty(chosen_reaction_order_); } } + return true; } return false; From 7922df1039dfcb23a2b3151633d390323a8f260b Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 18:21:41 +0300 Subject: [PATCH 160/200] Explicitly ignore failure to set thread affinity mask. --- tdactor/td/actor/ConcurrentScheduler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdactor/td/actor/ConcurrentScheduler.cpp b/tdactor/td/actor/ConcurrentScheduler.cpp index f5ffe10a2..bbfaba362 100644 --- a/tdactor/td/actor/ConcurrentScheduler.cpp +++ b/tdactor/td/actor/ConcurrentScheduler.cpp @@ -81,7 +81,7 @@ void ConcurrentScheduler::start() { detail::Iocp::Guard iocp_guard(iocp_.get()); #endif if (thread_affinity_mask != 0) { - thread::set_affinity_mask(this_thread::get_id(), thread_affinity_mask); + thread::set_affinity_mask(this_thread::get_id(), thread_affinity_mask).ignore(); } while (!is_finished()) { sched->run(Timestamp::in(10)); From e087521b01214bf8d942c474f6ee05107b4472e6 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 14 Sep 2022 19:02:49 +0300 Subject: [PATCH 161/200] Fix compilation error. --- td/telegram/MessageContent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index fe198606c..875ca6f57 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -4684,7 +4684,7 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const if (type == MessageContentDupType::Copy || type == MessageContentDupType::ServerCopy) { remove_unallowed_entities(td, result->text, dialog_id); } - return result; + return std::move(result); } case MessageContentType::Venue: return make_unique(*static_cast(content)); From 111018eadd1e248ade2a4beee90f03bd9825727c Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 15 Sep 2022 15:03:19 +0300 Subject: [PATCH 162/200] Add logging for some slow operations. --- td/mtproto/RawConnection.cpp | 4 +++- tdnet/td/net/SslStream.cpp | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/td/mtproto/RawConnection.cpp b/td/mtproto/RawConnection.cpp index a663e6af3..776ded6f2 100644 --- a/td/mtproto/RawConnection.cpp +++ b/td/mtproto/RawConnection.cpp @@ -25,6 +25,7 @@ #include "td/utils/SliceBuilder.h" #include "td/utils/Status.h" #include "td/utils/StorerBase.h" +#include "td/utils/Timer.h" #include #include @@ -247,10 +248,11 @@ class RawConnectionDefault final : public RawConnection { if (has_error_) { return Status::Error("Connection has already failed"); } + PerfWarningTimer timer("RawConnection::do_flush", 0.01); sync_with_poll(socket_fd_); // read/write - // EINVAL may be returned in linux kernel < 2.6.28. And on some new kernels too. + // EINVAL can be returned in Linux kernel < 2.6.28. And on some new kernels too. // just close connection and hope that read or write will not return this error too. TRY_STATUS(socket_fd_.get_pending_error()); diff --git a/tdnet/td/net/SslStream.cpp b/tdnet/td/net/SslStream.cpp index 2c88632f3..ca602cd7e 100644 --- a/tdnet/td/net/SslStream.cpp +++ b/tdnet/td/net/SslStream.cpp @@ -151,6 +151,7 @@ using SslCtx = std::shared_ptr; struct SslHandleDeleter { void operator()(SSL *ssl_handle) { + auto start_time = Time::now(); if (SSL_is_init_finished(ssl_handle)) { clear_openssl_errors("Before SSL_shutdown"); SSL_set_quiet_shutdown(ssl_handle, 1); @@ -158,6 +159,10 @@ struct SslHandleDeleter { clear_openssl_errors("After SSL_shutdown"); } SSL_free(ssl_handle); + auto elapsed_time = Time::now() - start_time; + if (elapsed_time >= 0.001) { + LOG(ERROR) << "SSL_free took " << elapsed_time << " seconds"; + } } }; @@ -289,7 +294,13 @@ Result create_ssl_ctx(CSlice cert_file, SslStream::VerifyPeer verify_pee return get_default_unverified_ssl_ctx(); } } - return do_create_ssl_ctx(cert_file, verify_peer); + auto start_time = Time::now(); + auto result = do_create_ssl_ctx(cert_file, verify_peer); + auto elapsed_time = Time::now() - start_time; + if (elapsed_time >= 0.01) { + LOG(ERROR) << "do_create_ssl_ctx took " << elapsed_time << " seconds"; + } + return result; } } // namespace @@ -381,7 +392,12 @@ class SslStreamImpl { Result read(MutableSlice slice) { clear_openssl_errors("Before SslFd::read"); + auto start_time = Time::now(); auto size = SSL_read(ssl_handle_.get(), slice.data(), static_cast(slice.size())); + auto elapsed_time = Time::now() - start_time; + if (elapsed_time >= 0.01) { + LOG(ERROR) << "SSL_read took " << elapsed_time << " seconds and returned " << size; + } if (size <= 0) { return process_ssl_error(size); } From ce1292ea326bdeb29adfd0547ffd5f4a157c2c0a Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 15 Sep 2022 16:08:19 +0300 Subject: [PATCH 163/200] Allow to always reuse photos from inputMessagePhoto. --- td/telegram/MessageContent.cpp | 4 ++-- td/telegram/files/FileManager.cpp | 11 ++++++++--- td/telegram/files/FileManager.h | 3 ++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 875ca6f57..0447fba86 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2086,8 +2086,8 @@ Result get_input_message_content( } case td_api::inputMessagePhoto::ID: { auto input_message = static_cast(input_message_content.get()); - r_file_id = - td->file_manager_->get_input_file_id(FileType::Photo, input_message->photo_, dialog_id, false, is_secret); + r_file_id = td->file_manager_->get_input_file_id(FileType::Photo, input_message->photo_, dialog_id, false, + is_secret, false, false, true); input_thumbnail = std::move(input_message->thumbnail_); if (!input_message->added_sticker_file_ids_.empty()) { sticker_file_ids = td->stickers_manager_->get_attached_sticker_file_ids(input_message->added_sticker_file_ids_); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 1119865d5..a8e928289 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -3145,7 +3145,7 @@ Result FileManager::get_input_thumbnail_file_id(const tl_object_ptr FileManager::get_input_file_id(FileType type, const tl_object_ptr &file, DialogId owner_dialog_id, bool allow_zero, bool is_encrypted, - bool get_by_hash, bool is_secure) { + bool get_by_hash, bool is_secure, bool force_reuse) { if (file == nullptr) { if (allow_zero) { return FileId(); @@ -3176,8 +3176,13 @@ Result FileManager::get_input_file_id(FileType type, const tl_object_ptr auto file_id = file_hash_to_file_id_.get(hash); if (file_id.is_valid()) { auto file_view = get_file_view(file_id); - if (!file_view.empty() && file_view.has_remote_location() && !file_view.remote_location().is_web()) { - return file_id; + if (!file_view.empty()) { + if (force_reuse) { + return file_id; + } + if (file_view.has_remote_location() && !file_view.remote_location().is_web()) { + return file_id; + } } } } diff --git a/td/telegram/files/FileManager.h b/td/telegram/files/FileManager.h index f07272c0d..ac53d8f0f 100644 --- a/td/telegram/files/FileManager.h +++ b/td/telegram/files/FileManager.h @@ -485,7 +485,8 @@ class FileManager final : public FileLoadManager::Callback { DialogId owner_dialog_id, bool is_encrypted) TD_WARN_UNUSED_RESULT; Result get_input_file_id(FileType type, const tl_object_ptr &file, DialogId owner_dialog_id, bool allow_zero, bool is_encrypted, - bool get_by_hash = false, bool is_secure = false) TD_WARN_UNUSED_RESULT; + bool get_by_hash = false, bool is_secure = false, + bool force_reuse = false) TD_WARN_UNUSED_RESULT; Result get_map_thumbnail_file_id(Location location, int32 zoom, int32 width, int32 height, int32 scale, DialogId owner_dialog_id) TD_WARN_UNUSED_RESULT; From d2ad29725de012339f5861bccf2b6afc3500116e Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 15 Sep 2022 21:35:37 +0300 Subject: [PATCH 164/200] Replace actor in chatEventMessagePinned/chatEventMessageUnpinned. --- td/telegram/DialogEventLog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/td/telegram/DialogEventLog.cpp b/td/telegram/DialogEventLog.cpp index ff7c8928f..56b5682e3 100644 --- a/td/telegram/DialogEventLog.cpp +++ b/td/telegram/DialogEventLog.cpp @@ -152,9 +152,8 @@ static td_api::object_ptr get_chat_event_action_object( } case telegram_api::channelAdminLogEventActionUpdatePinned::ID: { auto action = move_tl_object_as(action_ptr); - DialogId sender_dialog_id; auto message = td->messages_manager_->get_dialog_event_log_message_object( - DialogId(channel_id), std::move(action->message_), sender_dialog_id); + DialogId(channel_id), std::move(action->message_), actor_dialog_id); if (message == nullptr) { return nullptr; } From 0025c4164b8d406f1e51004aca88b6678dd9edaf Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 16 Sep 2022 01:30:54 +0300 Subject: [PATCH 165/200] Add internalLinkTypeInstantView. --- td/generate/scheme/td_api.tl | 3 +++ td/telegram/LinkManager.cpp | 18 ++++++++++++++++++ td/telegram/LinkManager.h | 1 + tdutils/td/utils/HttpUrl.cpp | 2 +- test/link.cpp | 18 ++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 3f802c80a..524c6e9d0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3725,6 +3725,9 @@ internalLinkTypeFilterSettings = InternalLinkType; //@bot_username Username of the bot that owns the game @game_short_name Short name of the game internalLinkTypeGame bot_username:string game_short_name:string = InternalLinkType; +//@description The link must be opened in an Instant View. Call getWebPageInstantView with the given URL to process the link @url URL to be passed to getWebPageInstantView +internalLinkTypeInstantView url:string = InternalLinkType; + //@description The link is a link to an invoice. Call getPaymentForm with the given invoice name to process the link @invoice_name Name of the invoice internalLinkTypeInvoice invoice_name:string = InternalLinkType; diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 20f644252..10217df8f 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -337,6 +337,18 @@ class LinkManager::InternalLinkGame final : public InternalLink { } }; +class LinkManager::InternalLinkInstantView final : public InternalLink { + string url_; + + td_api::object_ptr get_internal_link_type_object() const final { + return td_api::make_object(url_); + } + + public: + explicit InternalLinkInstantView(string url) : url_(std::move(url)) { + } +}; + class LinkManager::InternalLinkInvoice final : public InternalLink { string invoice_name_; @@ -1336,6 +1348,12 @@ unique_ptr LinkManager::parse_t_me_link_query(Slice q // /share/url?url=&text= return get_internal_link_message_draft(get_arg("url"), get_arg("text")); } + } else if (path[0] == "iv") { + if (path.size() == 1 && has_arg("url")) { + // /iv?url=&rhash= + return td::make_unique(PSTRING() + << "https://t.me/iv" << copy_arg("url") << copy_arg("rhash")); + } } else if (is_valid_username(path[0])) { if (path.size() >= 2 && to_integer(path[1]) > 0) { // //12345?single&thread=&comment=&t= diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h index 579fcba97..d9da23a6c 100644 --- a/td/telegram/LinkManager.h +++ b/td/telegram/LinkManager.h @@ -101,6 +101,7 @@ class LinkManager final : public Actor { class InternalLinkDialogInvite; class InternalLinkFilterSettings; class InternalLinkGame; + class InternalLinkInstantView; class InternalLinkInvoice; class InternalLinkLanguage; class InternalLinkLanguageSettings; diff --git a/tdutils/td/utils/HttpUrl.cpp b/tdutils/td/utils/HttpUrl.cpp index ced0a2860..e1d46964b 100644 --- a/tdutils/td/utils/HttpUrl.cpp +++ b/tdutils/td/utils/HttpUrl.cpp @@ -197,7 +197,7 @@ HttpUrlQuery parse_url_query(Slice query) { HttpUrlQuery result; result.path_ = full_split(url_decode(query.substr(0, path_size), false), '/'); - if (!result.path_.empty() && result.path_.back().empty()) { + while (!result.path_.empty() && result.path_.back().empty()) { result.path_.pop_back(); } diff --git a/test/link.cpp b/test/link.cpp index b81774f31..991b3b9c8 100644 --- a/test/link.cpp +++ b/test/link.cpp @@ -88,6 +88,7 @@ static void parse_internal_link(const td::string &url, td::td_api::object_ptr(bot_username, game_short_name); }; + auto instant_view = [](const td::string &url) { + return td::td_api::make_object(url); + }; auto invoice = [](const td::string &invoice_name) { return td::td_api::make_object(invoice_name); }; @@ -638,6 +642,20 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:setlanguage?lang=abc%30ef", language_pack("abc0ef")); parse_internal_link("tg://setlanguage?lang=", unknown_deep_link("tg://setlanguage?lang=")); + parse_internal_link("http://telegram.dog/iv?url=https://telegram.org&rhash=abcdef&test=1&tg_rhash=1", + instant_view("https://t.me/iv?url=https%3A%2F%2Ftelegram.org&rhash=abcdef")); + parse_internal_link("t.me/iva?url=https://telegram.org&rhash=abcdef", public_chat("iva")); + parse_internal_link("t.me/iv?url=&rhash=abcdef", nullptr); + parse_internal_link("t.me/iv?url=https://telegram.org&rhash=", + instant_view("https://t.me/iv?url=https%3A%2F%2Ftelegram.org&rhash")); + parse_internal_link("t.me/iv//////?url=https://telegram.org&rhash=", + instant_view("https://t.me/iv?url=https%3A%2F%2Ftelegram.org&rhash")); + parse_internal_link("t.me/iv/////1/?url=https://telegram.org&rhash=", nullptr); + parse_internal_link("t.me/iv", nullptr); + parse_internal_link("t.me/iv?#url=https://telegram.org&rhash=abcdef", nullptr); + parse_internal_link("tg:iv?url=https://telegram.org&rhash=abcdef", + unknown_deep_link("tg://iv?url=https://telegram.org&rhash=abcdef")); + parse_internal_link("t.me/addtheme?slug=abcdef", nullptr); parse_internal_link("t.me/addtheme", nullptr); parse_internal_link("t.me/addtheme/", nullptr); From 47d4101defec47bf3d6064512fdc73a4cf4e5980 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 16 Sep 2022 13:20:19 +0300 Subject: [PATCH 166/200] Add enum LinkType. --- td/telegram/LinkManager.cpp | 36 ++++++++++++++++++------------------ td/telegram/LinkManager.h | 5 +++-- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 10217df8f..85c31fcd6 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -888,8 +888,7 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { return result; } - result.is_internal_ = true; - result.is_tg_ = true; + result.type_ = LinkType::Tg; result.query_ = link.str(); return result; } else { @@ -905,8 +904,7 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { subdomain != "addtheme" && subdomain != "auth" && subdomain != "confirmphone" && subdomain != "invoice" && subdomain != "joinchat" && subdomain != "login" && subdomain != "proxy" && subdomain != "setlanguage" && subdomain != "share" && subdomain != "socks") { - result.is_internal_ = true; - result.is_tg_ = false; + result.type_ = LinkType::TMe; result.query_ = PSTRING() << '/' << subdomain << http_url.query_; return result; } @@ -929,8 +927,7 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { for (auto t_me_url : t_me_urls) { if (host == t_me_url) { - result.is_internal_ = true; - result.is_tg_ = false; + result.type_ = LinkType::TMe; Slice query = http_url.query_; while (true) { @@ -954,18 +951,21 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { bool LinkManager::is_internal_link(Slice link) { auto info = get_link_info(link); - return info.is_internal_; + return info.type_ != LinkType::External; } unique_ptr LinkManager::parse_internal_link(Slice link, bool is_trusted) { auto info = get_link_info(link); - if (!info.is_internal_) { - return nullptr; - } - if (info.is_tg_) { - return parse_tg_link_query(info.query_, is_trusted); - } else { - return parse_t_me_link_query(info.query_, is_trusted); + switch (info.type_) { + case LinkType::External: + return nullptr; + case LinkType::Tg: + return parse_tg_link_query(info.query_, is_trusted); + case LinkType::TMe: + return parse_t_me_link_query(info.query_, is_trusted); + default: + UNREACHABLE(); + return nullptr; } } @@ -1584,11 +1584,11 @@ void LinkManager::get_link_login_url(const string &url, bool allow_write_access, string LinkManager::get_dialog_invite_link_hash(Slice invite_link) { auto link_info = get_link_info(invite_link); - if (!link_info.is_internal_) { + if (link_info.type_ != LinkType::Tg && link_info.type_ != LinkType::TMe) { return string(); } const auto url_query = parse_url_query(link_info.query_); - return get_url_query_hash(link_info.is_tg_, url_query); + return get_url_query_hash(link_info.type_ == LinkType::Tg, url_query); } string LinkManager::get_dialog_invite_link(Slice hash, bool is_internal) { @@ -1691,7 +1691,7 @@ Result LinkManager::get_message_link_info(Slice url) { return Status::Error("URL must be non-empty"); } auto link_info = get_link_info(url); - if (!link_info.is_internal_) { + if (link_info.type_ != LinkType::Tg && link_info.type_ != LinkType::TMe) { return Status::Error("Invalid message link URL"); } url = link_info.query_; @@ -1703,7 +1703,7 @@ Result LinkManager::get_message_link_info(Slice url) { Slice media_timestamp_slice; bool is_single = false; bool for_comment = false; - if (link_info.is_tg_) { + if (link_info.type_ == LinkType::Tg) { // resolve?domain=username&post=12345&single&t=123&comment=12&thread=21 // privatepost?channel=123456789&post=12345&single&t=123&comment=12&thread=21 diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h index d9da23a6c..ccf423ffa 100644 --- a/td/telegram/LinkManager.h +++ b/td/telegram/LinkManager.h @@ -123,9 +123,10 @@ class LinkManager final : public Actor { class InternalLinkUserPhoneNumber; class InternalLinkVoiceChat; + enum class LinkType : int32 { External, TMe, Tg }; + struct LinkInfo { - bool is_internal_ = false; - bool is_tg_ = false; + LinkType type_ = LinkType::External; string query_; }; // returns information about the link From b76a920db812e57d04ad852ac3f95d15a2fb9a55 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 16 Sep 2022 13:51:52 +0300 Subject: [PATCH 167/200] Open Telegraph links in instant view. --- td/telegram/LinkManager.cpp | 12 ++++++++++++ td/telegram/LinkManager.h | 2 +- test/link.cpp | 11 +++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 85c31fcd6..83a02cf7d 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -945,6 +945,16 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { return result; } } + + if (http_url.query_.size() > 1) { + for (auto telegraph_url : {Slice("telegra.ph"), Slice("te.legra.ph"), Slice("graph.org")}) { + if (host == telegraph_url) { + result.type_ = LinkType::Telegraph; + result.query_ = std::move(http_url.query_); + return result; + } + } + } } return result; } @@ -963,6 +973,8 @@ unique_ptr LinkManager::parse_internal_link(Slice lin return parse_tg_link_query(info.query_, is_trusted); case LinkType::TMe: return parse_t_me_link_query(info.query_, is_trusted); + case LinkType::Telegraph: + return td::make_unique(PSTRING() << "https://telegra.ph" << info.query_); default: UNREACHABLE(); return nullptr; diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h index ccf423ffa..bcd284bb3 100644 --- a/td/telegram/LinkManager.h +++ b/td/telegram/LinkManager.h @@ -123,7 +123,7 @@ class LinkManager final : public Actor { class InternalLinkUserPhoneNumber; class InternalLinkVoiceChat; - enum class LinkType : int32 { External, TMe, Tg }; + enum class LinkType : int32 { External, TMe, Tg, Telegraph }; struct LinkInfo { LinkType type_ = LinkType::External; diff --git a/test/link.cpp b/test/link.cpp index 991b3b9c8..256c57bf8 100644 --- a/test/link.cpp +++ b/test/link.cpp @@ -27,7 +27,8 @@ static void check_find_urls(const td::string &url, bool is_valid) { { if (is_valid && (td::begins_with(url_lower, "http") || td::begins_with(url_lower, "t.me")) && - url.find('.') != td::string::npos && url.find(' ') == td::string::npos && url != "http://..") { + url.find('.') != td::string::npos && url.find(' ') == td::string::npos && url != "http://.." && + url.find("ra.ph") == td::string::npos && url.find("Aph") == td::string::npos) { auto urls = td::find_urls(url); ASSERT_EQ(1u, urls.size()); ASSERT_STREQ(url, urls[0].first); @@ -86,7 +87,7 @@ static void parse_internal_link(const td::string &url, td::td_api::object_ptrget_id() == td::td_api::internalLinkTypeMessageDraft::ID) { static_cast(object.get())->text_->entities_.clear(); } - ASSERT_STREQ(url + " " + to_string(expected), url + " " + to_string(object)); + ASSERT_STREQ(url + ' ' + to_string(expected), url + ' ' + to_string(object)); } else { LOG_IF(ERROR, expected != nullptr) << url; ASSERT_TRUE(expected == nullptr); @@ -964,4 +965,10 @@ TEST(Link, parse_internal_link) { parse_internal_link("setlanguage.t.me", nullptr); parse_internal_link("share.t.me", nullptr); parse_internal_link("socks.t.me", nullptr); + + parse_internal_link("www.telegra.ph/", nullptr); + parse_internal_link("www.telegrA.ph/#", nullptr); + parse_internal_link("www.telegrA.ph/?", instant_view("https://telegra.ph/?")); + parse_internal_link("http://te.leGra.ph/?", instant_view("https://telegra.ph/?")); + parse_internal_link("https://grAph.org/12345", instant_view("https://telegra.ph/12345")); } From aeed5107b73d3f99632c1ea602e204c083f6df32 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 16 Sep 2022 13:56:56 +0300 Subject: [PATCH 168/200] Fix Slice lifetime. --- td/telegram/LinkManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 83a02cf7d..a62524317 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -913,9 +913,10 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) { host = host.substr(4); } + string cur_t_me_url; vector t_me_urls{Slice("t.me"), Slice("telegram.me"), Slice("telegram.dog")}; if (Scheduler::context() != nullptr) { // for tests only - string cur_t_me_url = G()->get_option_string("t_me_url"); + cur_t_me_url = G()->get_option_string("t_me_url"); if (tolower_begins_with(cur_t_me_url, "http://") || tolower_begins_with(cur_t_me_url, "https://")) { Slice t_me_url = cur_t_me_url; t_me_url = t_me_url.substr(t_me_url[4] == 's' ? 8 : 7); From 15db91b536d796778b628fef3d60923cef351512 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 16 Sep 2022 21:38:09 +0300 Subject: [PATCH 169/200] Update version to 1.8.6. --- CMakeLists.txt | 2 +- README.md | 2 +- example/cpp/CMakeLists.txt | 2 +- example/uwp/extension.vsixmanifest | 2 +- td/telegram/OptionManager.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 779763bb6..e8b8af387 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if (POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() -project(TDLib VERSION 1.8.5 LANGUAGES CXX C) +project(TDLib VERSION 1.8.6 LANGUAGES CXX C) if (NOT DEFINED CMAKE_MODULE_PATH) set(CMAKE_MODULE_PATH "") diff --git a/README.md b/README.md index 5038d9b71..9a1c2c7d5 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic) Or you could install `TDLib` and then reference it in your CMakeLists.txt like this: ``` -find_package(Td 1.8.5 REQUIRED) +find_package(Td 1.8.6 REQUIRED) target_link_libraries(YourTarget PRIVATE Td::TdStatic) ``` See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/blob/master/example/cpp/CMakeLists.txt). diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt index 1356ac7f3..a9548d67c 100644 --- a/example/cpp/CMakeLists.txt +++ b/example/cpp/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.4 FATAL_ERROR) project(TdExample VERSION 1.0 LANGUAGES CXX) -find_package(Td 1.8.5 REQUIRED) +find_package(Td 1.8.6 REQUIRED) add_executable(tdjson_example tdjson_example.cpp) target_link_libraries(tdjson_example PRIVATE Td::TdJson) diff --git a/example/uwp/extension.vsixmanifest b/example/uwp/extension.vsixmanifest index 95d7134c2..c7df848cd 100644 --- a/example/uwp/extension.vsixmanifest +++ b/example/uwp/extension.vsixmanifest @@ -1,6 +1,6 @@ - + TDLib for Universal Windows Platform TDLib is a library for building Telegram clients https://core.telegram.org/tdlib diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 3f2e6f99b..da5bd959b 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -511,7 +511,7 @@ td_api::object_ptr OptionManager::get_option_synchronously( break; case 'v': if (name == "version") { - return td_api::make_object("1.8.5"); + return td_api::make_object("1.8.6"); } break; } From 0cc3fb0e9d8845bc88be0d3a7d5fc30127355e40 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 01:37:05 +0300 Subject: [PATCH 170/200] Include pthread.h on OpenBSD for pthread_t definition. --- tdutils/td/utils/port/detail/ThreadPthread.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.h b/tdutils/td/utils/port/detail/ThreadPthread.h index a0f15d1a5..88fea76d6 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.h +++ b/tdutils/td/utils/port/detail/ThreadPthread.h @@ -23,6 +23,9 @@ #include #include +#if TD_OPENBSD || TD_SOLARIS +#include +#endif #include namespace td { From 9d5c151a3f4e9d6645c7317344e534200ad6a585 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 13:21:04 +0300 Subject: [PATCH 171/200] Use DWORD as thread::id on Windows. --- tdutils/td/utils/port/detail/ThreadStl.h | 23 ++++++++++++++++++----- tdutils/test/port.cpp | 13 +++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/tdutils/td/utils/port/detail/ThreadStl.h b/tdutils/td/utils/port/detail/ThreadStl.h index ce6ac27fe..dd55a21ec 100644 --- a/tdutils/td/utils/port/detail/ThreadStl.h +++ b/tdutils/td/utils/port/detail/ThreadStl.h @@ -12,6 +12,9 @@ #include "td/utils/common.h" #include "td/utils/invoke.h" +#if TD_WINDOWS +#include "td/utils/port/detail/NativeFd.h" +#endif #include "td/utils/port/detail/ThreadIdGuard.h" #include "td/utils/port/thread_local.h" #include "td/utils/Slice.h" @@ -67,7 +70,7 @@ class ThreadStl { } #if TD_WINDOWS - using id = HANDLE; + using id = DWORD; #else using id = std::thread::id; #endif @@ -81,7 +84,12 @@ class ThreadStl { if (static_cast(mask) != mask) { return Status::Error("Invalid thread affinity mask specified"); } - if (SetThreadAffinityMask(thread_id, static_cast(mask))) { + auto handle = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, thread_id); + if (handle == nullptr) { + return Status::Error("Failed to access thread"); + } + NativeFd thread_handle(handle); + if (SetThreadAffinityMask(thread_handle.fd(), static_cast(mask))) { return Status::OK(); } return OS_ERROR("Failed to set thread affinity mask"); @@ -95,9 +103,14 @@ class ThreadStl { DWORD_PTR process_mask = 0; DWORD_PTR system_mask = 0; if (GetProcessAffinityMask(GetCurrentProcess(), &process_mask, &system_mask)) { - auto result = SetThreadAffinityMask(thread_id, process_mask); + auto handle = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, thread_id); + if (handle == nullptr) { + return 0; + } + NativeFd thread_handle(handle); + auto result = SetThreadAffinityMask(thread_handle.fd(), process_mask); if (result != 0 && result != process_mask) { - SetThreadAffinityMask(thread_id, result); + SetThreadAffinityMask(thread_handle.fd(), result); } return result; } @@ -117,7 +130,7 @@ class ThreadStl { namespace this_thread_stl { #if TD_WINDOWS inline ThreadStl::id get_id() { - return GetCurrentThread(); + return GetCurrentThreadId(); } #else using std::this_thread::get_id; diff --git a/tdutils/test/port.cpp b/tdutils/test/port.cpp index 79a41596c..9287dae0b 100644 --- a/tdutils/test/port.cpp +++ b/tdutils/test/port.cpp @@ -289,19 +289,20 @@ TEST(Port, EventFdAndSignals) { TEST(Port, ThreadAffinityMask) { auto thread_id = td::this_thread::get_id(); auto old_mask = td::thread::get_affinity_mask(thread_id); - LOG(INFO) << "Initial thread affinity mask: " << old_mask; + LOG(INFO) << "Initial thread " << thread_id << " affinity mask: " << old_mask; for (size_t i = 0; i < 64; i++) { auto mask = td::thread::get_affinity_mask(thread_id); LOG(INFO) << mask; auto result = td::thread::set_affinity_mask(thread_id, static_cast(1) << i); - LOG(INFO) << i << ": " << result; - mask = td::thread::get_affinity_mask(thread_id); - LOG(INFO) << mask; + LOG(INFO) << i << ": " << result << ' ' << td::thread::get_affinity_mask(thread_id); if (i <= 1) { td::thread thread([] { - auto mask = td::thread::get_affinity_mask(td::this_thread::get_id()); - LOG(INFO) << "New thread affinity mask: " << mask; + auto thread_id = td::this_thread::get_id(); + auto mask = td::thread::get_affinity_mask(thread_id); + LOG(INFO) << "New thread " << thread_id << " affinity mask: " << mask; + auto result = td::thread::set_affinity_mask(thread_id, 1); + LOG(INFO) << "Thread " << thread_id << ": " << result << ' ' << td::thread::get_affinity_mask(thread_id); }); } } From b47fce0d958cf7c88abf6c29c952039f5da531cf Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 14:45:42 +0300 Subject: [PATCH 172/200] Support CPU affinity on FreeBSD. --- .../td/utils/port/detail/ThreadPthread.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index a6ed9fa67..50327f4ab 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -14,8 +14,14 @@ char disable_linker_warning_about_empty_file_thread_pthread_cpp TD_UNUSED; #include "td/utils/port/detail/skip_eintr.h" #include +#if TD_FREEBSD +#include +#endif #include #include +#if TD_FREEBSD +#include +#endif #if TD_FREEBSD || TD_OPENBSD || TD_NETBSD #include #endif @@ -96,8 +102,12 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at } Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { -#if TD_LINUX +#if TD_LINUX || TD_FREEBSD +#if TD_FREEBSD + cpuset_t cpuset; +#else cpu_set_t cpuset; +#endif CPU_ZERO(&cpuset); for (int j = 0; j < 64 && j < CPU_SETSIZE; j++) { if ((mask >> j) & 1) { @@ -105,7 +115,7 @@ Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { } } - auto res = skip_eintr([&] { return pthread_setaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); }); + auto res = skip_eintr([&] { return pthread_setaffinity_np(thread_id, sizeof(cpuset), &cpuset); }); if (res) { return OS_ERROR("Failed to set thread affinity mask"); } @@ -116,10 +126,14 @@ Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { } uint64 ThreadPthread::get_affinity_mask(id thread_id) { -#if TD_LINUX +#if TD_LINUX || TD_FREEBSD +#if TD_FREEBSD + cpuset_t cpuset; +#else cpu_set_t cpuset; +#endif CPU_ZERO(&cpuset); - auto res = skip_eintr([&] { return pthread_getaffinity_np(thread_id, sizeof(cpu_set_t), &cpuset); }); + auto res = skip_eintr([&] { return pthread_getaffinity_np(thread_id, sizeof(cpuset), &cpuset); }); if (res) { return 0; } From b8abc6c19e11aab54a95a508ced5aa17fb13b449 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 21:48:16 +0300 Subject: [PATCH 173/200] Support CPU affinity on NetBSD. --- .../td/utils/port/detail/ThreadPthread.cpp | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index 50327f4ab..493488435 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -12,6 +12,9 @@ char disable_linker_warning_about_empty_file_thread_pthread_cpp TD_UNUSED; #include "td/utils/misc.h" #include "td/utils/port/detail/skip_eintr.h" +#if TD_NETBSD +#include "td/utils/ScopeGuard.h" +#endif #include #if TD_FREEBSD @@ -120,6 +123,27 @@ Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { return OS_ERROR("Failed to set thread affinity mask"); } return Status::OK(); +#elif TD_NETBSD + cpuset_t *cpuset = cpuset_create(); + if (cpuset == nullptr) { + return OS_ERROR("Failed to create cpuset"); + } + SCOPE_EXIT { + cpuset_destroy(cpuset); + }; + for (int j = 0; j < 64; j++) { + if ((mask >> j) & 1) { + if (cpuset_set(j, cpuset) != 0) { + return OS_ERROR("Failed to set CPU identifier"); + } + } + } + + auto res = skip_eintr([&] { return pthread_setaffinity_np(thread_id, cpuset_size(cpuset), cpuset); }); + if (res) { + return OS_ERROR("Failed to set thread affinity mask"); + } + return Status::OK(); #else return Status::Error("Unsupported"); #endif @@ -145,6 +169,26 @@ uint64 ThreadPthread::get_affinity_mask(id thread_id) { } } return mask; +#elif TD_NETBSD + cpuset_t *cpuset = cpuset_create(); + if (cpuset == nullptr) { + return 0; + } + SCOPE_EXIT { + cpuset_destroy(cpuset); + }; + auto res = skip_eintr([&] { return pthread_getaffinity_np(thread_id, cpuset_size(cpuset), cpuset); }); + if (res) { + return 0; + } + + uint64 mask = 0; + for (int j = 0; j < 64; j++) { + if (cpuset_isset(j, cpuset) > 0) { + mask |= static_cast(1) << j; + } + } + return mask; #else return 0; #endif From 9bf5d5785188e4f011588b5402b8ad6b01c067e4 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 21:58:00 +0300 Subject: [PATCH 174/200] Add TD_HAVE_THREAD_AFFINITY macros. --- tdactor/td/actor/ConcurrentScheduler.cpp | 2 ++ tdutils/td/utils/port/detail/ThreadPthread.cpp | 2 ++ tdutils/td/utils/port/detail/ThreadPthread.h | 6 ++++++ tdutils/td/utils/port/detail/ThreadStl.h | 12 ++++++------ tdutils/test/port.cpp | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tdactor/td/actor/ConcurrentScheduler.cpp b/tdactor/td/actor/ConcurrentScheduler.cpp index bbfaba362..c904295ad 100644 --- a/tdactor/td/actor/ConcurrentScheduler.cpp +++ b/tdactor/td/actor/ConcurrentScheduler.cpp @@ -80,9 +80,11 @@ void ConcurrentScheduler::start() { #if TD_PORT_WINDOWS detail::Iocp::Guard iocp_guard(iocp_.get()); #endif +#if TD_HAVE_THREAD_AFFINITY if (thread_affinity_mask != 0) { thread::set_affinity_mask(this_thread::get_id(), thread_affinity_mask).ignore(); } +#endif while (!is_finished()) { sched->run(Timestamp::in(10)); } diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index 493488435..de399f903 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -104,6 +104,7 @@ int ThreadPthread::do_pthread_create(pthread_t *thread, const pthread_attr_t *at return pthread_create(thread, attr, start_routine, arg); } +#if TD_HAVE_THREAD_AFFINITY Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { #if TD_LINUX || TD_FREEBSD #if TD_FREEBSD @@ -193,6 +194,7 @@ uint64 ThreadPthread::get_affinity_mask(id thread_id) { return 0; #endif } +#endif namespace this_thread_pthread { ThreadPthread::id get_id() { diff --git a/tdutils/td/utils/port/detail/ThreadPthread.h b/tdutils/td/utils/port/detail/ThreadPthread.h index 88fea76d6..76f6bebe1 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.h +++ b/tdutils/td/utils/port/detail/ThreadPthread.h @@ -28,6 +28,10 @@ #endif #include +#if TD_LINUX || TD_FREEBSD || TD_NETBSD +#define TD_HAVE_THREAD_AFFINITY 1 +#endif + namespace td { namespace detail { @@ -70,9 +74,11 @@ class ThreadPthread { static void send_real_time_signal(id thread_id, int real_time_signal_number); +#if TD_HAVE_THREAD_AFFINITY static Status set_affinity_mask(id thread_id, uint64 mask); static uint64 get_affinity_mask(id thread_id); +#endif private: MovableValue is_inited_; diff --git a/tdutils/td/utils/port/detail/ThreadStl.h b/tdutils/td/utils/port/detail/ThreadStl.h index dd55a21ec..b5313a36c 100644 --- a/tdutils/td/utils/port/detail/ThreadStl.h +++ b/tdutils/td/utils/port/detail/ThreadStl.h @@ -25,6 +25,10 @@ #include #include +#if TD_WINDOWS +#define TD_HAVE_THREAD_AFFINITY 1 +#endif + namespace td { namespace detail { @@ -79,8 +83,8 @@ class ThreadStl { // not supported } +#if TD_HAVE_THREAD_AFFINITY static Status set_affinity_mask(id thread_id, uint64 mask) { -#if TD_WINDOWS if (static_cast(mask) != mask) { return Status::Error("Invalid thread affinity mask specified"); } @@ -93,13 +97,9 @@ class ThreadStl { return Status::OK(); } return OS_ERROR("Failed to set thread affinity mask"); -#else - return Status::Error("Unsupported"); -#endif } static uint64 get_affinity_mask(id thread_id) { -#if TD_WINDOWS DWORD_PTR process_mask = 0; DWORD_PTR system_mask = 0; if (GetProcessAffinityMask(GetCurrentProcess(), &process_mask, &system_mask)) { @@ -114,9 +114,9 @@ class ThreadStl { } return result; } -#endif return 0; } +#endif private: std::thread thread_; diff --git a/tdutils/test/port.cpp b/tdutils/test/port.cpp index 9287dae0b..b5c90fd75 100644 --- a/tdutils/test/port.cpp +++ b/tdutils/test/port.cpp @@ -285,7 +285,7 @@ TEST(Port, EventFdAndSignals) { #endif #endif -#if !TD_THREAD_UNSUPPORTED +#if TD_HAVE_THREAD_AFFINITY TEST(Port, ThreadAffinityMask) { auto thread_id = td::this_thread::get_id(); auto old_mask = td::thread::get_affinity_mask(thread_id); From e37f3c17af9b9dafdd4705ed68baad3dd68e1117 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 22:54:21 +0300 Subject: [PATCH 175/200] Fix warnings. --- tdutils/test/HashSet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tdutils/test/HashSet.cpp b/tdutils/test/HashSet.cpp index 07bc1ce81..cd577d69b 100644 --- a/tdutils/test/HashSet.cpp +++ b/tdutils/test/HashSet.cpp @@ -315,7 +315,7 @@ TEST(FlatHashMap, stress_test) { ASSERT_EQ(ref[key], tbl[key]); }); - add_step("reserve", 10, [&] { tbl.reserve(rnd() % max_table_size); }); + add_step("reserve", 10, [&] { tbl.reserve(static_cast(rnd() % max_table_size)); }); add_step("find", 1000, [&] { auto key = gen_key(); @@ -398,7 +398,7 @@ TEST(FlatHashSet, stress_test) { tbl.insert(key); }); - add_step("reserve", 10, [&] { tbl.reserve(rnd() % max_table_size); }); + add_step("reserve", 10, [&] { tbl.reserve(static_cast(rnd() % max_table_size)); }); add_step("find", 1000, [&] { auto key = gen_key(); From cb70993b90ce84c16dea07c347835addbff46a2c Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 17 Sep 2022 23:25:42 +0300 Subject: [PATCH 176/200] Fix buggy behavior of pthread_setaffinity_np/pthread_getaffinity_np on NetBSD. --- tdutils/td/utils/port/detail/ThreadPthread.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tdutils/td/utils/port/detail/ThreadPthread.cpp b/tdutils/td/utils/port/detail/ThreadPthread.cpp index de399f903..3fa0d1938 100644 --- a/tdutils/td/utils/port/detail/ThreadPthread.cpp +++ b/tdutils/td/utils/port/detail/ThreadPthread.cpp @@ -144,6 +144,9 @@ Status ThreadPthread::set_affinity_mask(id thread_id, uint64 mask) { if (res) { return OS_ERROR("Failed to set thread affinity mask"); } + if (get_affinity_mask(thread_id) != mask) { + return Status::Error("Failed to set exact thread affinity mask"); + } return Status::OK(); #else return Status::Error("Unsupported"); @@ -189,6 +192,13 @@ uint64 ThreadPthread::get_affinity_mask(id thread_id) { mask |= static_cast(1) << j; } } + if (mask == 0) { + // the mask wasn't set, all CPUs are allowed + auto proc_count = sysconf(_SC_NPROCESSORS_ONLN); + for (int j = 0; j < 64 && j < proc_count; j++) { + mask |= static_cast(1) << j; + } + } return mask; #else return 0; From 297594af7e254572338112b3792367c852c70ad7 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 18 Sep 2022 21:35:16 +0300 Subject: [PATCH 177/200] Use SqliteDb::destroy instead of plain unlink. --- td/telegram/TdDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 3cdbac1c7..f70ce8049 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -288,7 +288,7 @@ Status TdDb::init_sqlite(const TdParameters ¶meters, const DbKey &key, const bool use_dialog_db = parameters.use_message_db; bool use_message_db = parameters.use_message_db; if (!use_sqlite) { - unlink(sql_database_path).ignore(); + SqliteDb::destroy(sql_database_path).ignore(); return Status::OK(); } From 12a8a5dbda3275067e8d759bf9bdff5e8e13a1fe Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 18 Sep 2022 21:57:13 +0300 Subject: [PATCH 178/200] Fix error handling in ReadFeaturedStickerSetsQuery. --- td/telegram/StickersManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index adb7954b3..e53c0b0c7 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -994,9 +994,8 @@ class ReadFeaturedStickerSetsQuery final : public Td::ResultHandler { if (!G()->is_expected_error(status)) { LOG(ERROR) << "Receive error for ReadFeaturedStickerSetsQuery: " << status; } - for (int32 type = 0; type < MAX_STICKER_TYPE; type++) { - td_->stickers_manager_->reload_featured_sticker_sets(static_cast(type), true); - } + td_->stickers_manager_->reload_featured_sticker_sets(StickerType::Regular, true); + td_->stickers_manager_->reload_featured_sticker_sets(StickerType::CustomEmoji, true); } }; @@ -6798,6 +6797,7 @@ void StickersManager::on_get_featured_sticker_sets_failed(StickerType sticker_ty } void StickersManager::load_featured_sticker_sets(StickerType sticker_type, Promise &&promise) { + CHECK(sticker_type != StickerType::Mask); auto type = static_cast(sticker_type); if (td_->auth_manager_->is_bot()) { are_featured_sticker_sets_loaded_[type] = true; From fcdd1e01d56218cb18f068bee6112ad9f788193e Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 18 Sep 2022 22:09:57 +0300 Subject: [PATCH 179/200] Destroy SQLite database if wasn't authorized. --- td/telegram/TdDb.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index f70ce8049..b79a2d9cf 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -411,6 +411,11 @@ void TdDb::open_impl(TdParameters parameters, DbKey key, Promise config_pmc->external_init_finish(binlog); VLOG(td_init) << "Finish initialization of config PMC"; + if (parameters.use_file_db && binlog_pmc->get("auth").empty()) { + LOG(INFO) << "Destroy SQLite database, because wasn't authorized yet"; + SqliteDb::destroy(get_sqlite_path(parameters)).ignore(); + } + DbKey new_sqlite_key; DbKey old_sqlite_key; bool encrypt_sqlite = encrypt_binlog; From 91c54cc748a91969384a64fce8c0d46612de59e0 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 00:24:15 +0300 Subject: [PATCH 180/200] Move send_update_message_content out of update_message_content. --- td/telegram/MessagesManager.cpp | 34 +++++++++++++++++---------------- td/telegram/MessagesManager.h | 2 +- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e0532471b..e654a9929 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6967,9 +6967,10 @@ td_api::object_ptr MessagesManager::get_message_ my_user_id = td_->contacts_manager_->get_my_id(); peer_user_id = dialog_id.get_user_id(); } - reactions = transform(m->reactions->reactions_, [td = td_, my_user_id, peer_user_id](const MessageReaction &reaction) { - return reaction.get_message_reaction_object(td, my_user_id, peer_user_id); - }); + reactions = + transform(m->reactions->reactions_, [td = td_, my_user_id, peer_user_id](const MessageReaction &reaction) { + return reaction.get_message_reaction_object(td, my_user_id, peer_user_id); + }); } return td_api::make_object(m->view_count, m->forward_count, std::move(reply_info), @@ -15393,7 +15394,7 @@ void MessagesManager::on_update_sent_text_message(int64 random_id, m->is_content_secret = is_secret_message_content(m->ttl, MessageContentType::Text); } if (need_update) { - send_update_message_content(dialog_id, m, true, "on_update_sent_text_message"); + send_update_message_content(d, m, true, "on_update_sent_text_message"); if (m->message_id == d->last_message_id) { send_update_chat_last_message_impl(d, "on_update_sent_text_message"); } @@ -26287,9 +26288,12 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag auto content = get_message_content(td_, caption == nullptr ? FormattedText() : *caption, std::move(media), dialog_id, false, UserId(), nullptr, nullptr, "on_upload_message_media_success"); - if (update_message_content(dialog_id, m, std::move(content), true, true, true) && - m->message_id == d->last_message_id) { - send_update_chat_last_message_impl(d, "on_upload_message_media_success"); + bool need_send_update = update_message_content(dialog_id, m, std::move(content), true, true); + if (need_send_update) { + send_update_message_content(d, m, true, "on_upload_message_media_success"); + if (m->message_id == d->last_message_id) { + send_update_chat_last_message_impl(d, "on_upload_message_media_success"); + } } auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true); @@ -27391,8 +27395,10 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess bool need_send_update_message_content = m->edited_content->get_type() == MessageContentType::Photo && m->content->get_type() == MessageContentType::Photo; bool need_merge_files = pts != 0 && pts == m->last_edit_pts; - update_message_content(dialog_id, m, std::move(m->edited_content), need_send_update_message_content, - need_merge_files, true); + bool need_send_update = update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true); + if (need_send_update && need_send_update_message_content) { + send_update_message_content(dialog_id, m, true, "on_message_media_edited"); + } } else { LOG(INFO) << "Failed to edit " << message_id << " in " << dialog_id << ": " << result.error(); if (was_uploaded) { @@ -36363,8 +36369,9 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr } } - if (update_message_content(dialog_id, old_message, std::move(new_message->content), true, + if (update_message_content(dialog_id, old_message, std::move(new_message->content), message_id.is_yet_unsent() && new_message->edit_date == 0, is_message_in_dialog)) { + send_update_message_content(d, old_message, is_message_in_dialog, "update_message"); need_send_update = true; } @@ -36407,8 +36414,7 @@ bool MessagesManager::need_message_changed_warning(const Message *old_message) { } bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_message, - unique_ptr new_content, - bool need_send_update_message_content, bool need_merge_files, + unique_ptr new_content, bool need_merge_files, bool is_message_in_dialog) { bool is_content_changed = false; bool need_update = false; @@ -36480,10 +36486,6 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me } if (need_update) { - if (need_send_update_message_content) { - send_update_message_content(dialog_id, old_message, is_message_in_dialog, "update_message_content"); - } - auto file_ids = get_message_content_file_ids(old_content.get(), td_); if (!file_ids.empty()) { auto file_source_id = get_message_file_source_id(FullMessageId(dialog_id, old_message->message_id)); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 98ab7117c..abe9085a8 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2404,7 +2404,7 @@ class MessagesManager final : public Actor { static bool need_message_changed_warning(const Message *old_message); bool update_message_content(DialogId dialog_id, Message *old_message, unique_ptr new_content, - bool need_send_update_message_content, bool need_merge_files, bool is_message_in_dialog); + bool need_merge_files, bool is_message_in_dialog); void update_message_max_reply_media_timestamp(const Dialog *d, Message *m, bool need_send_update_message_content); From 51403c883cce49b58a03885c5dd4ceb991430b74 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 00:29:31 +0300 Subject: [PATCH 181/200] Avoid usage of send_update_message_content with dialog_id. --- td/telegram/MessagesManager.cpp | 14 ++++---------- td/telegram/MessagesManager.h | 2 -- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e654a9929..846c3db36 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -27376,7 +27376,9 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess // must not run getDifference CHECK(message_id.is_any_server()); - auto m = get_message({dialog_id, message_id}); + Dialog *d = get_dialog(dialog_id); + CHECK(d != nullptr); + auto m = get_message(d, message_id); if (m == nullptr || m->edit_generation != generation) { // message is already deleted or was edited again return; @@ -27397,7 +27399,7 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess bool need_merge_files = pts != 0 && pts == m->last_edit_pts; bool need_send_update = update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true); if (need_send_update && need_send_update_message_content) { - send_update_message_content(dialog_id, m, true, "on_message_media_edited"); + send_update_message_content(d, m, true, "on_message_media_edited"); } } else { LOG(INFO) << "Failed to edit " << message_id << " in " << dialog_id << ": " << result.error(); @@ -30787,14 +30789,6 @@ void MessagesManager::send_update_message_send_succeeded(Dialog *d, MessageId ol get_message_object(d->dialog_id, m, "send_update_message_send_succeeded"), old_message_id.get())); } -void MessagesManager::send_update_message_content(DialogId dialog_id, Message *m, bool is_message_in_dialog, - const char *source) { - Dialog *d = get_dialog(dialog_id); - LOG_CHECK(d != nullptr) << "Send updateMessageContent in unknown " << dialog_id << " from " << source - << " with load count " << loaded_dialogs_.count(dialog_id); - send_update_message_content(d, m, is_message_in_dialog, source); -} - void MessagesManager::send_update_message_content(const Dialog *d, Message *m, bool is_message_in_dialog, const char *source) { CHECK(d != nullptr); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index abe9085a8..f612c9294 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2477,8 +2477,6 @@ class MessagesManager final : public Actor { void send_update_message_send_succeeded(Dialog *d, MessageId old_message_id, const Message *m) const; - void send_update_message_content(DialogId dialog_id, Message *m, bool is_message_in_dialog, const char *source); - void send_update_message_content(const Dialog *d, Message *m, bool is_message_in_dialog, const char *source); void send_update_message_content_impl(DialogId dialog_id, const Message *m, const char *source) const; From 5cf248ae01d37ab99f07d13f5674aa5c33d1a99f Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 01:05:23 +0300 Subject: [PATCH 182/200] Call on_message_changed after send_update_message_content. --- td/telegram/MessagesManager.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 846c3db36..851b9936d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7187,6 +7187,7 @@ void MessagesManager::on_external_update_message_content(FullMessageId full_mess Message *m = get_message(d, full_message_id.get_message_id()); CHECK(m != nullptr); send_update_message_content(d, m, true, "on_external_update_message_content"); + // must not call on_message_changed, because the message itself wasn't changed if (m->message_id == d->last_message_id) { send_update_chat_last_message_impl(d, "on_external_update_message_content"); } @@ -15392,12 +15393,11 @@ void MessagesManager::on_update_sent_text_message(int64 random_id, "on_update_sent_text_message"); m->content = std::move(new_content); m->is_content_secret = is_secret_message_content(m->ttl, MessageContentType::Text); - } - if (need_update) { - send_update_message_content(d, m, true, "on_update_sent_text_message"); - if (m->message_id == d->last_message_id) { - send_update_chat_last_message_impl(d, "on_update_sent_text_message"); + + if (need_update) { + send_update_message_content(d, m, true, "on_update_sent_text_message"); } + on_message_changed(d, m, need_update, "on_update_sent_text_message"); } } @@ -26288,12 +26288,10 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag auto content = get_message_content(td_, caption == nullptr ? FormattedText() : *caption, std::move(media), dialog_id, false, UserId(), nullptr, nullptr, "on_upload_message_media_success"); - bool need_send_update = update_message_content(dialog_id, m, std::move(content), true, true); - if (need_send_update) { + bool need_update = update_message_content(dialog_id, m, std::move(content), true, true); + if (need_update) { send_update_message_content(d, m, true, "on_upload_message_media_success"); - if (m->message_id == d->last_message_id) { - send_update_chat_last_message_impl(d, "on_upload_message_media_success"); - } + on_message_changed(d, m, need_update, "on_upload_message_media_success"); } auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true); @@ -27397,9 +27395,10 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess bool need_send_update_message_content = m->edited_content->get_type() == MessageContentType::Photo && m->content->get_type() == MessageContentType::Photo; bool need_merge_files = pts != 0 && pts == m->last_edit_pts; - bool need_send_update = update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true); - if (need_send_update && need_send_update_message_content) { + bool need_update = update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true); + if (need_update && need_send_update_message_content) { send_update_message_content(d, m, true, "on_message_media_edited"); + on_message_changed(d, m, need_update, "on_message_media_edited"); } } else { LOG(INFO) << "Failed to edit " << message_id << " in " << dialog_id << ": " << result.error(); From 8d0cb5b82d9a133f72a9552e18fdf403f7b09aab Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 01:12:20 +0300 Subject: [PATCH 183/200] Return is_content_changed from update_message_content. --- td/telegram/MessagesManager.cpp | 28 ++++++++++++++++++++-------- td/telegram/MessagesManager.h | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 851b9936d..80f946f52 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -26288,9 +26288,12 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag auto content = get_message_content(td_, caption == nullptr ? FormattedText() : *caption, std::move(media), dialog_id, false, UserId(), nullptr, nullptr, "on_upload_message_media_success"); - bool need_update = update_message_content(dialog_id, m, std::move(content), true, true); + bool is_content_changed = false; + bool need_update = update_message_content(dialog_id, m, std::move(content), true, true, is_content_changed); if (need_update) { send_update_message_content(d, m, true, "on_upload_message_media_success"); + } + if (is_content_changed || need_update) { on_message_changed(d, m, need_update, "on_upload_message_media_success"); } @@ -27395,10 +27398,16 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess bool need_send_update_message_content = m->edited_content->get_type() == MessageContentType::Photo && m->content->get_type() == MessageContentType::Photo; bool need_merge_files = pts != 0 && pts == m->last_edit_pts; - bool need_update = update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true); - if (need_update && need_send_update_message_content) { - send_update_message_content(d, m, true, "on_message_media_edited"); - on_message_changed(d, m, need_update, "on_message_media_edited"); + bool is_content_changed = false; + bool need_update = + update_message_content(dialog_id, m, std::move(m->edited_content), need_merge_files, true, is_content_changed); + if (need_send_update_message_content) { + if (need_update) { + send_update_message_content(d, m, true, "on_message_media_edited"); + } + if (is_content_changed || need_update) { + on_message_changed(d, m, need_update, "on_message_media_edited"); + } } } else { LOG(INFO) << "Failed to edit " << message_id << " in " << dialog_id << ": " << result.error(); @@ -36362,8 +36371,10 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr } } + bool is_content_changed = false; if (update_message_content(dialog_id, old_message, std::move(new_message->content), - message_id.is_yet_unsent() && new_message->edit_date == 0, is_message_in_dialog)) { + message_id.is_yet_unsent() && new_message->edit_date == 0, is_message_in_dialog, + is_content_changed)) { send_update_message_content(d, old_message, is_message_in_dialog, "update_message"); need_send_update = true; } @@ -36408,9 +36419,10 @@ bool MessagesManager::need_message_changed_warning(const Message *old_message) { bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_message, unique_ptr new_content, bool need_merge_files, - bool is_message_in_dialog) { - bool is_content_changed = false; + bool is_message_in_dialog, bool &is_content_changed) { + is_content_changed = false; bool need_update = false; + unique_ptr &old_content = old_message->content; MessageContentType old_content_type = old_content->get_type(); MessageContentType new_content_type = new_content->get_type(); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index f612c9294..984e68771 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2404,7 +2404,7 @@ class MessagesManager final : public Actor { static bool need_message_changed_warning(const Message *old_message); bool update_message_content(DialogId dialog_id, Message *old_message, unique_ptr new_content, - bool need_merge_files, bool is_message_in_dialog); + bool need_merge_files, bool is_message_in_dialog, bool &is_content_changed); void update_message_max_reply_media_timestamp(const Dialog *d, Message *m, bool need_send_update_message_content); From 618bface99ea11ccf373ce6f928c317c34c47ab8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 11:15:13 +0300 Subject: [PATCH 184/200] Save voice message to database when it is recognized. --- td/telegram/MessagesManager.cpp | 9 +++++++++ td/telegram/MessagesManager.h | 2 ++ td/telegram/VoiceNotesManager.cpp | 13 +++++++++++-- td/telegram/VoiceNotesManager.h | 2 ++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 80f946f52..d6fe0252a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7193,6 +7193,15 @@ void MessagesManager::on_external_update_message_content(FullMessageId full_mess } } +void MessagesManager::on_update_message_content(FullMessageId full_message_id) { + Dialog *d = get_dialog(full_message_id.get_dialog_id()); + CHECK(d != nullptr); + Message *m = get_message(d, full_message_id.get_message_id()); + CHECK(m != nullptr); + send_update_message_content(d, m, true, "on_update_message_content"); + on_message_changed(d, m, true, "on_update_message_content"); +} + bool MessagesManager::update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source) { LOG_CHECK(m != nullptr) << source; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 984e68771..c305e56c2 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -366,6 +366,8 @@ class MessagesManager final : public Actor { void on_external_update_message_content(FullMessageId full_message_id); + void on_update_message_content(FullMessageId full_message_id); + void on_read_channel_inbox(ChannelId channel_id, MessageId max_message_id, int32 server_unread_count, int32 pts, const char *source); diff --git a/td/telegram/VoiceNotesManager.cpp b/td/telegram/VoiceNotesManager.cpp index 6ca890556..0fa497a37 100644 --- a/td/telegram/VoiceNotesManager.cpp +++ b/td/telegram/VoiceNotesManager.cpp @@ -182,7 +182,7 @@ FileId VoiceNotesManager::on_get_voice_note(unique_ptr new_voice_note v->transcription_id = new_voice_note->transcription_id; v->text = std::move(new_voice_note->text); v->last_transcription_error = Status::OK(); - on_voice_note_transcription_updated(file_id); + on_voice_note_transcription_completed(file_id); } } @@ -316,7 +316,7 @@ void VoiceNotesManager::on_voice_note_transcribed(FileId file_id, string &&text, auto promises = std::move(it->second); speech_recognition_queries_.erase(it); - on_voice_note_transcription_updated(file_id); + on_voice_note_transcription_completed(file_id); set_promises(promises); } else { if (is_changed) { @@ -386,6 +386,15 @@ void VoiceNotesManager::on_voice_note_transcription_updated(FileId file_id) { } } +void VoiceNotesManager::on_voice_note_transcription_completed(FileId file_id) { + auto it = voice_note_messages_.find(file_id); + if (it != voice_note_messages_.end()) { + for (const auto &full_message_id : it->second) { + td_->messages_manager_->on_update_message_content(full_message_id); + } + } +} + void VoiceNotesManager::rate_speech_recognition(FullMessageId full_message_id, bool is_good, Promise &&promise) { if (!td_->messages_manager_->have_message_force(full_message_id, "rate_speech_recognition")) { return promise.set_error(Status::Error(400, "Message not found")); diff --git a/td/telegram/VoiceNotesManager.h b/td/telegram/VoiceNotesManager.h index ce5fb3f55..e77b94f57 100644 --- a/td/telegram/VoiceNotesManager.h +++ b/td/telegram/VoiceNotesManager.h @@ -100,6 +100,8 @@ class VoiceNotesManager final : public Actor { void on_voice_note_transcription_updated(FileId file_id); + void on_voice_note_transcription_completed(FileId file_id); + void tear_down() final; Td *td_; From bb6fc999f841e2d39018da848e7ac5cb573c9e81 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 16:19:59 +0300 Subject: [PATCH 185/200] Add on_message_notification_changed function. --- td/telegram/MessagesManager.cpp | 49 +++++++++++++++++++-------------- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d6fe0252a..c39043a26 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -34836,27 +34836,8 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq try_add_active_live_location(dialog_id, m); } change_message_files(dialog_id, m, old_file_ids); - if (need_send_update && m->notification_id.is_valid() && is_message_notification_active(d, m)) { - auto &group_info = get_notification_group_info(d, m); - if (group_info.group_id.is_valid()) { - send_closure_later( - G()->notification_manager(), &NotificationManager::edit_notification, group_info.group_id, - m->notification_id, - create_new_message_notification( - m->message_id, is_message_preview_enabled(d, m, is_from_mention_notification_group(m)))); - } - } - if (need_send_update && m->is_pinned && d->pinned_message_notification_message_id.is_valid() && - d->mention_notification_group.group_id.is_valid()) { - auto pinned_message = get_message_force(d, d->pinned_message_notification_message_id, "after update_message"); - if (pinned_message != nullptr && pinned_message->notification_id.is_valid() && - is_message_notification_active(d, pinned_message) && - get_message_content_pinned_message_id(pinned_message->content.get()) == message_id) { - send_closure_later( - G()->notification_manager(), &NotificationManager::edit_notification, - d->mention_notification_group.group_id, pinned_message->notification_id, - create_new_message_notification(pinned_message->message_id, is_message_preview_enabled(d, m, true))); - } + if (need_send_update) { + on_message_notification_changed(d, m, source); } update_message_count_by_index(d, -1, old_index_mask & ~new_index_mask); update_message_count_by_index(d, +1, new_index_mask & ~old_index_mask); @@ -35586,6 +35567,32 @@ void MessagesManager::on_message_changed(const Dialog *d, const Message *m, bool } } +void MessagesManager::on_message_notification_changed(Dialog *d, const Message *m, const char *source) { + CHECK(d != nullptr); + CHECK(m != nullptr); + if (m->notification_id.is_valid() && is_message_notification_active(d, m)) { + auto &group_info = get_notification_group_info(d, m); + if (group_info.group_id.is_valid()) { + send_closure_later(G()->notification_manager(), &NotificationManager::edit_notification, group_info.group_id, + m->notification_id, + create_new_message_notification( + m->message_id, is_message_preview_enabled(d, m, is_from_mention_notification_group(m)))); + } + } + if (m->is_pinned && d->pinned_message_notification_message_id.is_valid() && + d->mention_notification_group.group_id.is_valid()) { + auto pinned_message = get_message_force(d, d->pinned_message_notification_message_id, "after update_message"); + if (pinned_message != nullptr && pinned_message->notification_id.is_valid() && + is_message_notification_active(d, pinned_message) && + get_message_content_pinned_message_id(pinned_message->content.get()) == m->message_id) { + send_closure_later( + G()->notification_manager(), &NotificationManager::edit_notification, d->mention_notification_group.group_id, + pinned_message->notification_id, + create_new_message_notification(pinned_message->message_id, is_message_preview_enabled(d, m, true))); + } + } +} + void MessagesManager::add_message_to_database(const Dialog *d, const Message *m, const char *source) { if (!G()->parameters().use_message_db) { return; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c305e56c2..b76e2b043 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2358,6 +2358,8 @@ class MessagesManager final : public Actor { void on_message_changed(const Dialog *d, const Message *m, bool need_send_update, const char *source); + void on_message_notification_changed(Dialog *d, const Message *m, const char *source); + bool need_delete_file(FullMessageId full_message_id, FileId file_id) const; bool need_delete_message_files(DialogId dialog_id, const Message *m) const; From b9bd024969c51b2962c56ab14d59d4fb3facd221 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 16:26:56 +0300 Subject: [PATCH 186/200] Update message notifications after external changes of message content. --- td/telegram/MessagesManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c39043a26..493715216 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7191,6 +7191,7 @@ void MessagesManager::on_external_update_message_content(FullMessageId full_mess if (m->message_id == d->last_message_id) { send_update_chat_last_message_impl(d, "on_external_update_message_content"); } + on_message_notification_changed(d, m, "on_external_update_message_content"); } void MessagesManager::on_update_message_content(FullMessageId full_message_id) { @@ -7200,6 +7201,7 @@ void MessagesManager::on_update_message_content(FullMessageId full_message_id) { CHECK(m != nullptr); send_update_message_content(d, m, true, "on_update_message_content"); on_message_changed(d, m, true, "on_update_message_content"); + on_message_notification_changed(d, m, "on_update_message_content"); } bool MessagesManager::update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, From 06e1ebf809a7bc09bfe6808fe6f2001924ab37f5 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 16:34:28 +0300 Subject: [PATCH 187/200] Add check just in case. --- td/telegram/MessagesManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 493715216..90c0bfd38 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24528,6 +24528,7 @@ Result> MessagesManager::get_mess FlatHashSet all_available_reactions; for (const auto &reaction : available_reactions.reactions_) { + CHECK(!reaction.empty()); all_available_reactions.insert(reaction); } From 275ee280d28a92f71c99170cbcea9abbb7accd8e Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 18:17:51 +0300 Subject: [PATCH 188/200] Use thread-local EVP_MD_CTX in OpenSSL 3.0. --- tdutils/td/utils/crypto.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index 0f859acd7..cca3215f4 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -721,15 +721,22 @@ void AesCtrState::decrypt(Slice from, MutableSlice to) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) { - EVP_MD_CTX *ctx = EVP_MD_CTX_new(); - LOG_IF(FATAL, ctx == nullptr); + static TD_THREAD_LOCAL EVP_MD_CTX *ctx; + if (unlikely(ctx == nullptr)) { + ctx = EVP_MD_CTX_new(); + LOG_IF(FATAL, ctx == nullptr); + detail::add_thread_local_destructor(create_destructor([] { + EVP_MD_CTX_free(ctx); + ctx = nullptr; + })); + } int res = EVP_DigestInit_ex(ctx, evp_md, nullptr); LOG_IF(FATAL, res != 1); res = EVP_DigestUpdate(ctx, data.ubegin(), data.size()); LOG_IF(FATAL, res != 1); res = EVP_DigestFinal_ex(ctx, output.ubegin(), nullptr); LOG_IF(FATAL, res != 1); - EVP_MD_CTX_free(ctx); + EVP_MD_CTX_reset(ctx); } static void init_thread_local_evp_md(const EVP_MD *&evp_md, const char *algorithm) { From 74879d97262b311cd6f1413af9d174946608b287 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Sep 2022 21:33:23 +0300 Subject: [PATCH 189/200] Move PerfWarningTimer to SessionConnection::do_flush. --- td/mtproto/RawConnection.cpp | 2 -- td/mtproto/SessionConnection.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/td/mtproto/RawConnection.cpp b/td/mtproto/RawConnection.cpp index 776ded6f2..c7b196eaa 100644 --- a/td/mtproto/RawConnection.cpp +++ b/td/mtproto/RawConnection.cpp @@ -25,7 +25,6 @@ #include "td/utils/SliceBuilder.h" #include "td/utils/Status.h" #include "td/utils/StorerBase.h" -#include "td/utils/Timer.h" #include #include @@ -248,7 +247,6 @@ class RawConnectionDefault final : public RawConnection { if (has_error_) { return Status::Error("Connection has already failed"); } - PerfWarningTimer timer("RawConnection::do_flush", 0.01); sync_with_poll(socket_fd_); // read/write diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index eb6b35966..63e785b37 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -26,6 +26,7 @@ #include "td/utils/ScopeGuard.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Time.h" +#include "td/utils/Timer.h" #include "td/utils/tl_parsers.h" #include "td/utils/TlDowncastHelper.h" @@ -1027,6 +1028,7 @@ Status SessionConnection::do_flush() { << connected_flag_ << ' ' << is_main_ << ' ' << need_destroy_auth_key_ << ' ' << sent_destroy_auth_key_ << ' ' << callback_ << ' ' << (Time::now() - created_at_) << ' ' << (Time::now() - last_read_at_); + PerfWarningTimer timer("SessionConnection::do_flush", 0.01); CHECK(state_ != Closed); if (state_ == Init) { TRY_STATUS(init()); From ee381ecbb5f5cfabb08398563ebf12a8a7168210 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 20 Sep 2022 00:26:22 +0300 Subject: [PATCH 190/200] Avoid force_reuse even for message photos. --- td/telegram/MessageContent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 0447fba86..028a8db73 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2080,7 +2080,7 @@ Result get_input_message_content( auto input_message = static_cast(input_message_content.get()); auto file_type = input_message->disable_content_type_detection_ ? FileType::DocumentAsFile : FileType::Document; r_file_id = - td->file_manager_->get_input_file_id(file_type, input_message->document_, dialog_id, false, is_secret, true); + td->file_manager_->get_input_file_id(file_type, input_message->document_, dialog_id, false, is_secret); input_thumbnail = std::move(input_message->thumbnail_); break; } From 097f3d42e1b053374c8a2d16c32ea89ba4cb49d8 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 20 Sep 2022 02:02:28 +0300 Subject: [PATCH 191/200] Fix error code in on_upload_error/on_download_error. --- td/telegram/MessagesManager.cpp | 2 +- td/telegram/files/FileGenerateManager.cpp | 6 ++--- td/telegram/files/FileLoadManager.cpp | 4 +-- td/telegram/files/FileLoader.cpp | 2 +- td/telegram/files/FileManager.cpp | 30 +++++++++++++---------- td/telegram/files/FileUploader.cpp | 2 +- td/telegram/files/PartsManager.cpp | 2 +- 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 90c0bfd38..0f199fe81 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9052,7 +9052,7 @@ void MessagesManager::on_upload_media_error(FileId file_id, Status status) { bool is_edit = full_message_id.get_message_id().is_any_server(); if (is_edit) { - fail_edit_message_media(full_message_id, Status::Error(status.code() > 0 ? status.code() : 500, status.message())); + fail_edit_message_media(full_message_id, std::move(status)); } else { fail_send_message(full_message_id, std::move(status)); } diff --git a/td/telegram/files/FileGenerateManager.cpp b/td/telegram/files/FileGenerateManager.cpp index 00f7e1507..b823f74c3 100644 --- a/td/telegram/files/FileGenerateManager.cpp +++ b/td/telegram/files/FileGenerateManager.cpp @@ -258,7 +258,7 @@ class WebFileDownloadGenerateActor final : public FileGenerateActor { } void hangup_shared() final { - on_error(Status::Error(1, "Canceled")); + on_error(Status::Error(-1, "Canceled")); } }; @@ -328,7 +328,7 @@ class FileExternalGenerateActor final : public FileGenerateActor { static_cast(query_id_), generate_location_.original_path_, path_, generate_location_.conversion_)); } void hangup() final { - check_status(Status::Error(1, "Canceled")); + check_status(Status::Error(-1, "Canceled")); } Status do_file_generate_write_part(int64 offset, const string &data) { @@ -365,7 +365,7 @@ class FileExternalGenerateActor final : public FileGenerateActor { void check_status(Status status, Promise<> promise = Promise<>()) { if (promise) { - if (status.is_ok() || status.code() == 1) { + if (status.is_ok() || status.code() == -1) { promise.set_value(Unit()); } else { promise.set_error(Status::Error(400, status.message())); diff --git a/td/telegram/files/FileLoadManager.cpp b/td/telegram/files/FileLoadManager.cpp index e7656d2d1..9549cba3f 100644 --- a/td/telegram/files/FileLoadManager.cpp +++ b/td/telegram/files/FileLoadManager.cpp @@ -156,7 +156,7 @@ void FileLoadManager::cancel(QueryId id) { if (it == query_id_to_node_id_.end()) { return; } - on_error_impl(it->second, Status::Error(1, "Canceled")); + on_error_impl(it->second, Status::Error(-1, "Canceled")); } void FileLoadManager::update_local_file_location(QueryId id, const LocalFileLocation &local) { if (stop_flag_) { @@ -298,7 +298,7 @@ void FileLoadManager::on_error_impl(NodeId node_id, Status status) { void FileLoadManager::hangup_shared() { auto node_id = get_link_token(); - on_error_impl(node_id, Status::Error(1, "Canceled")); + on_error_impl(node_id, Status::Error(-1, "Canceled")); } void FileLoadManager::loop() { diff --git a/td/telegram/files/FileLoader.cpp b/td/telegram/files/FileLoader.cpp index 0c7c22dc3..1ac07c10b 100644 --- a/td/telegram/files/FileLoader.cpp +++ b/td/telegram/files/FileLoader.cpp @@ -153,7 +153,7 @@ void FileLoader::loop() { } auto status = do_loop(); if (status.is_error()) { - if (status.code() == 1) { + if (status.code() == -1) { return; } on_error(std::move(status)); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index a8e928289..d389de86c 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -2193,7 +2193,7 @@ void FileManager::download(FileId file_id, std::shared_ptr cal if (!node) { LOG(INFO) << "File " << file_id << " not found"; if (callback) { - callback->on_download_error(file_id, Status::Error("File not found")); + callback->on_download_error(file_id, Status::Error(400, "File not found")); } return; } @@ -2220,7 +2220,7 @@ void FileManager::download(FileId file_id, std::shared_ptr cal if (!file_view.can_download_from_server() && !file_view.can_generate()) { LOG(INFO) << "File " << file_id << " can't be downloaded"; if (callback) { - callback->on_download_error(file_id, Status::Error("Can't download or generate file")); + callback->on_download_error(file_id, Status::Error(400, "Can't download or generate file")); } return; } @@ -2439,7 +2439,7 @@ class FileManager::ForceUploadActor final : public Actor { if (callback_.empty()) { return; } - send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, Status::Error("Canceled")); + send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, Status::Error(200, "Canceled")); } private: @@ -2517,7 +2517,7 @@ class FileManager::ForceUploadActor final : public Actor { void tear_down() final { if (callback_) { - callback_->on_upload_error(file_id_, Status::Error("Canceled")); + callback_->on_upload_error(file_id_, Status::Error(200, "Canceled")); } } }; @@ -2536,7 +2536,7 @@ void FileManager::resume_upload(FileId file_id, vector bad_parts, std::shar if (!node) { LOG(INFO) << "File " << file_id << " not found"; if (callback) { - callback->on_upload_error(file_id, Status::Error("File not found")); + callback->on_upload_error(file_id, Status::Error(400, "File not found")); } return; } @@ -2545,7 +2545,7 @@ void FileManager::resume_upload(FileId file_id, vector bad_parts, std::shar if (node->last_successful_force_reupload_time_ >= Time::now() - 60) { LOG(INFO) << "Recently reuploaded file " << file_id << ", do not try again"; if (callback) { - callback->on_upload_error(file_id, Status::Error("Failed to reupload file")); + callback->on_upload_error(file_id, Status::Error(400, "Failed to reupload file")); } return; } @@ -2585,8 +2585,8 @@ void FileManager::resume_upload(FileId file_id, vector bad_parts, std::shar if (!file_view.has_local_location() && !file_view.has_generate_location() && !file_view.has_alive_remote_location()) { LOG(INFO) << "File " << file_id << " can't be uploaded"; if (callback) { - callback->on_upload_error(file_id, - Status::Error("Need full local (or generate, or inactive remote) location for upload")); + callback->on_upload_error( + file_id, Status::Error(400, "Need full local (or generate, or inactive remote) location for upload")); } return; } @@ -2594,7 +2594,7 @@ void FileManager::resume_upload(FileId file_id, vector bad_parts, std::shar (!file_view.has_local_location() && file_view.can_download_from_server())) { // TODO if (callback) { - callback->on_upload_error(file_id, Status::Error("Failed to upload thumbnail without local location")); + callback->on_upload_error(file_id, Status::Error(400, "Failed to upload thumbnail without local location")); } return; } @@ -3854,9 +3854,13 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act return; } - if (status.code() != 1 && !G()->close_flag()) { - LOG(WARNING) << "Failed to " << type << " file " << node->main_file_id_ << " of type " << FileView(node).get_type() - << ": " << status; + if (G()->close_flag() && status.code() < 400) { + status = Global::request_aborted_error(); + } else { + if (status.code() != -1) { + LOG(WARNING) << "Failed to " << type << " file " << node->main_file_id_ << " of type " + << FileView(node).get_type() << ": " << status; + } if (status.code() == 0) { // Remove partial locations if (node->local_.type() == LocalFileLocation::Type::Partial && @@ -3872,8 +3876,8 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act } } node->delete_partial_remote_location(); - status = Status::Error(400, status.message()); } + status = Status::Error(400, status.message()); } // Stop everything on error diff --git a/td/telegram/files/FileUploader.cpp b/td/telegram/files/FileUploader.cpp index ff6360c29..fbda0d6bd 100644 --- a/td/telegram/files/FileUploader.cpp +++ b/td/telegram/files/FileUploader.cpp @@ -239,7 +239,7 @@ Status FileUploader::generate_iv_map() { Status FileUploader::before_start_parts() { auto status = acquire_fd(); if (status.is_error() && !local_is_ready_) { - return Status::Error(1, "Can't open temporary file"); + return Status::Error(-1, "Can't open temporary file"); } return status; } diff --git a/td/telegram/files/PartsManager.cpp b/td/telegram/files/PartsManager.cpp index 3e6a7c8af..ffe9890da 100644 --- a/td/telegram/files/PartsManager.cpp +++ b/td/telegram/files/PartsManager.cpp @@ -281,7 +281,7 @@ Result PartsManager::start_part() { update_first_empty_part(); auto part_i = first_streaming_empty_part_; if (known_prefix_flag_ && part_i >= static_cast(known_prefix_size_ / part_size_)) { - return Status::Error(1, "Wait for prefix to be known"); + return Status::Error(-1, "Wait for prefix to be known"); } if (part_i == part_count_) { if (unknown_size_flag_) { From bed08625f0129ac2fcda3e90a778be0a78db2a3b Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 20 Sep 2022 17:11:15 +0300 Subject: [PATCH 192/200] Improve error logging. --- tdnet/td/net/SslStream.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tdnet/td/net/SslStream.cpp b/tdnet/td/net/SslStream.cpp index ca602cd7e..2888bd1f5 100644 --- a/tdnet/td/net/SslStream.cpp +++ b/tdnet/td/net/SslStream.cpp @@ -383,7 +383,13 @@ class SslStreamImpl { Result write(Slice slice) { clear_openssl_errors("Before SslFd::write"); + auto start_time = Time::now(); auto size = SSL_write(ssl_handle_.get(), slice.data(), static_cast(slice.size())); + auto elapsed_time = Time::now() - start_time; + if (elapsed_time >= 0.001) { + LOG(ERROR) << "SSL_write of size " << slice.size() << " took " << elapsed_time << " seconds and returned " << size + << ' ' << SSL_get_error(ssl_handle_.get(), size); + } if (size <= 0) { return process_ssl_error(size); } @@ -395,8 +401,9 @@ class SslStreamImpl { auto start_time = Time::now(); auto size = SSL_read(ssl_handle_.get(), slice.data(), static_cast(slice.size())); auto elapsed_time = Time::now() - start_time; - if (elapsed_time >= 0.01) { - LOG(ERROR) << "SSL_read took " << elapsed_time << " seconds and returned " << size; + if (elapsed_time >= 0.001) { + LOG(ERROR) << "SSL_read took " << elapsed_time << " seconds and returned " << size << ' ' + << SSL_get_error(ssl_handle_.get(), size); } if (size <= 0) { return process_ssl_error(size); From 3a579dd5cb591cabc2f15bbf797c6d717a872b3d Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 20 Sep 2022 17:46:10 +0300 Subject: [PATCH 193/200] Improve warning on long RawConnection::flush. --- td/mtproto/RawConnection.cpp | 16 ++++++++++++---- td/mtproto/RawConnection.h | 4 ++-- td/mtproto/SessionConnection.cpp | 21 ++++++++++++++++----- td/mtproto/SessionConnection.h | 3 +++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/td/mtproto/RawConnection.cpp b/td/mtproto/RawConnection.cpp index c7b196eaa..d69211e7b 100644 --- a/td/mtproto/RawConnection.cpp +++ b/td/mtproto/RawConnection.cpp @@ -49,11 +49,13 @@ class RawConnectionDefault final : public RawConnection { bool can_send() const final { return transport_->can_write(); } + TransportType get_transport_type() const final { return transport_->get_type(); } - void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, - uint64 quick_ack_token) final { + + size_t send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, + uint64 quick_ack_token) final { PacketInfo info; info.version = 2; info.no_crypto_flag = false; @@ -76,7 +78,9 @@ class RawConnectionDefault final : public RawConnection { } } + auto packet_size = packet.size(); transport_->write(std::move(packet), use_quick_ack); + return packet_size; } uint64 send_no_crypto(const Storer &storer) final { @@ -280,11 +284,13 @@ class RawConnectionHttp final : public RawConnection { bool can_send() const final { return mode_ == Send; } + TransportType get_transport_type() const final { return mtproto::TransportType{mtproto::TransportType::Http, 0, mtproto::ProxySecret()}; } - void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, - uint64 quick_ack_token) final { + + size_t send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, + uint64 quick_ack_token) final { PacketInfo info; info.version = 2; info.no_crypto_flag = false; @@ -295,7 +301,9 @@ class RawConnectionHttp final : public RawConnection { auto packet = BufferWriter{Transport::write(storer, auth_key, &info), 0, 0}; Transport::write(storer, auth_key, &info, packet.as_slice()); + auto packet_size = packet.size(); send_packet(packet.as_buffer_slice()); + return packet_size; } uint64 send_no_crypto(const Storer &storer) final { diff --git a/td/mtproto/RawConnection.h b/td/mtproto/RawConnection.h index be63533dd..6582d46e7 100644 --- a/td/mtproto/RawConnection.h +++ b/td/mtproto/RawConnection.h @@ -48,8 +48,8 @@ class RawConnection { virtual bool can_send() const = 0; virtual TransportType get_transport_type() const = 0; - virtual void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, - uint64 quick_ack_token) = 0; + virtual size_t send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key, + uint64 quick_ack_token) = 0; virtual uint64 send_no_crypto(const Storer &storer) = 0; virtual PollableFdInfo &get_poll_info() = 0; diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index 63e785b37..bb7b6670c 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -26,7 +26,6 @@ #include "td/utils/ScopeGuard.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Time.h" -#include "td/utils/Timer.h" #include "td/utils/tl_parsers.h" #include "td/utils/TlDowncastHelper.h" @@ -718,6 +717,7 @@ Status SessionConnection::on_quick_ack(uint64 quick_ack_token) { void SessionConnection::on_read(size_t size) { last_read_at_ = Time::now_cached(); + last_read_size_ += size; } SessionConnection::SessionConnection(Mode mode, unique_ptr raw_connection, AuthData *auth_data) @@ -768,8 +768,9 @@ void SessionConnection::do_close(Status status) { void SessionConnection::send_crypto(const Storer &storer, uint64 quick_ack_token) { CHECK(state_ != Closed); - raw_connection_->send_crypto(storer, auth_data_->get_session_id(), auth_data_->get_server_salt(Time::now_cached()), - auth_data_->get_auth_key(), quick_ack_token); + last_write_size_ += raw_connection_->send_crypto(storer, auth_data_->get_session_id(), + auth_data_->get_server_salt(Time::now_cached()), + auth_data_->get_auth_key(), quick_ack_token); } Result SessionConnection::send_query(BufferSlice buffer, bool gzip_flag, int64 message_id, @@ -1028,7 +1029,6 @@ Status SessionConnection::do_flush() { << connected_flag_ << ' ' << is_main_ << ' ' << need_destroy_auth_key_ << ' ' << sent_destroy_auth_key_ << ' ' << callback_ << ' ' << (Time::now() - created_at_) << ' ' << (Time::now() - last_read_at_); - PerfWarningTimer timer("SessionConnection::do_flush", 0.01); CHECK(state_ != Closed); if (state_ == Init) { TRY_STATUS(init()); @@ -1037,7 +1037,18 @@ Status SessionConnection::do_flush() { return Status::Error("No auth key"); } - TRY_STATUS(raw_connection_->flush(auth_data_->get_auth_key(), *this)); + last_read_size_ = 0; + last_write_size_ = 0; + auto start_time = Time::now(); + auto result = raw_connection_->flush(auth_data_->get_auth_key(), *this); + auto elapsed_time = Time::now() - start_time; + if (elapsed_time >= 0.01) { + LOG(ERROR) << "RawConnection::flush took " << elapsed_time << " seconds, written " << last_write_size_ + << " bytes, read " << last_read_size_ << " bytes and returned " << result; + } + if (result.is_error()) { + return result; + } if (last_pong_at_ + ping_disconnect_delay() < Time::now_cached()) { auto stats_callback = raw_connection_->stats_callback(); diff --git a/td/mtproto/SessionConnection.h b/td/mtproto/SessionConnection.h index 1ba2d3ba6..ead20e1b1 100644 --- a/td/mtproto/SessionConnection.h +++ b/td/mtproto/SessionConnection.h @@ -189,6 +189,9 @@ class SessionConnection final uint64 last_ping_message_id_ = 0; uint64 last_ping_container_id_ = 0; + uint64 last_read_size_ = 0; + uint64 last_write_size_ = 0; + bool need_destroy_auth_key_ = false; bool sent_destroy_auth_key_ = false; From 9c04dc47ad933fa42445006e5cc89f3ec39cfe33 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 20 Sep 2022 18:13:14 +0300 Subject: [PATCH 194/200] Add support for cashtag in Twitter link preview. --- td/telegram/WebPagesManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 522dea0b8..3112fe6c0 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -1238,6 +1238,9 @@ tl_object_ptr WebPagesManager::get_web_page_object(WebPageId we if (entity.type == MessageEntity::Type::Hashtag) { return PSTRING() << "https://twitter.com/hashtag/" << url_encode(text.substr(1)); } + if (entity.type == MessageEntity::Type::Cashtag) { + return PSTRING() << "https://twitter.com/search?q=" << url_encode(text) << "&src=cashtag_click"; + } return string(); }); } else if (host == "t.me" || host == "telegram.me" || host == "telegram.dog" || host == "telesco.pe") { From b6db8a66ec560f5dffcd95489d992162f885a18f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 14:25:31 +0300 Subject: [PATCH 195/200] Remove dangerous Timestamp::store. --- td/telegram/AuthManager.hpp | 15 +++++++++++---- td/telegram/SendCodeHelper.cpp | 5 +++-- td/telegram/SendCodeHelper.h | 2 +- td/telegram/SendCodeHelper.hpp | 5 +++-- tdutils/td/utils/Time.cpp | 2 ++ tdutils/td/utils/Time.h | 17 ----------------- 6 files changed, 20 insertions(+), 26 deletions(-) diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp index 15e6cb393..65225376e 100644 --- a/td/telegram/AuthManager.hpp +++ b/td/telegram/AuthManager.hpp @@ -55,6 +55,7 @@ void AuthManager::DbState::store(StorerT &storer) const { bool is_wait_registration_supported = true; bool is_wait_registration_stores_phone_number = true; bool is_wait_qr_code_confirmation_supported = true; + bool is_time_store_supported = true; BEGIN_STORE_FLAGS(); STORE_FLAG(has_terms_of_service); STORE_FLAG(is_pbkdf2_supported); @@ -64,11 +65,12 @@ void AuthManager::DbState::store(StorerT &storer) const { STORE_FLAG(is_wait_qr_code_confirmation_supported); STORE_FLAG(allow_apple_id_); STORE_FLAG(allow_google_id_); + STORE_FLAG(is_time_store_supported); END_STORE_FLAGS(); store(state_, storer); store(api_id_, storer); store(api_hash_, storer); - store(state_timestamp_, storer); + store_time(state_timestamp_.at(), storer); if (has_terms_of_service) { store(terms_of_service_, storer); @@ -105,6 +107,7 @@ void AuthManager::DbState::parse(ParserT &parser) { bool is_wait_registration_supported = false; bool is_wait_registration_stores_phone_number = false; bool is_wait_qr_code_confirmation_supported = false; + bool is_time_store_supported = false; if (parser.version() >= static_cast(Version::AddTermsOfService)) { BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_terms_of_service); @@ -115,20 +118,24 @@ void AuthManager::DbState::parse(ParserT &parser) { PARSE_FLAG(is_wait_qr_code_confirmation_supported); PARSE_FLAG(allow_apple_id_); PARSE_FLAG(allow_google_id_); + PARSE_FLAG(is_time_store_supported); END_PARSE_FLAGS(); } - if (!is_wait_qr_code_confirmation_supported) { - return parser.set_error("Have no QR code confirmation support"); + if (!is_time_store_supported) { + return parser.set_error("Have no time store support"); } CHECK(is_pbkdf2_supported); CHECK(is_srp_supported); CHECK(is_wait_registration_supported); CHECK(is_wait_registration_stores_phone_number); + CHECK(is_wait_qr_code_confirmation_supported); parse(state_, parser); parse(api_id_, parser); parse(api_hash_, parser); - parse(state_timestamp_, parser); + double state_timestamp = 0.0; + parse_time(state_timestamp, parser); + state_timestamp_ = Timestamp::at(state_timestamp); if (has_terms_of_service) { parse(terms_of_service_, parser); diff --git a/td/telegram/SendCodeHelper.cpp b/td/telegram/SendCodeHelper.cpp index 989e2a8f0..f073f9e7d 100644 --- a/td/telegram/SendCodeHelper.cpp +++ b/td/telegram/SendCodeHelper.cpp @@ -15,7 +15,8 @@ void SendCodeHelper::on_sent_code(telegram_api::object_ptrphone_code_hash_); sent_code_info_ = get_sent_authentication_code_info(std::move(sent_code->type_)); next_code_info_ = get_authentication_code_info(std::move(sent_code->next_type_)); - next_code_timestamp_ = Timestamp::in((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); + next_code_timestamp_ = + Time::now() + ((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); } void SendCodeHelper::on_phone_code_hash(string &&phone_code_hash) { @@ -30,7 +31,7 @@ td_api::object_ptr SendCodeHelper::get_authentic return make_tl_object( phone_number_, get_authentication_code_type_object(sent_code_info_), get_authentication_code_type_object(next_code_info_), - max(static_cast(next_code_timestamp_.in() + 1 - 1e-9), 0)); + max(static_cast(next_code_timestamp_ - Time::now() + 1 - 1e-9), 0)); } Result SendCodeHelper::resend_code() const { diff --git a/td/telegram/SendCodeHelper.h b/td/telegram/SendCodeHelper.h index e4cff30c4..d78464594 100644 --- a/td/telegram/SendCodeHelper.h +++ b/td/telegram/SendCodeHelper.h @@ -83,7 +83,7 @@ class SendCodeHelper { SendCodeHelper::AuthenticationCodeInfo sent_code_info_; SendCodeHelper::AuthenticationCodeInfo next_code_info_; - Timestamp next_code_timestamp_; + double next_code_timestamp_ = 0.0; static AuthenticationCodeInfo get_authentication_code_info( tl_object_ptr &&code_type_ptr); diff --git a/td/telegram/SendCodeHelper.hpp b/td/telegram/SendCodeHelper.hpp index 673f20b43..1fab66ac5 100644 --- a/td/telegram/SendCodeHelper.hpp +++ b/td/telegram/SendCodeHelper.hpp @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/logevent/LogEventHelper.h" #include "td/telegram/SendCodeHelper.h" #include "td/utils/tl_helpers.h" @@ -36,7 +37,7 @@ void SendCodeHelper::store(StorerT &storer) const { store(phone_code_hash_, storer); store(sent_code_info_, storer); store(next_code_info_, storer); - store(next_code_timestamp_, storer); + store_time(next_code_timestamp_, storer); } template @@ -48,7 +49,7 @@ void SendCodeHelper::parse(ParserT &parser) { parse(phone_code_hash_, parser); parse(sent_code_info_, parser); parse(next_code_info_, parser); - parse(next_code_timestamp_, parser); + parse_time(next_code_timestamp_, parser); } } // namespace td diff --git a/tdutils/td/utils/Time.cpp b/tdutils/td/utils/Time.cpp index 78d222be6..93ed7d1ac 100644 --- a/tdutils/td/utils/Time.cpp +++ b/tdutils/td/utils/Time.cpp @@ -6,6 +6,8 @@ // #include "td/utils/Time.h" +#include "td/utils/port/Clocks.h" + #include #include diff --git a/tdutils/td/utils/Time.h b/tdutils/td/utils/Time.h index c0653e978..bf1dce6e1 100644 --- a/tdutils/td/utils/Time.h +++ b/tdutils/td/utils/Time.h @@ -7,7 +7,6 @@ #pragma once #include "td/utils/common.h" -#include "td/utils/port/Clocks.h" namespace td { @@ -58,9 +57,6 @@ class Timestamp { static Timestamp at(double timeout) { return Timestamp{timeout}; } - static Timestamp at_unix(double timeout) { - return Timestamp{timeout - Clocks::system() + Time::now()}; - } static Timestamp in(double timeout, Timestamp now = now_cached()) { return Timestamp{now.at() + timeout}; @@ -80,9 +76,6 @@ class Timestamp { double at() const { return at_; } - double at_unix() const { - return at_ + Clocks::system() - Time::now(); - } double in() const { return at_ - Time::now_cached(); @@ -110,14 +103,4 @@ inline bool operator<(const Timestamp &a, const Timestamp &b) { return a.at() < b.at(); } -template -void store(const Timestamp ×tamp, StorerT &storer) { - storer.store_binary(timestamp.at() - Time::now() + Clocks::system()); -} - -template -void parse(Timestamp ×tamp, ParserT &parser) { - timestamp = Timestamp::in(parser.fetch_double() - Clocks::system()); -} - } // namespace td From e9ccb43ccd0f22f8d4ce6e76f33c2f17e6e759dc Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 17:30:03 +0300 Subject: [PATCH 196/200] Use const Message * earlier in add_message_to_dialog. --- td/telegram/MessagesManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0f199fe81..be31e690c 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -35128,8 +35128,9 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } + const Message *m = message.get(); if (*need_update && message_id > d->last_read_inbox_message_id && !td_->auth_manager_->is_bot()) { - if (has_incoming_notification(dialog_id, message.get())) { + if (has_incoming_notification(dialog_id, m)) { int32 server_unread_count = d->server_unread_count; int32 local_unread_count = d->local_unread_count; if (message_id.is_server()) { @@ -35149,16 +35150,16 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } } - if (*need_update && message->contains_unread_mention) { + if (*need_update && m->contains_unread_mention) { set_dialog_unread_mention_count(d, d->unread_mention_count + 1); send_update_chat_unread_mention_count(d); } - if (*need_update && has_unread_message_reactions(dialog_id, message.get())) { + if (*need_update && has_unread_message_reactions(dialog_id, m)) { set_dialog_unread_reaction_count(d, d->unread_reaction_count + 1); send_update_chat_unread_reaction_count(d, "add_message_to_dialog"); } if (*need_update) { - update_message_count_by_index(d, +1, message.get()); + update_message_count_by_index(d, +1, m); } if (auto_attach && message_id > d->last_message_id && message_id >= d->last_new_message_id) { set_dialog_last_message_id(d, message_id, "add_message_to_dialog"); @@ -35174,12 +35175,11 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq set_dialog_last_database_message_id(d, message_id, "add_message_to_dialog"); if (!d->first_database_message_id.is_valid()) { set_dialog_first_database_message_id(d, message_id, "add_message_to_dialog"); - try_restore_dialog_reply_markup(d, message.get()); + try_restore_dialog_reply_markup(d, m); } } } - const Message *m = message.get(); if (m->message_id.is_yet_unsent() && m->reply_to_message_id != MessageId()) { if (!m->reply_to_message_id.is_yet_unsent()) { if (!m->reply_to_message_id.is_scheduled()) { From 23fe3994bfda20784c4348ee83e5ebeb672fc91f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 17:44:25 +0300 Subject: [PATCH 197/200] Don't unload messages from the last media album. --- td/telegram/MessagesManager.cpp | 26 +++++++++++++++++++++----- td/telegram/MessagesManager.h | 3 ++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index be31e690c..2da4bb11f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -14856,12 +14856,26 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f return FullMessageId(dialog_id, message_id); } -void MessagesManager::set_dialog_last_message_id(Dialog *d, MessageId last_message_id, const char *source) { +void MessagesManager::set_dialog_last_message_id(Dialog *d, MessageId last_message_id, const char *source, + const Message *m) { CHECK(!last_message_id.is_scheduled()); LOG(INFO) << "Set " << d->dialog_id << " last message to " << last_message_id << " from " << source; d->last_message_id = last_message_id; + if (m != nullptr) { + d->last_media_album_id = m->media_album_id; + } else if (!last_message_id.is_valid()) { + d->last_media_album_id = 0; + } else { + m = get_message(d, last_message_id); + if (m == nullptr) { + LOG(ERROR) << "Failed to find last " << last_message_id << " in " << d->dialog_id; + d->last_media_album_id = 0; + } else { + d->last_media_album_id = m->media_album_id; + } + } if (!last_message_id.is_valid()) { d->suffix_load_first_message_id_ = MessageId(); d->suffix_load_done_ = false; @@ -15927,6 +15941,7 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons // don't want to unload message with active reply markup // don't want to unload the newest pinned message // don't want to unload last edited message, because server can send updateEditChannelMessage again + // don't want to unload messages from the last album // can't unload from memory last dialog, last database messages, yet unsent messages, being edited media messages and active live locations // can't unload messages in dialog with active suffix load query FullMessageId full_message_id{d->dialog_id, m->message_id}; @@ -15934,7 +15949,8 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons !m->message_id.is_yet_unsent() && active_live_location_full_message_ids_.count(full_message_id) == 0 && replied_by_yet_unsent_messages_.count(full_message_id) == 0 && m->edited_content == nullptr && d->suffix_load_queries_.empty() && m->message_id != d->reply_markup_message_id && - m->message_id != d->last_pinned_message_id && m->message_id != d->last_edited_message_id; + m->message_id != d->last_pinned_message_id && m->message_id != d->last_edited_message_id && + (m->media_album_id != d->last_media_album_id || m->media_album_id == 0); } void MessagesManager::unload_message(Dialog *d, MessageId message_id) { @@ -16226,7 +16242,7 @@ unique_ptr MessagesManager::do_delete_message(Dialog * if ((*it)->have_previous) { --it; if (*it != nullptr) { - set_dialog_last_message_id(d, (*it)->message_id, "do_delete_message"); + set_dialog_last_message_id(d, (*it)->message_id, "do_delete_message", *it); } else { LOG(ERROR) << "Have have_previous is true, but there is no previous for " << full_message_id << " from " << source; @@ -35162,7 +35178,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq update_message_count_by_index(d, +1, m); } if (auto_attach && message_id > d->last_message_id && message_id >= d->last_new_message_id) { - set_dialog_last_message_id(d, message_id, "add_message_to_dialog"); + set_dialog_last_message_id(d, message_id, "add_message_to_dialog", m); *need_update_dialog_pos = true; } if (auto_attach && !message_id.is_yet_unsent() && message_id >= d->last_new_message_id && @@ -37290,7 +37306,7 @@ bool MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptrmessage_id, "add_dialog_last_database_message 2"); + set_dialog_last_message_id(d, m->message_id, "add_dialog_last_database_message 2", m); send_update_chat_last_message(d, "add_dialog_last_database_message 3"); } else { if (d->pending_last_message_date != 0) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index b76e2b043..5f088413a 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1293,6 +1293,7 @@ class MessagesManager final : public Actor { vector pending_join_request_user_ids; int32 have_full_history_source = 0; int32 unload_dialog_delay_seed = 0; + int64 last_media_album_id = 0; FolderId folder_id; vector dialog_list_ids; // TODO replace with mask @@ -2598,7 +2599,7 @@ class MessagesManager final : public Actor { void set_dialog_last_read_outbox_message_id(Dialog *d, MessageId message_id); - void set_dialog_last_message_id(Dialog *d, MessageId last_message_id, const char *source); + void set_dialog_last_message_id(Dialog *d, MessageId last_message_id, const char *source, const Message *m = nullptr); void set_dialog_first_database_message_id(Dialog *d, MessageId first_database_message_id, const char *source); From 831f0bead38bcb9c59f0c9c0050def438e066897 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 18:02:28 +0300 Subject: [PATCH 198/200] Send updateMessageContent about edited messages. --- td/telegram/MessagesManager.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 2da4bb11f..21d2886c9 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7895,8 +7895,8 @@ void MessagesManager::on_message_edited(FullMessageId full_message_id, int32 pts Message *m = get_message(d, full_message_id.get_message_id()); CHECK(m != nullptr); m->last_edit_pts = pts; + d->last_edited_message_id = m->message_id; if (td_->auth_manager_->is_bot()) { - d->last_edited_message_id = m->message_id; send_update_message_edited(dialog_id, m); } update_used_hashtags(dialog_id, m); @@ -36279,15 +36279,6 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr old_message->disable_web_page_preview = new_message->disable_web_page_preview; } - if (!is_scheduled && - update_message_contains_unread_mention(d, old_message, new_message->contains_unread_mention, "update_message")) { - need_send_update = true; - } - if (update_message_interaction_info(d, old_message, new_message->view_count, new_message->forward_count, true, - std::move(new_message->reply_info), true, std::move(new_message->reactions), - "update_message")) { - need_send_update = true; - } if (old_message->noforwards != new_message->noforwards) { LOG(DEBUG) << "Message can_be_saved has changed from " << !old_message->noforwards << " to " << !old_message->noforwards; @@ -36323,10 +36314,6 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr // old_message->is_from_scheduled = new_message->is_from_scheduled; } - if (!is_scheduled && update_message_is_pinned(d, old_message, new_message->is_pinned, "update_message")) { - need_send_update = true; - } - if (old_message->edit_date > 0) { // inline keyboard can be edited bool reply_markup_changed = @@ -36391,10 +36378,23 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr if (old_message->last_access_date < new_message->last_access_date) { old_message->last_access_date = new_message->last_access_date; } - if (new_message->is_update_sent) { + if (new_message->is_update_sent || is_edited) { old_message->is_update_sent = true; } + if (!is_scheduled && update_message_is_pinned(d, old_message, new_message->is_pinned, "update_message")) { + need_send_update = true; + } + if (!is_scheduled && + update_message_contains_unread_mention(d, old_message, new_message->contains_unread_mention, "update_message")) { + need_send_update = true; + } + if (update_message_interaction_info(d, old_message, new_message->view_count, new_message->forward_count, true, + std::move(new_message->reply_info), true, std::move(new_message->reactions), + "update_message")) { + need_send_update = true; + } + if (!is_scheduled) { CHECK(!new_message->have_previous || !new_message->have_next); if (new_message->have_previous && !old_message->have_previous) { @@ -36419,7 +36419,6 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr } if (is_edited && !td_->auth_manager_->is_bot()) { - d->last_edited_message_id = message_id; send_update_message_edited(dialog_id, old_message); } From 6c91b9aa6b881b20142cb75b4fecca24dbee0061 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 18:55:21 +0300 Subject: [PATCH 199/200] Create all dialogs before initializing inactive_channel_ids_. --- td/telegram/ContactsManager.cpp | 42 ++++++++++++++++++++++----------- td/telegram/ContactsManager.h | 8 ++++--- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index c62c5dbae..d7cd587b1 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2588,11 +2588,9 @@ class GetInactiveChannelsQuery final : public Td::ResultHandler { auto result = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetInactiveChannelsQuery: " << to_string(result); - // TODO use result->dates_ + // don't need to use result->dates_, because chat.last_message.date is more reliable td_->contacts_manager_->on_get_users(std::move(result->users_), "GetInactiveChannelsQuery"); - td_->contacts_manager_->on_get_inactive_channels(std::move(result->chats_)); - - promise_.set_value(Unit()); + td_->contacts_manager_->on_get_inactive_channels(std::move(result->chats_), std::move(promise_)); } void on_error(Status status) final { @@ -8305,26 +8303,42 @@ void ContactsManager::update_dialogs_for_discussion(DialogId dialog_id, bool is_ } vector ContactsManager::get_inactive_channels(Promise &&promise) { - if (inactive_channels_inited_) { + if (inactive_channel_ids_inited_) { promise.set_value(Unit()); - return transform(inactive_channels_, [&](ChannelId channel_id) { - DialogId dialog_id{channel_id}; - td_->messages_manager_->force_create_dialog(dialog_id, "get_inactive_channels"); - return dialog_id; - }); + return transform(inactive_channel_ids_, [&](ChannelId channel_id) { return DialogId(channel_id); }); } td_->create_handler(std::move(promise))->send(); return {}; } -void ContactsManager::on_get_inactive_channels(vector> &&chats) { - inactive_channels_inited_ = true; - inactive_channels_ = get_channel_ids(std::move(chats), "on_get_inactive_channels"); +void ContactsManager::on_get_inactive_channels(vector> &&chats, + Promise &&promise) { + auto channel_ids = get_channel_ids(std::move(chats), "on_get_inactive_channels"); + + MultiPromiseActorSafe mpas{"GetInactiveChannelsMultiPromiseActor"}; + mpas.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), channel_ids, + promise = std::move(promise)](Unit) mutable { + send_closure(actor_id, &ContactsManager::on_create_inactive_channels, std::move(channel_ids), std::move(promise)); + })); + mpas.set_ignore_errors(true); + auto lock_promise = mpas.get_promise(); + + for (auto channel_id : channel_ids) { + td_->messages_manager_->create_dialog(DialogId(channel_id), false, mpas.get_promise()); + } + + lock_promise.set_value(Unit()); +} + +void ContactsManager::on_create_inactive_channels(vector &&channel_ids, Promise &&promise) { + inactive_channel_ids_inited_ = true; + inactive_channel_ids_ = std::move(channel_ids); + promise.set_value(Unit()); } void ContactsManager::remove_inactive_channel(ChannelId channel_id) { - if (inactive_channels_inited_ && td::remove(inactive_channels_, channel_id)) { + if (inactive_channel_ids_inited_ && td::remove(inactive_channel_ids_, channel_id)) { LOG(DEBUG) << "Remove " << channel_id << " from list of inactive channels"; } } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 537665621..542b172b8 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -252,7 +252,7 @@ class ContactsManager final : public Actor { void on_get_dialogs_for_discussion(vector> &&chats); - void on_get_inactive_channels(vector> &&chats); + void on_get_inactive_channels(vector> &&chats, Promise &&promise); void remove_inactive_channel(ChannelId channel_id); @@ -1608,6 +1608,8 @@ class ContactsManager final : public Actor { vector get_dialog_ids(vector> &&chats, const char *source); + void on_create_inactive_channels(vector &&channel_ids, Promise &&promise); + void update_dialogs_for_discussion(DialogId dialog_id, bool is_suitable); void send_edit_chat_admin_query(ChatId chat_id, UserId user_id, bool is_administrator, Promise &&promise); @@ -1757,8 +1759,8 @@ class ContactsManager final : public Actor { bool dialogs_for_discussion_inited_ = false; vector dialogs_for_discussion_; - bool inactive_channels_inited_ = false; - vector inactive_channels_; + bool inactive_channel_ids_inited_ = false; + vector inactive_channel_ids_; FlatHashMap>, UserIdHash> load_user_from_database_queries_; FlatHashSet loaded_from_database_users_; From 2a41ab05628945dd2750f354a592a0df27725fd5 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Sep 2022 19:04:36 +0300 Subject: [PATCH 200/200] Don't add self speculatively to channel members if join requests are enabled in the chat. --- td/telegram/ContactsManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index d7cd587b1..90e35a643 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -7243,7 +7243,9 @@ void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_ return promise.set_error(Status::Error(400, "Can't return to kicked from chat")); } - speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), c->status); + if (!get_channel_join_request(c)) { + speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), c->status); + } td_->create_handler(std::move(promise))->send(channel_id); return; }