diff --git a/CMakeLists.txt b/CMakeLists.txt index fb27df21c..701694679 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -786,6 +786,7 @@ set(TDLIB_SOURCE td/telegram/ReactionListType.h td/telegram/ReactionManager.h td/telegram/ReactionType.h + td/telegram/ReactionUnavailabilityReason.h td/telegram/RecentDialogList.h td/telegram/RepliedMessageInfo.h td/telegram/ReplyMarkup.h diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 444f4efcd..8d47a31a0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4025,7 +4025,8 @@ availableReaction type:ReactionType needs_premium:Bool = AvailableReaction; //@popular_reactions List of popular reactions //@allow_custom_emoji True, if any custom emoji reaction can be added by Telegram Premium subscribers //@are_tags True, if the reactions will be tags and the message can be found by them -availableReactions top_reactions:vector recent_reactions:vector popular_reactions:vector allow_custom_emoji:Bool are_tags:Bool = AvailableReactions; +//@unavailability_reason The reason why the current user can't add reactions to the message, despite some other users can; null if none +availableReactions top_reactions:vector recent_reactions:vector popular_reactions:vector allow_custom_emoji:Bool are_tags:Bool unavailability_reason:ReactionUnavailabilityReason = AvailableReactions; //@description Contains information about an emoji reaction //@emoji Text representation of the reaction @@ -4041,6 +4042,15 @@ availableReactions top_reactions:vector recent_reactions:vect 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; +//@class ReactionUnavailabilityReason @description Describes why the current user can't add reactions to the message, despite some other users can + +//@description The user is an anonymous administrator in the supergroup, but isn't a creator of it, so they can't vote on behalf of the supergroup +reactionUnavailabilityReasonAnonymousAdministrator = ReactionUnavailabilityReason; + +//@description The user isn't a member of the supergroup and can't send messages and reactions there without joining +reactionUnavailabilityReasonGuest = ReactionUnavailabilityReason; + + //@description Represents a list of animations @animations List of animations animations animations:vector = Animations; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 14d8ca440..b02c7607d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -22645,12 +22645,15 @@ Result> MessagesManager::get_mess } bool is_tag = can_add_message_tag(dialog_id, m->reactions.get()); - return td_->reaction_manager_->get_sorted_available_reactions(get_message_available_reactions(d, m, false), - get_message_active_reactions(d, m), row_size, is_tag); + ReactionUnavailabilityReason unavailability_reason = ReactionUnavailabilityReason::None; + auto available_reactions = get_message_available_reactions(d, m, false, &unavailability_reason); + return td_->reaction_manager_->get_sorted_available_reactions( + std::move(available_reactions), get_message_active_reactions(d, m), row_size, is_tag, unavailability_reason); } ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, const Message *m, - bool disallow_custom_for_non_premium) { + bool disallow_custom_for_non_premium, + ReactionUnavailabilityReason *unavailability_reason) { CHECK(d != nullptr); CHECK(m != nullptr); auto active_reactions = get_message_active_reactions(d, m); @@ -22665,11 +22668,17 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d, !td_->contacts_manager_->get_channel_status(channel_id).is_member() && can_send_message(d->dialog_id).is_error()) { // can't use reactions if can't send messages to the group without joining + if (unavailability_reason != nullptr) { + *unavailability_reason = ReactionUnavailabilityReason::Guest; + } can_use_reactions = false; } else if (td_->dialog_manager_->is_anonymous_administrator(d->dialog_id, nullptr) && !td_->dialog_manager_->is_broadcast_channel(d->dialog_id) && !td_->contacts_manager_->get_channel_status(channel_id).is_creator()) { // only creator can react as the chat + if (unavailability_reason != nullptr) { + *unavailability_reason = ReactionUnavailabilityReason::AnonymousAdministrator; + } can_use_reactions = false; } } @@ -22732,7 +22741,7 @@ void MessagesManager::add_message_reaction(MessageFullId message_full_id, Reacti return promise.set_error(Status::Error(400, "Message not found")); } - if (!get_message_available_reactions(d, m, true).is_allowed_reaction_type(reaction_type)) { + if (!get_message_available_reactions(d, m, true, nullptr).is_allowed_reaction_type(reaction_type)) { 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 0dc1f469d..5a876926a 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -52,6 +52,7 @@ #include "td/telegram/NotificationSettingsScope.h" #include "td/telegram/OrderedMessage.h" #include "td/telegram/ReactionType.h" +#include "td/telegram/ReactionUnavailabilityReason.h" #include "td/telegram/RecentDialogList.h" #include "td/telegram/RepliedMessageInfo.h" #include "td/telegram/ReplyMarkup.h" @@ -2522,8 +2523,8 @@ class MessagesManager final : public Actor { bool can_add_message_tag(DialogId dialog_id, const MessageReactions *reactions) const; - ChatReactions get_message_available_reactions(const Dialog *d, const Message *m, - bool disallow_custom_for_non_premium); + ChatReactions get_message_available_reactions(const Dialog *d, const Message *m, bool disallow_custom_for_non_premium, + ReactionUnavailabilityReason *unavailability_reason); DialogId get_my_reaction_dialog_id(const Dialog *d) const; diff --git a/td/telegram/ReactionManager.cpp b/td/telegram/ReactionManager.cpp index 3da2afca9..c6cec47c9 100644 --- a/td/telegram/ReactionManager.cpp +++ b/td/telegram/ReactionManager.cpp @@ -383,7 +383,8 @@ void ReactionManager::get_emoji_reaction(const string &emoji, } td_api::object_ptr ReactionManager::get_sorted_available_reactions( - ChatReactions available_reactions, ChatReactions active_reactions, int32 row_size, bool is_tag) { + ChatReactions available_reactions, ChatReactions active_reactions, int32 row_size, bool is_tag, + ReactionUnavailabilityReason unavailability_reason) { if (is_tag) { load_reaction_list(ReactionListType::DefaultTag); } else { @@ -490,16 +491,31 @@ td_api::object_ptr ReactionManager::get_sorted_avail CHECK(all_available_reaction_types.empty()); + td_api::object_ptr reason; + switch (unavailability_reason) { + case ReactionUnavailabilityReason::None: + break; + case ReactionUnavailabilityReason::AnonymousAdministrator: + reason = td_api::make_object(); + break; + case ReactionUnavailabilityReason::Guest: + reason = td_api::make_object(); + break; + default: + UNREACHABLE(); + } + return td_api::make_object( std::move(top_reaction_objects), std::move(recent_reaction_objects), std::move(popular_reaction_objects), - available_reactions.allow_all_custom_, is_tag); + available_reactions.allow_all_custom_, is_tag, std::move(reason)); } td_api::object_ptr ReactionManager::get_available_reactions(int32 row_size) { ChatReactions available_reactions; available_reactions.reaction_types_ = active_reaction_types_; available_reactions.allow_all_custom_ = true; - return get_sorted_available_reactions(std::move(available_reactions), ChatReactions(true, true), row_size, false); + return get_sorted_available_reactions(std::move(available_reactions), ChatReactions(true, true), row_size, false, + ReactionUnavailabilityReason::None); } void ReactionManager::add_recent_reaction(const ReactionType &reaction_type) { diff --git a/td/telegram/ReactionManager.h b/td/telegram/ReactionManager.h index 9bf60d959..8c7b7f39d 100644 --- a/td/telegram/ReactionManager.h +++ b/td/telegram/ReactionManager.h @@ -10,6 +10,7 @@ #include "td/telegram/files/FileId.h" #include "td/telegram/ReactionListType.h" #include "td/telegram/ReactionType.h" +#include "td/telegram/ReactionUnavailabilityReason.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -42,9 +43,9 @@ class ReactionManager final : public Actor { void get_emoji_reaction(const string &emoji, Promise> &&promise); - td_api::object_ptr get_sorted_available_reactions(ChatReactions available_reactions, - ChatReactions active_reactions, - int32 row_size, bool is_tag); + td_api::object_ptr get_sorted_available_reactions( + ChatReactions available_reactions, ChatReactions active_reactions, int32 row_size, bool is_tag, + ReactionUnavailabilityReason unavailability_reason); td_api::object_ptr get_available_reactions(int32 row_size); diff --git a/td/telegram/ReactionUnavailabilityReason.h b/td/telegram/ReactionUnavailabilityReason.h new file mode 100644 index 000000000..35d7758c2 --- /dev/null +++ b/td/telegram/ReactionUnavailabilityReason.h @@ -0,0 +1,15 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 +// +// 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/utils/common.h" + +namespace td { + +enum class ReactionUnavailabilityReason : int32 { None, AnonymousAdministrator, Guest }; + +} // namespace td