This commit is contained in:
Andrea Cavalli 2020-12-25 18:58:35 +01:00
commit 204757e075
24 changed files with 485 additions and 66 deletions

View File

@ -326,6 +326,7 @@ set(TDLIB_SOURCE
td/telegram/HashtagHints.cpp
td/telegram/InlineQueriesManager.cpp
td/telegram/InputDialogId.cpp
td/telegram/InputGroupCallId.cpp
td/telegram/InputMessageText.cpp
td/telegram/JsonValue.cpp
td/telegram/LanguagePackManager.cpp
@ -499,6 +500,7 @@ set(TDLIB_SOURCE
td/telegram/HashtagHints.h
td/telegram/InlineQueriesManager.h
td/telegram/InputDialogId.h
td/telegram/InputGroupCallId.h
td/telegram/InputMessageText.h
td/telegram/JsonValue.h
td/telegram/LanguagePackManager.h

View File

@ -270,8 +270,8 @@ photo has_stickers:Bool minithumbnail:minithumbnail sizes:vector<photoSize> = Ph
//@description Describes a sticker @set_id The identifier of the sticker set to which the sticker belongs; 0 if none @width Sticker width; as defined by the sender @height Sticker height; as defined by the sender
//@emoji Emoji corresponding to the sticker @is_animated True, if the sticker is an animated sticker in TGS format @is_mask True, if the sticker is a mask @mask_position Position where the mask should be placed; may be null
//@thumbnail Sticker thumbnail in WEBP or JPEG format; may be null @sticker File containing the sticker
sticker set_id:int64 width:int32 height:int32 emoji:string is_animated:Bool is_mask:Bool mask_position:maskPosition thumbnail:thumbnail sticker:file = Sticker;
//@cover Sticker cover in an SVG format; may be empty @thumbnail Sticker thumbnail in WEBP or JPEG format; may be null @sticker File containing the sticker
sticker set_id:int64 width:int32 height:int32 emoji:string is_animated:Bool is_mask:Bool mask_position:maskPosition cover:string thumbnail:thumbnail sticker:file = Sticker;
//@description Describes a video file @duration Duration of the video, in seconds; as defined by the sender @width Video width; as defined by the sender @height Video height; as defined by the sender
//@file_name Original name of the file; as defined by the sender @mime_type MIME type of the file; as defined by the sender
@ -458,8 +458,9 @@ chatMemberStatusCreator custom_title:string is_anonymous:Bool is_member:Bool = C
//@can_restrict_members True, if the administrator can restrict, ban, or unban chat members
//@can_pin_messages True, if the administrator can pin messages; applicable to groups only
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them
//@can_manage_calls True, if the administrator can manage group calls; applicable to supergroups only
//@is_anonymous True, if the administrator isn't shown in the chat member list and sends messages anonymously; applicable to supergroups only
chatMemberStatusAdministrator custom_title:string can_be_edited: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 is_anonymous:Bool = ChatMemberStatus;
chatMemberStatusAdministrator custom_title:string can_be_edited: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_calls:Bool is_anonymous:Bool = ChatMemberStatus;
//@description The user is a member of a chat, without any additional privileges or restrictions
chatMemberStatusMember = ChatMemberStatus;
@ -1626,6 +1627,12 @@ messageInvoice title:string description:string photo:photo currency:string total
//@description A message with information about an ended call @is_video True, if the call was a video call @discard_reason Reason why the call was discarded @duration Call duration, in seconds
messageCall is_video:Bool discard_reason:CallDiscardReason duration:int32 = MessageContent;
//@description A message with information about a group call
messageGroupCall = MessageContent;
//@description A message with information about an invite to a group call
messageInviteToGroupCall = MessageContent;
//@description A newly created basic group @title Title of the basic group @member_user_ids User identifiers of members in the basic group
messageBasicGroupChatCreate title:string member_user_ids:vector<int32> = MessageContent;
@ -1931,6 +1938,8 @@ chatActionStartPlayingGame = ChatAction;
chatActionRecordingVideoNote = ChatAction;
//@description The user is uploading a video note @progress Upload progress, as a percentage
chatActionUploadingVideoNote progress:int32 = ChatAction;
//@description The user is speaking in a call; supergroups only
chatActionSpeakingInCall = ChatAction;
//@description The user has cancelled the previous action
chatActionCancel = ChatAction;

View File

@ -111,11 +111,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#9ba2d800 id:int = Chat;
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#7328bdb id:int title:string = Chat;
channel#d31a961e 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 id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channel#d31a961e 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 id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
channelFull#f0e6672a 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 id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int = ChatFull;
channelFull#ef3a6acd 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 id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@ -169,6 +169,8 @@ messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
messageActionContactSignUp#f3f25f76 = MessageAction;
messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int = MessageAction;
messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int = MessageAction;
messageActionInviteToGroupCall#f25f03a call:InputGroupCall user_id:int = MessageAction;
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
@ -181,6 +183,7 @@ photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = Phot
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector<int> = PhotoSize;
photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
@ -349,6 +352,8 @@ updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
updateGroupCallParticipants#f2ebdb4e call:InputGroupCall participants:Vector<GroupCallParticipant> version:int = Update;
updateGroupCall#85fe86ed call:GroupCall = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -435,6 +440,7 @@ sendMessageChooseContactAction#628cbc6f = SendMessageAction;
sendMessageGamePlayAction#dd6a8f48 = SendMessageAction;
sendMessageRecordRoundAction#88f27fbc = SendMessageAction;
sendMessageUploadRoundAction#243e1c66 progress:int = SendMessageAction;
speakingInGroupCallAction#d92c2285 = SendMessageAction;
contacts.found#b3134d9d my_results:Vector<Peer> results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
@ -1023,7 +1029,7 @@ chatOnlines#f041e250 onlines:int = ChatOnlines;
statsURL#47a971e0 url:string = StatsURL;
chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true = ChatAdminRights;
chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true = ChatAdminRights;
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true until_date:int = ChatBannedRights;
@ -1165,6 +1171,17 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
groupCall#55903081 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true id:long access_hash:long participants_count:int params:flags.0?DataJSON version:int = GroupCall;
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant;
phone.groupCall#985c2087 call:GroupCall sources:Vector<int> participants:Vector<GroupCallParticipant> participants_next_offset:string users:Vector<User> = phone.GroupCall;
phone.groupParticipants#9cfeb92d count:int participants:Vector<GroupCallParticipant> next_offset:string users:Vector<User> version:int = phone.GroupParticipants;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1519,6 +1536,16 @@ phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall durati
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
phone.createGroupCall#e428fa02 channel:InputChannel random_id:int = Updates;
phone.joinGroupCall#5f9c8e62 flags:# muted:flags.0?true call:InputGroupCall params:DataJSON = Updates;
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
phone.editGroupCallMember#63146ae4 flags:# muted:flags.0?true call:InputGroupCall user_id:InputUser = Updates;
phone.inviteToGroupCall#dd698f84 call:InputGroupCall user_id:InputUser = Updates;
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
phone.toggleGroupCallSettings#74bbb43d flags:# call:InputGroupCall join_muted:flags.0?Bool = Updates;
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
phone.getGroupParticipants#ae1910a4 call:InputGroupCall offset:string limit:int = phone.GroupParticipants;
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;

View File

@ -80,6 +80,9 @@ DialogAction::DialogAction(tl_object_ptr<td_api::ChatAction> &&action) {
init(Type::UploadingVideoNote, uploading_action->progress_);
break;
}
case td_api::chatActionSpeakingInCall::ID:
init(Type::SpeakingInCall);
break;
default:
UNREACHABLE();
break;
@ -137,6 +140,9 @@ DialogAction::DialogAction(tl_object_ptr<telegram_api::SendMessageAction> &&acti
init(Type::UploadingVideoNote, upload_round_action->progress_);
break;
}
case telegram_api::speakingInGroupCallAction::ID:
init(Type::SpeakingInCall);
break;
default:
UNREACHABLE();
break;
@ -171,6 +177,8 @@ tl_object_ptr<telegram_api::SendMessageAction> DialogAction::get_input_send_mess
return make_tl_object<telegram_api::sendMessageRecordRoundAction>();
case Type::UploadingVideoNote:
return make_tl_object<telegram_api::sendMessageUploadRoundAction>(progress_);
case Type::SpeakingInCall:
return make_tl_object<telegram_api::speakingInGroupCallAction>();
default:
UNREACHABLE();
return nullptr;
@ -205,6 +213,8 @@ tl_object_ptr<secret_api::SendMessageAction> DialogAction::get_secret_input_send
return make_tl_object<secret_api::sendMessageRecordRoundAction>();
case Type::UploadingVideoNote:
return make_tl_object<secret_api::sendMessageUploadRoundAction>();
case Type::SpeakingInCall:
return make_tl_object<secret_api::sendMessageTypingAction>();
default:
UNREACHABLE();
return nullptr;
@ -239,6 +249,8 @@ tl_object_ptr<td_api::ChatAction> DialogAction::get_chat_action_object() const {
return td_api::make_object<td_api::chatActionRecordingVideoNote>();
case Type::UploadingVideoNote:
return td_api::make_object<td_api::chatActionUploadingVideoNote>(progress_);
case Type::SpeakingInCall:
return td_api::make_object<td_api::chatActionSpeakingInCall>();
default:
UNREACHABLE();
return td_api::make_object<td_api::chatActionCancel>();
@ -306,6 +318,8 @@ bool DialogAction::is_cancelled_by_message_of_type(MessageContentType message_co
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
default:
UNREACHABLE();
@ -366,6 +380,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogAction &act
return "RecordingVideoNote";
case DialogAction::Type::UploadingVideoNote:
return "UploadingVideoNote";
case DialogAction::Type::SpeakingInCall:
return "SpeakingInCall";
default:
UNREACHABLE();
return "Cancel";

View File

@ -30,7 +30,8 @@ class DialogAction {
ChoosingContact,
StartPlayingGame,
RecordingVideoNote,
UploadingVideoNote
UploadingVideoNote,
SpeakingInCall
};
Type type_ = Type::Cancel;
int32 progress_ = 0;

View File

@ -38,7 +38,8 @@ DialogParticipantStatus DialogParticipantStatus::Administrator(bool is_anonymous
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_pin_messages, bool can_promote_members,
bool can_manage_calls) {
uint32 flags = (static_cast<uint32>(can_be_edited) * CAN_BE_EDITED) |
(static_cast<uint32>(can_change_info) * CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) |
(static_cast<uint32>(can_post_messages) * CAN_POST_MESSAGES) |
@ -48,6 +49,7 @@ DialogParticipantStatus DialogParticipantStatus::Administrator(bool is_anonymous
(static_cast<uint32>(can_restrict_members) * CAN_RESTRICT_MEMBERS) |
(static_cast<uint32>(can_pin_messages) * CAN_PIN_MESSAGES_ADMIN) |
(static_cast<uint32>(can_promote_members) * CAN_PROMOTE_MEMBERS) |
(static_cast<uint32>(can_manage_calls) * CAN_MANAGE_CALLS) |
(static_cast<uint32>(is_anonymous) * IS_ANONYMOUS);
if (flags == 0 || flags == CAN_BE_EDITED) {
return Member();
@ -90,14 +92,14 @@ DialogParticipantStatus DialogParticipantStatus::Banned(int32 banned_until_date)
}
DialogParticipantStatus DialogParticipantStatus::GroupAdministrator(bool is_creator) {
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false);
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false, false);
}
DialogParticipantStatus DialogParticipantStatus::ChannelAdministrator(bool is_creator, bool is_megagroup) {
if (is_megagroup) {
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false);
return Administrator(false, string(), is_creator, true, false, false, true, true, true, true, false, false);
} else {
return Administrator(false, string(), is_creator, false, true, true, true, false, true, false, false);
return Administrator(false, string(), is_creator, false, true, true, true, false, true, false, false, false);
}
}
@ -115,7 +117,7 @@ tl_object_ptr<td_api::ChatMemberStatus> DialogParticipantStatus::get_chat_member
return td_api::make_object<td_api::chatMemberStatusAdministrator>(
rank_, can_be_edited(), can_change_info_and_settings(), can_post_messages(), can_edit_messages(),
can_delete_messages(), can_invite_users(), can_restrict_members(), can_pin_messages(), can_promote_members(),
is_anonymous());
can_manage_calls(), is_anonymous());
case Type::Member:
return td_api::make_object<td_api::chatMemberStatusMember>();
case Type::Restricted:
@ -157,14 +159,17 @@ tl_object_ptr<telegram_api::chatAdminRights> DialogParticipantStatus::get_chat_a
if (can_promote_members()) {
flags |= telegram_api::chatAdminRights::ADD_ADMINS_MASK;
}
if (can_manage_calls()) {
flags |= telegram_api::chatAdminRights::MANAGE_CALL_MASK;
}
if (is_anonymous()) {
flags |= telegram_api::chatAdminRights::ANONYMOUS_MASK;
}
LOG(INFO) << "Create chat admin rights " << flags;
return make_tl_object<telegram_api::chatAdminRights>(flags, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/);
return make_tl_object<telegram_api::chatAdminRights>(
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/);
}
tl_object_ptr<telegram_api::chatBannedRights> DialogParticipantStatus::get_chat_banned_rights() const {
@ -314,6 +319,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant
if (status.can_promote_members()) {
string_builder << "(promote)";
}
if (status.can_manage_calls()) {
string_builder << "(call)";
}
if (!status.rank_.empty()) {
string_builder << " [" << status.rank_ << "]";
}
@ -396,7 +404,7 @@ DialogParticipantStatus get_dialog_participant_status(const tl_object_ptr<td_api
return DialogParticipantStatus::Administrator(
st->is_anonymous_, st->custom_title_, true /*st->can_be_edited_*/, st->can_change_info_,
st->can_post_messages_, st->can_edit_messages_, st->can_delete_messages_, st->can_invite_users_,
st->can_restrict_members_, st->can_pin_messages_, st->can_promote_members_);
st->can_restrict_members_, st->can_pin_messages_, st->can_promote_members_, st->can_manage_calls_);
}
case td_api::chatMemberStatusMember::ID:
return DialogParticipantStatus::Member();
@ -437,10 +445,12 @@ DialogParticipantStatus get_dialog_participant_status(bool can_be_edited,
bool can_restrict_members = (admin_rights->flags_ & telegram_api::chatAdminRights::BAN_USERS_MASK) != 0;
bool can_pin_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::PIN_MESSAGES_MASK) != 0;
bool can_promote_members = (admin_rights->flags_ & telegram_api::chatAdminRights::ADD_ADMINS_MASK) != 0;
bool can_manage_calls = (admin_rights->flags_ & telegram_api::chatAdminRights::MANAGE_CALL_MASK) != 0;
bool is_anonymous = (admin_rights->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
return DialogParticipantStatus::Administrator(
is_anonymous, std::move(rank), can_be_edited, can_change_info, can_post_messages, can_edit_messages,
can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members);
return DialogParticipantStatus::Administrator(is_anonymous, std::move(rank), can_be_edited, can_change_info,
can_post_messages, can_edit_messages, can_delete_messages,
can_invite_users, can_restrict_members, can_pin_messages,
can_promote_members, can_manage_calls);
}
DialogParticipantStatus get_dialog_participant_status(

View File

@ -118,6 +118,7 @@ class DialogParticipantStatus {
static constexpr uint32 CAN_RESTRICT_MEMBERS = 1 << 6;
static constexpr uint32 CAN_PIN_MESSAGES_ADMIN = 1 << 7;
static constexpr uint32 CAN_PROMOTE_MEMBERS = 1 << 8;
static constexpr uint32 CAN_MANAGE_CALLS = 1 << 9;
static constexpr uint32 CAN_BE_EDITED = 1 << 15;
@ -143,7 +144,7 @@ class DialogParticipantStatus {
static constexpr uint32 ALL_ADMINISTRATOR_RIGHTS =
CAN_CHANGE_INFO_AND_SETTINGS_ADMIN | CAN_POST_MESSAGES | CAN_EDIT_MESSAGES | CAN_DELETE_MESSAGES |
CAN_INVITE_USERS_ADMIN | CAN_RESTRICT_MEMBERS | CAN_PIN_MESSAGES_ADMIN | CAN_PROMOTE_MEMBERS;
CAN_INVITE_USERS_ADMIN | CAN_RESTRICT_MEMBERS | CAN_PIN_MESSAGES_ADMIN | CAN_PROMOTE_MEMBERS | CAN_MANAGE_CALLS;
static constexpr uint32 ALL_ADMIN_PERMISSION_RIGHTS =
CAN_CHANGE_INFO_AND_SETTINGS_BANNED | CAN_INVITE_USERS_BANNED | CAN_PIN_MESSAGES_BANNED;
@ -171,7 +172,7 @@ class DialogParticipantStatus {
static DialogParticipantStatus Administrator(bool is_anonymous, string rank, bool can_be_edited, 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_promote_members, bool can_manage_calls);
static DialogParticipantStatus Member();
@ -237,6 +238,10 @@ class DialogParticipantStatus {
return (flags_ & CAN_PROMOTE_MEMBERS) != 0;
}
bool can_manage_calls() const {
return (flags_ & CAN_MANAGE_CALLS) != 0;
}
bool can_be_edited() const {
return (flags_ & CAN_BE_EDITED) != 0;
}

View File

@ -265,11 +265,13 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
if (document_type != Document::Type::VoiceNote) {
for (auto &thumb : document->thumbs_) {
auto photo_size =
get_photo_size(td_->file_manager_.get(), {FileType::Thumbnail, 0}, id, access_hash, file_reference,
DcId::create(dc_id), owner_dialog_id, std::move(thumb), thumbnail_format);
auto photo_size = get_photo_size(td_->file_manager_.get(), {FileType::Thumbnail, 0}, id, access_hash,
file_reference, DcId::create(dc_id), owner_dialog_id, std::move(thumb),
thumbnail_format, document_type != Document::Type::Sticker);
if (photo_size.get_offset() == 0) {
thumbnail = std::move(photo_size.get<0>());
if (!thumbnail.file_id.is_valid()) {
thumbnail = std::move(photo_size.get<0>());
}
} else {
minithumbnail = std::move(photo_size.get<1>());
}
@ -433,8 +435,8 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
std::move(mime_type), !is_web);
break;
case Document::Type::Sticker:
td_->stickers_manager_->create_sticker(file_id, std::move(thumbnail), dimensions, std::move(sticker),
is_animated_sticker, load_data_multipromise_ptr);
td_->stickers_manager_->create_sticker(file_id, std::move(minithumbnail), std::move(thumbnail), dimensions,
std::move(sticker), is_animated_sticker, load_data_multipromise_ptr);
break;
case Document::Type::Video:
td_->videos_manager_->create_video(file_id, std::move(minithumbnail), std::move(thumbnail),

View File

@ -957,7 +957,7 @@ tl_object_ptr<td_api::photo> copy(const td_api::photo &obj) {
template <>
tl_object_ptr<td_api::sticker> copy(const td_api::sticker &obj) {
return make_tl_object<td_api::sticker>(obj.set_id_, obj.width_, obj.height_, obj.emoji_, obj.is_animated_,
obj.is_mask_, copy(obj.mask_position_), copy(obj.thumbnail_),
obj.is_mask_, copy(obj.mask_position_), obj.cover_, copy(obj.thumbnail_),
copy(obj.sticker_));
}

View File

@ -0,0 +1,25 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// 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/InputGroupCallId.h"
#include "td/utils/logging.h"
namespace td {
InputGroupCallId::InputGroupCallId(const tl_object_ptr<telegram_api::inputGroupCall> &input_group_call)
: group_call_id(input_group_call->id_), access_hash(input_group_call->access_hash_) {
}
tl_object_ptr<telegram_api::inputGroupCall> InputGroupCallId::get_input_group_call() const {
return make_tl_object<telegram_api::inputGroupCall>(group_call_id, access_hash);
}
StringBuilder &operator<<(StringBuilder &string_builder, InputGroupCallId input_group_call_id) {
return string_builder << "input group call " << input_group_call_id.group_call_id;
}
} // namespace td

View File

@ -0,0 +1,54 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// 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"
namespace td {
class InputGroupCallId {
int64 group_call_id = 0;
int64 access_hash = 0;
public:
InputGroupCallId() = default;
explicit InputGroupCallId(const tl_object_ptr<telegram_api::inputGroupCall> &input_group_call);
bool operator==(const InputGroupCallId &other) const {
return group_call_id == other.group_call_id && access_hash == other.access_hash;
}
bool operator!=(const InputGroupCallId &other) const {
return !(*this == other);
}
bool is_valid() const {
return group_call_id != 0;
}
tl_object_ptr<telegram_api::inputGroupCall> get_input_group_call() const;
template <class StorerT>
void store(StorerT &storer) const {
storer.store_long(group_call_id);
storer.store_long(access_hash);
}
template <class ParserT>
void parse(ParserT &parser) {
group_call_id = parser.fetch_long();
access_hash = parser.fetch_long();
}
friend StringBuilder &operator<<(StringBuilder &string_builder, InputGroupCallId input_group_call_id);
};
} // namespace td

View File

@ -28,6 +28,7 @@
#include "td/telegram/Game.hpp"
#include "td/telegram/Global.h"
#include "td/telegram/HashtagHints.h"
#include "td/telegram/InputGroupCallId.h"
#include "td/telegram/InputMessageText.h"
#include "td/telegram/Location.h"
#include "td/telegram/MessageEntity.h"
@ -688,6 +689,8 @@ class MessageDice : public MessageContent {
}
};
constexpr const char *MessageDice::DEFAULT_EMOJI;
class MessageProximityAlertTriggered : public MessageContent {
public:
DialogId traveler_dialog_id;
@ -704,7 +707,34 @@ class MessageProximityAlertTriggered : public MessageContent {
}
};
constexpr const char *MessageDice::DEFAULT_EMOJI;
class MessageGroupCall : public MessageContent {
public:
InputGroupCallId group_call_id;
int32 duration = -1;
MessageGroupCall() = default;
MessageGroupCall(InputGroupCallId group_call_id, int32 duration) : group_call_id(group_call_id), duration(duration) {
}
MessageContentType get_type() const override {
return MessageContentType::GroupCall;
}
};
class MessageInviteToGroupCall : public MessageContent {
public:
InputGroupCallId group_call_id;
UserId user_id;
MessageInviteToGroupCall() = default;
MessageInviteToGroupCall(InputGroupCallId group_call_id, UserId user_id)
: group_call_id(group_call_id), user_id(user_id) {
}
MessageContentType get_type() const override {
return MessageContentType::InviteToGroupCall;
}
};
template <class StorerT>
static void store(const MessageContent *content, StorerT &storer) {
@ -978,6 +1008,24 @@ static void store(const MessageContent *content, StorerT &storer) {
store(m->distance, storer);
break;
}
case MessageContentType::GroupCall: {
auto m = static_cast<const MessageGroupCall *>(content);
bool has_duration = m->duration >= 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_duration);
END_STORE_FLAGS();
store(m->group_call_id, storer);
if (has_duration) {
store(m->duration, storer);
}
break;
}
case MessageContentType::InviteToGroupCall: {
auto m = static_cast<const MessageInviteToGroupCall *>(content);
store(m->group_call_id, storer);
store(m->user_id, storer);
break;
}
default:
UNREACHABLE();
}
@ -1352,6 +1400,26 @@ static void parse(unique_ptr<MessageContent> &content, ParserT &parser) {
content = std::move(m);
break;
}
case MessageContentType::GroupCall: {
auto m = make_unique<MessageGroupCall>();
bool has_duration;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_duration);
END_PARSE_FLAGS();
parse(m->group_call_id, parser);
if (has_duration) {
parse(m->duration, parser);
}
content = std::move(m);
break;
}
case MessageContentType::InviteToGroupCall: {
auto m = make_unique<MessageInviteToGroupCall>();
parse(m->group_call_id, parser);
parse(m->user_id, parser);
content = std::move(m);
break;
}
default:
LOG(FATAL) << "Have unknown message content type " << static_cast<int32>(content_type);
}
@ -1638,8 +1706,9 @@ static Result<InputMessageContent> create_input_message_content(
}
case td_api::inputMessageSticker::ID: {
auto input_sticker = static_cast<td_api::inputMessageSticker *>(input_message_content.get());
td->stickers_manager_->create_sticker(
file_id, thumbnail, get_dimensions(input_sticker->width_, input_sticker->height_), nullptr, false, nullptr);
td->stickers_manager_->create_sticker(file_id, string(), thumbnail,
get_dimensions(input_sticker->width_, input_sticker->height_), nullptr,
false, nullptr);
content = make_unique<MessageSticker>(file_id);
break;
@ -2047,6 +2116,8 @@ bool can_have_input_media(const Td *td, const MessageContent *content) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
case MessageContentType::Animation:
case MessageContentType::Audio:
@ -2160,6 +2231,8 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
break;
default:
UNREACHABLE();
@ -2350,6 +2423,8 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
break;
default:
UNREACHABLE();
@ -2473,6 +2548,8 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) {
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
break;
default:
UNREACHABLE();
@ -2597,6 +2674,8 @@ static int32 get_message_content_media_index_mask(const MessageContent *content,
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return 0;
default:
UNREACHABLE();
@ -3218,6 +3297,22 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
}
break;
}
case MessageContentType::GroupCall: {
auto old_ = static_cast<const MessageGroupCall *>(old_content);
auto new_ = static_cast<const MessageGroupCall *>(new_content);
if (old_->group_call_id != new_->group_call_id || old_->duration != new_->duration) {
need_update = true;
}
break;
}
case MessageContentType::InviteToGroupCall: {
auto old_ = static_cast<const MessageInviteToGroupCall *>(old_content);
auto new_ = static_cast<const MessageInviteToGroupCall *>(new_content);
if (old_->group_call_id != new_->group_call_id || old_->user_id != new_->user_id) {
need_update = true;
}
break;
}
case MessageContentType::Unsupported: {
auto old_ = static_cast<const MessageUnsupported *>(old_content);
auto new_ = static_cast<const MessageUnsupported *>(new_content);
@ -3351,6 +3446,8 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
LOG(ERROR) << "Receive new file " << new_file_id << " in a sent message of the type " << content_type;
break;
default:
@ -4244,6 +4341,8 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return nullptr;
default:
UNREACHABLE();
@ -4438,6 +4537,28 @@ unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<tele
return make_unique<MessageProximityAlertTriggered>(traveler_id, watcher_id, distance);
}
case telegram_api::messageActionGroupCall::ID: {
auto group_call = move_tl_object_as<telegram_api::messageActionGroupCall>(action);
int32 duration = -1;
if ((group_call->flags_ & telegram_api::messageActionGroupCall::DURATION_MASK) != 0) {
duration = group_call->duration_;
if (duration < 0) {
LOG(ERROR) << "Receive invalid " << oneline(to_string(group_call));
break;
}
}
return make_unique<MessageGroupCall>(InputGroupCallId(group_call->call_), duration);
}
case telegram_api::messageActionInviteToGroupCall::ID: {
auto invite_to_group_call = move_tl_object_as<telegram_api::messageActionInviteToGroupCall>(action);
UserId user_id(invite_to_group_call->user_id_);
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive messageActionInviteToGroupCall with invalid " << user_id << " in " << owner_dialog_id;
break;
}
return make_unique<MessageInviteToGroupCall>(InputGroupCallId(invite_to_group_call->call_), user_id);
}
default:
UNREACHABLE();
}
@ -4647,6 +4768,10 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
td->messages_manager_->get_message_sender_object(m->traveler_dialog_id),
td->messages_manager_->get_message_sender_object(m->watcher_dialog_id), m->distance);
}
case MessageContentType::GroupCall:
return make_tl_object<td_api::messageGroupCall>();
case MessageContentType::InviteToGroupCall:
return make_tl_object<td_api::messageInviteToGroupCall>();
default:
UNREACHABLE();
return nullptr;
@ -4959,6 +5084,8 @@ string get_message_content_search_text(const Td *td, const MessageContent *conte
case MessageContentType::PassportDataReceived:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return string();
default:
UNREACHABLE();
@ -5158,6 +5285,13 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC
add_message_sender_dependencies(dependencies, content->watcher_dialog_id);
break;
}
case MessageContentType::GroupCall:
break;
case MessageContentType::InviteToGroupCall: {
auto content = static_cast<const MessageInviteToGroupCall *>(message_content);
dependencies.user_ids.insert(content->user_id);
break;
}
default:
UNREACHABLE();
break;

View File

@ -98,6 +98,10 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType cont
return string_builder << "Dice";
case MessageContentType::ProximityAlertTriggered:
return string_builder << "ProximityAlertTriggered";
case MessageContentType::GroupCall:
return string_builder << "GroupCall";
case MessageContentType::InviteToGroupCall:
return string_builder << "InviteToGroupCall";
default:
UNREACHABLE();
return string_builder;
@ -150,6 +154,8 @@ bool is_allowed_media_group_content(MessageContentType content_type) {
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
default:
UNREACHABLE();
@ -210,6 +216,8 @@ bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
default:
UNREACHABLE();
@ -263,6 +271,8 @@ bool is_service_message_content(MessageContentType content_type) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return true;
default:
UNREACHABLE();
@ -316,6 +326,8 @@ bool can_have_message_content_caption(MessageContentType content_type) {
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
default:
UNREACHABLE();

View File

@ -57,7 +57,9 @@ enum class MessageContentType : int32 {
PassportDataReceived,
Poll,
Dice,
ProximityAlertTriggered
ProximityAlertTriggered,
GroupCall,
InviteToGroupCall
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);

View File

@ -22833,6 +22833,8 @@ Status MessagesManager::can_send_message_content(DialogId dialog_id, const Messa
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
UNREACHABLE();
}
return Status::OK();
@ -24406,6 +24408,8 @@ bool MessagesManager::can_edit_message(DialogId dialog_id, const Message *m, boo
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
case MessageContentType::GroupCall:
case MessageContentType::InviteToGroupCall:
return false;
default:
UNREACHABLE();

View File

@ -358,7 +358,7 @@ PhotoSize get_secret_thumbnail_photo_size(FileManager *file_manager, BufferSlice
Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSource source, int64 id,
int64 access_hash, std::string file_reference, DcId dc_id,
DialogId owner_dialog_id, tl_object_ptr<telegram_api::PhotoSize> &&size_ptr,
PhotoFormat format) {
PhotoFormat format, bool expect_jpeg_minithumbnail) {
CHECK(size_ptr != nullptr);
tl_object_ptr<telegram_api::fileLocationToBeDeprecated> location;
@ -393,6 +393,10 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
}
case telegram_api::photoStrippedSize::ID: {
auto size = move_tl_object_as<telegram_api::photoStrippedSize>(size_ptr);
if (!expect_jpeg_minithumbnail) {
LOG(ERROR) << "Receive unexpected JPEG minithumbnail";
return std::move(res);
}
return size->bytes_.as_slice().str();
}
case telegram_api::photoSizeProgressive::ID: {
@ -413,6 +417,14 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
break;
}
case telegram_api::photoPathSize::ID: {
auto size = move_tl_object_as<telegram_api::photoPathSize>(size_ptr);
if (expect_jpeg_minithumbnail) {
LOG(ERROR) << "Receive unexpected SVG minithumbnail";
return std::move(res);
}
return size->bytes_.as_slice().str();
}
default:
UNREACHABLE();
break;
@ -707,7 +719,7 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
for (auto &size_ptr : photo->sizes_) {
auto photo_size = get_photo_size(file_manager, {FileType::Photo, 0}, photo->id_, photo->access_hash_,
photo->file_reference_.as_slice().str(), dc_id, owner_dialog_id,
std::move(size_ptr), PhotoFormat::Jpeg);
std::move(size_ptr), PhotoFormat::Jpeg, true);
if (photo_size.get_offset() == 0) {
PhotoSize &size = photo_size.get<0>();
if (size.type == 0 || size.type == 't' || size.type == 'i' || size.type == 'u' || size.type == 'v') {

View File

@ -113,7 +113,7 @@ PhotoSize get_secret_thumbnail_photo_size(FileManager *file_manager, BufferSlice
Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSource source, int64 id,
int64 access_hash, string file_reference, DcId dc_id,
DialogId owner_dialog_id, tl_object_ptr<telegram_api::PhotoSize> &&size_ptr,
PhotoFormat format);
PhotoFormat format, bool expect_jpeg_minithumbnail);
AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource source, int64 id, int64 access_hash,
string file_reference, DcId dc_id, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::videoSize> &&size);

View File

@ -1336,6 +1336,40 @@ tl_object_ptr<td_api::MaskPoint> StickersManager::get_mask_point_object(int32 po
}
}
string StickersManager::get_sticker_minithumbnail(const string &path) {
if (path.empty()) {
return string();
}
const auto prefix = Slice(
"<?xml version=\"1.0\" encoding=\"utf-8\"?><svg version=\"1.1\" id=\"Layer_1\" "
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" "
"viewBox=\"0 0 512 512\" style=\"enable-background:new 0 0 512 512;\" xml:space=\"preserve\"><style "
"type=\"text/css\">.st0{fill:#E8E8E8;}</style><path class=\"st0\" d=\"M");
const auto suffix = Slice("z\"/></svg>");
auto buf = StackAllocator::alloc(1 << 7);
StringBuilder sb(buf.as_slice(), true);
sb << prefix;
for (unsigned char c : path) {
if (c >= 128 + 64) {
sb << "AACAAAAHAAALMAAAQASTAVAAAZaacaaaahaaalmaaaqastava.az0123456789-,"[c - 128 - 64];
} else {
if (c >= 128) {
sb << ',';
} else if (c >= 64) {
sb << '-';
}
sb << (c & 63);
}
}
sb << suffix;
CHECK(!sb.is_error());
return sb.as_cslice().str();
}
tl_object_ptr<td_api::sticker> StickersManager::get_sticker_object(FileId file_id) const {
if (!file_id.is_valid()) {
return nullptr;
@ -1372,7 +1406,8 @@ tl_object_ptr<td_api::sticker> StickersManager::get_sticker_object(FileId file_i
auto thumbnail_object = get_thumbnail_object(td_->file_manager_.get(), thumbnail, thumbnail_format);
return make_tl_object<td_api::sticker>(sticker->set_id.get(), sticker->dimensions.width, sticker->dimensions.height,
sticker->alt, sticker->is_animated, sticker->is_mask, std::move(mask_position),
std::move(thumbnail_object), td_->file_manager_->get_file_object(file_id));
get_sticker_minithumbnail(sticker->minithumbnail), std::move(thumbnail_object),
td_->file_manager_->get_file_object(file_id));
}
tl_object_ptr<td_api::stickers> StickersManager::get_stickers_object(const vector<FileId> &sticker_ids) const {
@ -1559,19 +1594,24 @@ FileId StickersManager::on_get_sticker(unique_ptr<Sticker> new_sticker, bool rep
}
if (s->alt != new_sticker->alt && !new_sticker->alt.empty()) {
LOG(DEBUG) << "Sticker " << file_id << " emoji has changed";
s->alt = new_sticker->alt;
s->alt = std::move(new_sticker->alt);
s->is_changed = true;
}
if (s->minithumbnail != new_sticker->minithumbnail) {
LOG(DEBUG) << "Sticker " << file_id << " minithumbnail has changed";
s->minithumbnail = std::move(new_sticker->minithumbnail);
s->is_changed = true;
}
if (s->s_thumbnail != new_sticker->s_thumbnail && new_sticker->s_thumbnail.file_id.is_valid()) {
LOG_IF(INFO, s->s_thumbnail.file_id.is_valid()) << "Sticker " << file_id << " s thumbnail has changed from "
<< s->s_thumbnail << " to " << new_sticker->s_thumbnail;
s->s_thumbnail = new_sticker->s_thumbnail;
s->s_thumbnail = std::move(new_sticker->s_thumbnail);
s->is_changed = true;
}
if (s->m_thumbnail != new_sticker->m_thumbnail && new_sticker->m_thumbnail.file_id.is_valid()) {
LOG_IF(INFO, s->m_thumbnail.file_id.is_valid()) << "Sticker " << file_id << " m thumbnail has changed from "
<< s->m_thumbnail << " to " << new_sticker->m_thumbnail;
s->m_thumbnail = new_sticker->m_thumbnail;
s->m_thumbnail = std::move(new_sticker->m_thumbnail);
s->is_changed = true;
}
if (s->is_animated != new_sticker->is_animated && new_sticker->is_animated) {
@ -1647,20 +1687,24 @@ std::pair<int64, FileId> StickersManager::on_get_sticker_document(
PSTRING() << document_id << (is_animated ? ".tgs" : ".webp"));
PhotoSize thumbnail;
string minithumbnail;
for (auto &thumb : document->thumbs_) {
auto photo_size =
get_photo_size(td_->file_manager_.get(), {FileType::Thumbnail, 0}, document_id, document->access_hash_,
document->file_reference_.as_slice().str(), dc_id, DialogId(), std::move(thumb),
has_webp_thumbnail(sticker) ? PhotoFormat::Webp : PhotoFormat::Jpeg);
has_webp_thumbnail(sticker) ? PhotoFormat::Webp : PhotoFormat::Jpeg, false);
if (photo_size.get_offset() == 0) {
thumbnail = std::move(photo_size.get<0>());
if (!thumbnail.file_id.is_valid()) {
thumbnail = std::move(photo_size.get<0>());
}
break;
} else {
LOG(ERROR) << "Receive minithumbnail for a sticker " << sticker_id << ": " << to_string(sticker);
minithumbnail = std::move(photo_size.get<1>());
}
}
create_sticker(sticker_id, std::move(thumbnail), dimensions, std::move(sticker), is_animated, nullptr);
create_sticker(sticker_id, std::move(minithumbnail), std::move(thumbnail), dimensions, std::move(sticker),
is_animated, nullptr);
return {document_id, sticker_id};
}
@ -1983,7 +2027,7 @@ void StickersManager::add_sticker_thumbnail(Sticker *s, PhotoSize thumbnail) {
LOG(ERROR) << "Receive sticker thumbnail of unsupported type " << thumbnail.type;
}
void StickersManager::create_sticker(FileId file_id, PhotoSize thumbnail, Dimensions dimensions,
void StickersManager::create_sticker(FileId file_id, string minithumbnail, PhotoSize thumbnail, Dimensions dimensions,
tl_object_ptr<telegram_api::documentAttributeSticker> sticker, bool is_animated,
MultiPromiseActor *load_data_multipromise_ptr) {
if (is_animated && dimensions.width == 0) {
@ -1994,6 +2038,7 @@ void StickersManager::create_sticker(FileId file_id, PhotoSize thumbnail, Dimens
auto s = make_unique<Sticker>();
s->file_id = file_id;
s->dimensions = dimensions;
s->minithumbnail = std::move(minithumbnail);
add_sticker_thumbnail(s.get(), thumbnail);
if (sticker != nullptr) {
s->set_id = on_get_input_sticker_set(file_id, std::move(sticker->stickerset_), load_data_multipromise_ptr);
@ -2185,14 +2230,17 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
bool is_masks = (set->flags_ & telegram_api::stickerSet::MASKS_MASK) != 0;
PhotoSize thumbnail;
string minithumbnail;
if (set->thumb_ != nullptr) {
auto photo_size = get_photo_size(td_->file_manager_.get(), {set_id.get(), s->access_hash}, 0, 0, "",
DcId::create(set->thumb_dc_id_), DialogId(), std::move(set->thumb_),
is_animated ? PhotoFormat::Tgs : PhotoFormat::Webp);
is_animated ? PhotoFormat::Tgs : PhotoFormat::Webp, false);
if (photo_size.get_offset() == 0) {
thumbnail = std::move(photo_size.get<0>());
if (!thumbnail.file_id.is_valid()) {
thumbnail = std::move(photo_size.get<0>());
}
} else {
LOG(ERROR) << "Receive minithumbnail for a " << set_id;
minithumbnail = std::move(photo_size.get<1>());
}
}
if (!s->is_inited) {
@ -2200,9 +2248,10 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
s->is_inited = true;
s->title = std::move(set->title_);
s->short_name = std::move(set->short_name_);
s->minithumbnail = std::move(minithumbnail);
s->thumbnail = std::move(thumbnail);
s->is_thumbnail_reloaded = true;
s->are_legacy_thumbnails_reloaded = true;
s->are_legacy_sticker_thumbnails_reloaded = true;
s->sticker_count = set->count_;
s->hash = set->hash_;
s->is_official = is_official;
@ -2236,15 +2285,20 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
installed_sticker_sets_hints_[s->is_masks].add(set_id.get(), PSLICE() << s->title << ' ' << s->short_name);
}
}
if (s->minithumbnail != minithumbnail) {
LOG(INFO) << "Minithumbnail of " << set_id << " has changed";
s->minithumbnail = std::move(minithumbnail);
s->is_changed = true;
}
if (s->thumbnail != thumbnail) {
LOG(INFO) << "Thumbnail of " << set_id << " has changed from " << s->thumbnail << " to " << thumbnail;
s->thumbnail = std::move(thumbnail);
s->is_changed = true;
}
if (!s->is_thumbnail_reloaded || !s->are_legacy_thumbnails_reloaded) {
if (!s->is_thumbnail_reloaded || !s->are_legacy_sticker_thumbnails_reloaded) {
LOG(INFO) << "Sticker thumbnails and thumbnail of " << set_id << " was reloaded";
s->is_thumbnail_reloaded = true;
s->are_legacy_thumbnails_reloaded = true;
s->are_legacy_sticker_thumbnails_reloaded = true;
s->need_save_to_database = true;
}
@ -3426,7 +3480,7 @@ void StickersManager::on_load_sticker_set_from_database(StickerSetId sticker_set
<< format::as_hex_dump<4>(Slice(value));
}
}
if (!sticker_set->is_thumbnail_reloaded || !sticker_set->are_legacy_thumbnails_reloaded) {
if (!sticker_set->is_thumbnail_reloaded || !sticker_set->are_legacy_sticker_thumbnails_reloaded) {
do_reload_sticker_set(sticker_set_id, get_input_sticker_set(sticker_set), Auto());
}
@ -4323,7 +4377,7 @@ Result<std::tuple<FileId, bool, bool, bool>> StickersManager::prepare_input_file
if (is_animated) {
int32 width = for_thumbnail ? 100 : 512;
create_sticker(file_id, PhotoSize(), get_dimensions(width, width), nullptr, true, nullptr);
create_sticker(file_id, string(), PhotoSize(), get_dimensions(width, width), nullptr, true, nullptr);
} else {
td_->documents_manager_->create_document(file_id, string(), PhotoSize(), "sticker.png", "image/png", false);
}

View File

@ -73,7 +73,7 @@ class StickersManager : public Actor {
void unregister_dice(const string &emoji, int32 value, FullMessageId full_message_id, const char *source);
void create_sticker(FileId file_id, PhotoSize thumbnail, Dimensions dimensions,
void create_sticker(FileId file_id, string minithumbnail, PhotoSize thumbnail, Dimensions dimensions,
tl_object_ptr<telegram_api::documentAttributeSticker> sticker, bool is_animated,
MultiPromiseActor *load_data_multipromise_ptr);
@ -308,6 +308,7 @@ class StickersManager : public Actor {
StickerSetId set_id;
string alt;
Dimensions dimensions;
string minithumbnail;
PhotoSize s_thumbnail;
PhotoSize m_thumbnail;
FileId file_id;
@ -335,6 +336,7 @@ class StickersManager : public Actor {
int32 hash = 0;
int32 expires_at = 0;
string minithumbnail;
PhotoSize thumbnail;
vector<FileId> sticker_ids;
@ -348,7 +350,7 @@ class StickersManager : public Actor {
bool is_masks = false;
bool is_viewed = true;
bool is_thumbnail_reloaded = false;
bool are_legacy_thumbnails_reloaded = false;
bool are_legacy_sticker_thumbnails_reloaded = false;
mutable bool was_update_sent = false; // does the sticker set is known to the client
bool is_changed = true; // have new changes that need to be sent to the client and database
bool need_save_to_database = true; // have new changes that need only to be saved to the database
@ -395,6 +397,8 @@ class StickersManager : public Actor {
class UploadStickerFileCallback;
static string get_sticker_minithumbnail(const string &path);
static tl_object_ptr<td_api::MaskPoint> get_mask_point_object(int32 point);
tl_object_ptr<td_api::stickerSetInfo> get_sticker_set_info_object(StickerSetId sticker_set_id,

View File

@ -27,11 +27,13 @@ void StickersManager::store_sticker(FileId file_id, bool in_sticker_set, StorerT
}
const Sticker *sticker = it->second.get();
bool has_sticker_set_access_hash = sticker->set_id.is_valid() && !in_sticker_set;
bool has_minithumbnail = !sticker->minithumbnail.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(sticker->is_mask);
STORE_FLAG(has_sticker_set_access_hash);
STORE_FLAG(in_sticker_set);
STORE_FLAG(sticker->is_animated);
STORE_FLAG(has_minithumbnail);
END_STORE_FLAGS();
if (!in_sticker_set) {
store(sticker->set_id.get(), storer);
@ -53,6 +55,9 @@ void StickersManager::store_sticker(FileId file_id, bool in_sticker_set, StorerT
store(sticker->y_shift, storer);
store(sticker->scale, storer);
}
if (has_minithumbnail) {
store(sticker->minithumbnail, storer);
}
}
template <class ParserT>
@ -64,11 +69,13 @@ FileId StickersManager::parse_sticker(bool in_sticker_set, ParserT &parser) {
auto sticker = make_unique<Sticker>();
bool has_sticker_set_access_hash;
bool in_sticker_set_stored;
bool has_minithumbnail;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(sticker->is_mask);
PARSE_FLAG(has_sticker_set_access_hash);
PARSE_FLAG(in_sticker_set_stored);
PARSE_FLAG(sticker->is_animated);
PARSE_FLAG(has_minithumbnail);
END_PARSE_FLAGS();
if (in_sticker_set_stored != in_sticker_set) {
Slice data = parser.template fetch_string_raw<Slice>(parser.get_left_len());
@ -108,6 +115,9 @@ FileId StickersManager::parse_sticker(bool in_sticker_set, ParserT &parser) {
parse(sticker->y_shift, parser);
parse(sticker->scale, parser);
}
if (has_minithumbnail) {
parse(sticker->minithumbnail, parser);
}
if (parser.get_error() != nullptr || !sticker->file_id.is_valid()) {
return FileId();
}
@ -122,6 +132,7 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
bool is_loaded = sticker_set->is_loaded && is_full;
bool has_expires_at = !sticker_set->is_installed && sticker_set->expires_at != 0;
bool has_thumbnail = sticker_set->thumbnail.file_id.is_valid();
bool has_minithumbnail = !sticker_set->minithumbnail.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(sticker_set->is_inited);
STORE_FLAG(was_loaded);
@ -135,7 +146,8 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
STORE_FLAG(has_thumbnail);
STORE_FLAG(sticker_set->is_thumbnail_reloaded);
STORE_FLAG(sticker_set->is_animated);
STORE_FLAG(sticker_set->are_legacy_thumbnails_reloaded);
STORE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded);
STORE_FLAG(has_minithumbnail);
END_STORE_FLAGS();
store(sticker_set->id.get(), storer);
store(sticker_set->access_hash, storer);
@ -150,6 +162,9 @@ void StickersManager::store_sticker_set(const StickerSet *sticker_set, bool with
if (has_thumbnail) {
store(sticker_set->thumbnail, storer);
}
if (has_minithumbnail) {
store(sticker_set->minithumbnail, storer);
}
uint32 stored_sticker_count = narrow_cast<uint32>(is_full ? sticker_set->sticker_ids.size() : stickers_limit);
store(stored_sticker_count, storer);
@ -180,9 +195,10 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
bool is_archived;
bool is_official;
bool is_masks;
bool is_animated;
bool has_expires_at;
bool has_thumbnail;
bool is_animated;
bool has_minithumbnail;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(sticker_set->is_inited);
PARSE_FLAG(sticker_set->was_loaded);
@ -196,7 +212,8 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
PARSE_FLAG(has_thumbnail);
PARSE_FLAG(sticker_set->is_thumbnail_reloaded);
PARSE_FLAG(is_animated);
PARSE_FLAG(sticker_set->are_legacy_thumbnails_reloaded);
PARSE_FLAG(sticker_set->are_legacy_sticker_thumbnails_reloaded);
PARSE_FLAG(has_minithumbnail);
END_PARSE_FLAGS();
int64 sticker_set_id;
int64 access_hash;
@ -211,6 +228,8 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
if (sticker_set->is_inited) {
string title;
string short_name;
string minithumbnail;
PhotoSize thumbnail;
int32 sticker_count;
int32 hash;
int32 expires_at = 0;
@ -222,11 +241,17 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
parse(expires_at, parser);
}
if (has_thumbnail) {
parse(sticker_set->thumbnail, parser);
parse(thumbnail, parser);
}
if (has_minithumbnail) {
parse(minithumbnail, parser);
}
if (!was_inited) {
sticker_set->title = std::move(title);
sticker_set->short_name = std::move(short_name);
sticker_set->minithumbnail = std::move(minithumbnail);
sticker_set->thumbnail = std::move(thumbnail);
sticker_set->sticker_count = sticker_count;
sticker_set->hash = hash;
sticker_set->expires_at = expires_at;

View File

@ -557,6 +557,7 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
case telegram_api::messageActionSecureValuesSent::ID:
case telegram_api::messageActionSecureValuesSentMe::ID:
case telegram_api::messageActionContactSignUp::ID:
case telegram_api::messageActionGroupCall::ID:
break;
case telegram_api::messageActionChatCreate::ID: {
auto chat_create = static_cast<const telegram_api::messageActionChatCreate *>(action);
@ -614,6 +615,13 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
}
break;
}
case telegram_api::messageActionInviteToGroupCall::ID: {
auto invite_to_group_call = static_cast<const telegram_api::messageActionInviteToGroupCall *>(action);
if (!is_acceptable_user(UserId(invite_to_group_call->user_id_))) {
return false;
}
break;
}
default:
UNREACHABLE();
return false;
@ -2173,4 +2181,10 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelParticip
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateTheme> update, bool /*force_apply*/) {
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update, bool /*force_apply*/) {
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> update, bool /*force_apply*/) {
}
} // namespace td

View File

@ -318,6 +318,10 @@ class UpdatesManager : public Actor {
// unsupported updates
void on_update(tl_object_ptr<telegram_api::updateTheme> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateGroupCall> update, bool /*force_apply*/);
};
} // namespace td

View File

@ -8,7 +8,7 @@
namespace td {
constexpr int32 MTPROTO_LAYER = 120;
constexpr int32 MTPROTO_LAYER = 122;
enum class Version : int32 {
Initial, // 0

View File

@ -1196,6 +1196,9 @@ class CliClient final : public Actor {
if (action == "uvn" || action == "upload_video_note") {
return td_api::make_object<td_api::chatActionUploadingVideoNote>(50);
}
if (action == "sic" || action == "speaking_in_call") {
return td_api::make_object<td_api::chatActionSpeakingInCall>();
}
return td_api::make_object<td_api::chatActionTyping>();
}
@ -3835,25 +3838,25 @@ class CliClient final : public Actor {
status = td_api::make_object<td_api::chatMemberStatusCreator>("", false, false);
} else if (status_str == "anon") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", true, true, true, true, true, true,
true, true, true, true);
true, true, true, false, true);
} else if (status_str == "anonadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, false, true);
false, false, false, false, false, true);
} else if (status_str == "addadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, true, false);
false, false, false, true, false, false);
} else if (status_str == "admin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, true, true, true, true,
true, true, true, false);
true, true, true, false, false);
} else if (status_str == "adminq") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("title", true, true, true, true, true, true,
true, true, true, false);
true, true, true, false, false);
} else if (status_str == "minadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, false, false, false, false,
false, false, false, false);
false, false, false, false, false);
} else if (status_str == "unadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, false, false, false, false, false,
false, false, false, false);
false, false, false, false, false);
} else if (status_str == "rest") {
status = td_api::make_object<td_api::chatMemberStatusRestricted>(
true, static_cast<int32>(120 + std::time(nullptr)),