diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index ab4d73d9c..7ab4bf23f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1377,6 +1377,9 @@ messageVenue venue:venue = MessageContent; //@description A message with a user contact @contact The contact description messageContact contact:contact = MessageContent; +//@description A die message. The die value is randomly generated by the server @value The die value; 0-6. If the value is 0, the die must roll infinitely +messageDie value:int32 = MessageContent; + //@description A message with a game @game The game description messageGame game:game = MessageContent; @@ -1578,6 +1581,9 @@ inputMessageVenue venue:venue = InputMessageContent; //@description A message containing a user contact @contact Contact to send inputMessageContact contact:contact = InputMessageContent; +//@description A die message +inputMessageDie = InputMessageContent; + //@description A message with a game; not supported for channels or secret chats @bot_user_id User identifier of the bot that owns the game @game_short_name Short name of the game inputMessageGame bot_user_id:int32 game_short_name:string = InputMessageContent; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 5f9d6e1c5..d7039b5a3 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 8b3191999..609821e04 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -643,6 +643,19 @@ class MessagePoll : public MessageContent { } }; +class MessageDie : public MessageContent { + public: + int32 die_value = 0; + + MessageDie() = default; + explicit MessageDie(int32 die_value) : die_value(die_value) { + } + + MessageContentType get_type() const override { + return MessageContentType::Die; + } +}; + template static void store(const MessageContent *content, StorerT &storer) { CHECK(content != nullptr); @@ -900,6 +913,11 @@ static void store(const MessageContent *content, StorerT &storer) { store(m->poll_id, storer); break; } + case MessageContentType::Die: { + auto m = static_cast(content); + store(m->die_value, storer); + break; + } default: UNREACHABLE(); } @@ -1242,6 +1260,13 @@ static void parse(unique_ptr &content, ParserT &parser) { content = std::move(m); break; } + case MessageContentType::Die: { + auto m = make_unique(); + parse(m->die_value, parser); + is_bad = m->die_value < 0 || m->die_value > 6; + content = std::move(m); + break; + } default: LOG(FATAL) << "Have unknown message content type " << static_cast(content_type); } @@ -1450,6 +1475,9 @@ static Result create_input_message_content( content = make_unique(file_id, std::move(caption)); break; } + case td_api::inputMessageDie::ID: + content = make_unique(); + break; case td_api::inputMessageDocument::ID: td->documents_manager_->create_document(file_id, string(), thumbnail, std::move(file_name), std::move(mime_type), false); @@ -1903,6 +1931,7 @@ bool can_have_input_media(const Td *td, const MessageContent *content) { case MessageContentType::Animation: case MessageContentType::Audio: case MessageContentType::Contact: + case MessageContentType::Die: case MessageContentType::Document: case MessageContentType::Invoice: case MessageContentType::LiveLocation: @@ -1981,6 +2010,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td, return td->voice_notes_manager_->get_secret_input_media(m->file_id, std::move(input_file), m->caption.text); } case MessageContentType::Call: + case MessageContentType::Die: case MessageContentType::Game: case MessageContentType::Invoice: case MessageContentType::LiveLocation: @@ -2113,6 +2143,8 @@ static tl_object_ptr get_input_media_impl( auto m = static_cast(content); return m->contact.get_input_media_contact(); } + case MessageContentType::Die: + return make_tl_object(); case MessageContentType::Document: { auto m = static_cast(content); return td->documents_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail)); @@ -2268,6 +2300,7 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) { return td->video_notes_manager_->delete_video_note_thumbnail(m->file_id); } case MessageContentType::Contact: + case MessageContentType::Die: case MessageContentType::Game: case MessageContentType::Invoice: case MessageContentType::LiveLocation: @@ -2436,6 +2469,7 @@ static int32 get_message_content_media_index_mask(const MessageContent *content, case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: return 0; default: UNREACHABLE(); @@ -3039,6 +3073,14 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo } break; } + case MessageContentType::Die: { + auto old_ = static_cast(old_content); + auto new_ = static_cast(new_content); + if (old_->die_value != new_->die_value) { + need_update = true; + } + break; + } case MessageContentType::Unsupported: { auto old_ = static_cast(old_content); auto new_ = static_cast(new_content); @@ -3170,6 +3212,7 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: LOG(ERROR) << "Receive new file " << new_file_id << " in a sent message of the type " << content_type; break; default: @@ -3660,6 +3703,16 @@ unique_ptr get_message_content(Td *td, FormattedText message, } return make_unique(std::move(photo), std::move(message)); } + case telegram_api::messageMediaDice::ID: { + auto message_dice = move_tl_object_as(media); + + auto m = make_unique(message_dice->value_); + if (m->die_value < 0 || m->die_value > 6) { + break; + } + + return std::move(m); + } case telegram_api::messageMediaGeo::ID: { auto message_geo_point = move_tl_object_as(media); @@ -3842,6 +3895,12 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const } case MessageContentType::Contact: return make_unique(*static_cast(content)); + case MessageContentType::Die: + if (type != MessageContentDupType::Forward) { + return make_unique(); + } else { + return make_unique(*static_cast(content)); + } case MessageContentType::Document: { auto result = make_unique(*static_cast(content)); if (remove_caption) { @@ -4371,6 +4430,10 @@ tl_object_ptr get_message_content_object(const MessageCo const MessagePoll *m = static_cast(content); return make_tl_object(td->poll_manager_->get_poll_object(m->poll_id)); } + case MessageContentType::Die: { + const MessageDie *m = static_cast(content); + return make_tl_object(m->die_value); + } default: UNREACHABLE(); return nullptr; @@ -4663,6 +4726,7 @@ string get_message_content_search_text(const Td *td, const MessageContent *conte case MessageContentType::WebsiteConnected: case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: + case MessageContentType::Die: return string(); default: UNREACHABLE(); @@ -4854,6 +4918,8 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC case MessageContentType::Poll: // no need to add poll dependencies, because they are forcely loaded with the poll break; + case MessageContentType::Die: + break; default: UNREACHABLE(); break; diff --git a/td/telegram/MessageContentType.cpp b/td/telegram/MessageContentType.cpp index 8d58addb1..97ce6070c 100644 --- a/td/telegram/MessageContentType.cpp +++ b/td/telegram/MessageContentType.cpp @@ -94,6 +94,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType cont return string_builder << "PassportDataReceived"; case MessageContentType::Poll: return string_builder << "Poll"; + case MessageContentType::Die: + return string_builder << "Die"; default: UNREACHABLE(); return string_builder; @@ -144,6 +146,7 @@ bool is_allowed_media_group_content(MessageContentType content_type) { case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: return false; default: UNREACHABLE(); @@ -198,6 +201,7 @@ bool is_secret_message_content(int32 ttl, MessageContentType content_type) { case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: return false; default: UNREACHABLE(); @@ -226,6 +230,7 @@ bool is_service_message_content(MessageContentType content_type) { case MessageContentType::ExpiredPhoto: case MessageContentType::ExpiredVideo: case MessageContentType::Poll: + case MessageContentType::Die: return false; case MessageContentType::ChatCreate: case MessageContentType::ChatChangeTitle: @@ -300,6 +305,7 @@ bool can_have_message_content_caption(MessageContentType content_type) { case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: return false; default: UNREACHABLE(); diff --git a/td/telegram/MessageContentType.h b/td/telegram/MessageContentType.h index 240b58b92..cc6f01892 100644 --- a/td/telegram/MessageContentType.h +++ b/td/telegram/MessageContentType.h @@ -53,7 +53,8 @@ enum class MessageContentType : int32 { WebsiteConnected, PassportDataSent, PassportDataReceived, - Poll + Poll, + Die }; StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ff1d91834..d5d6a4537 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6046,6 +6046,7 @@ bool MessagesManager::need_cancel_user_dialog_action(int32 action_id, MessageCon case MessageContentType::PassportDataSent: case MessageContentType::PassportDataReceived: case MessageContentType::Poll: + case MessageContentType::Die: return false; default: UNREACHABLE(); @@ -8520,6 +8521,10 @@ bool MessagesManager::can_delete_message(DialogId dialog_id, const Message *m) c } switch (dialog_id.get_type()) { case DialogType::User: + if (G()->unix_time_cached() < m->date + 86400 && m->content->get_type() == MessageContentType::Die && + dialog_id != get_my_dialog_id()) { + return false; + } return true; case DialogType::Chat: return true; @@ -17982,6 +17987,9 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa if (content_type == MessageContentType::Poll) { return Status::Error(400, "Polls can't be sent to secret chats"); } + if (content_type == MessageContentType::Die) { + return Status::Error(400, "Dice can't be sent to secret chats"); + } break; case DialogType::None: default: @@ -18004,6 +18012,11 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa return Status::Error(400, "Not enough rights to send contacts to the chat"); } break; + case MessageContentType::Die: + if (!can_send_messages) { + return Status::Error(400, "Not enough rights to send dice to the chat"); + } + break; case MessageContentType::Document: if (!can_send_media) { return Status::Error(400, "Not enough rights to send documents to the chat"); @@ -19520,6 +19533,7 @@ bool MessagesManager::can_edit_message(DialogId dialog_id, const Message *m, boo return !get_message_content_poll_is_closed(td_, m->content.get()); } case MessageContentType::Contact: + case MessageContentType::Die: case MessageContentType::Location: case MessageContentType::Sticker: case MessageContentType::Venue: @@ -20852,7 +20866,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i forward_info->from_dialog_id = saved_from_dialog_id; forward_info->from_message_id = saved_from_message_id; } else { - if (from_dialog_id != DialogId(my_id)) { + if (from_dialog_id != DialogId(my_id) || content_type == MessageContentType::Die) { if (forwarded_message->is_channel_post) { if (is_broadcast_channel(from_dialog_id)) { auto author_signature = forwarded_message->sender_user_id.is_valid() @@ -21247,6 +21261,9 @@ Result MessagesManager::add_local_message( if (message_content.content->get_type() == MessageContentType::Game) { return Status::Error(400, "Can't add local game message"); } + if (message_content.content->get_type() == MessageContentType::Die) { + return Status::Error(400, "Can't add local die message"); + } bool is_channel_post = is_broadcast_channel(dialog_id); if (sender_user_id != UserId() && !td_->contacts_manager_->have_user_force(sender_user_id)) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ce251832b..37ca067c7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3123,6 +3123,8 @@ class CliClient final : public Actor { send_message(chat_id, td_api::make_object(as_chat_id(from_chat_id), as_message_id(from_message_id), true, op == "scopy", Random::fast(0, 1) == 0)); + } else if (op == "sdie") { + send_message(args, td_api::make_object()); } else if (op == "sd") { string chat_id; string document_path;