Support media timestamp in message links.

This commit is contained in:
levlam 2021-07-26 02:40:36 +03:00
parent 8a745b3480
commit bfa0973dec
6 changed files with 64 additions and 3 deletions

View File

@ -3119,9 +3119,10 @@ messageLink link:string is_public:Bool = MessageLink;
//@is_public True, if the link is a public link for a message in a chat
//@chat_id If found, identifier of the chat to which the message belongs, 0 otherwise
//@message If found, the linked message; may be null
//@media_timestamp Timestamp from which the video/audio/video note/voice note playing should start, in seconds; 0 if not specified
//@for_album True, if the whole media album to which the message belongs is linked
//@for_comment True, if the message is linked as a channel post comment or from a message thread
messageLinkInfo is_public:Bool chat_id:int53 message:message for_album:Bool for_comment:Bool = MessageLinkInfo;
messageLinkInfo is_public:Bool chat_id:int53 message:message media_timestamp:int32 for_album:Bool for_comment:Bool = MessageLinkInfo;
//@description Contains a part of a file @data File bytes

View File

@ -1125,6 +1125,7 @@ Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
Slice channel_id_slice;
Slice message_id_slice;
Slice comment_message_id_slice = "0";
Slice media_timestamp_slice;
bool is_single = false;
bool for_comment = false;
if (link_info.is_tg_) {
@ -1167,6 +1168,9 @@ Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
message_id_slice = key_value.second;
}
}
if (key_value.first == "t") {
media_timestamp_slice = key_value.second;
}
if (key_value.first == "single") {
is_single = true;
}
@ -1206,6 +1210,9 @@ Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
auto args = full_split(url.substr(query_pos + 1), '&');
for (auto arg : args) {
auto key_value = split(arg, '=');
if (key_value.first == "t") {
media_timestamp_slice = key_value.second;
}
if (key_value.first == "single") {
is_single = true;
}
@ -1239,11 +1246,49 @@ Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
return Status::Error("Wrong comment message ID");
}
bool is_media_timestamp_invalid = false;
int32 media_timestamp = 0;
const int32 MAX_MEDIA_TIMESTAMP = 10000000;
if (!media_timestamp_slice.empty()) {
int32 current_value = 0;
for (size_t i = 0; i <= media_timestamp_slice.size(); i++) {
auto c = i < media_timestamp_slice.size() ? media_timestamp_slice[i] : 's';
if ('0' <= c && c <= '9') {
current_value = current_value * 10 + c - '0';
if (current_value > MAX_MEDIA_TIMESTAMP) {
is_media_timestamp_invalid = true;
break;
}
} else {
auto mul = 0;
switch (to_lower(c)) {
case 'h':
mul = 3600;
break;
case 'm':
mul = 60;
break;
case 's':
mul = 1;
break;
}
if (mul == 0 || current_value > MAX_MEDIA_TIMESTAMP / mul ||
media_timestamp + current_value * mul > MAX_MEDIA_TIMESTAMP) {
is_media_timestamp_invalid = true;
break;
}
media_timestamp += current_value * mul;
current_value = 0;
}
}
}
MessageLinkInfo info;
info.username = username.str();
info.channel_id = channel_id;
info.message_id = MessageId(ServerMessageId(r_message_id.ok()));
info.comment_message_id = MessageId(ServerMessageId(r_comment_message_id.ok()));
info.media_timestamp = is_media_timestamp_invalid ? 0 : media_timestamp;
info.is_single = is_single;
info.for_comment = for_comment;
LOG(INFO) << "Have link to " << info.message_id << " in chat @" << info.username << "/" << channel_id.get();

View File

@ -335,4 +335,9 @@ bool can_have_message_content_caption(MessageContentType content_type) {
}
}
bool can_have_media_timestamp(MessageContentType content_type) {
return content_type == MessageContentType::Audio || content_type == MessageContentType::Video ||
content_type == MessageContentType::VideoNote || content_type == MessageContentType::VoiceNote;
}
} // namespace td

View File

@ -75,6 +75,8 @@ bool is_service_message_content(MessageContentType content_type);
bool can_have_message_content_caption(MessageContentType content_type);
bool can_have_media_timestamp(MessageContentType content_type);
struct MessageContentTypeHash {
std::size_t operator()(MessageContentType content_type) const {
return std::hash<int32>()(static_cast<int32>(content_type));

View File

@ -21,6 +21,7 @@ struct MessageLinkInfo {
MessageId message_id;
bool is_single = false;
int32 media_timestamp = 0;
DialogId comment_dialog_id;
MessageId comment_message_id;

View File

@ -17545,6 +17545,7 @@ td_api::object_ptr<td_api::messageLinkInfo> MessagesManager::get_message_link_in
: (is_public ? resolve_dialog_username(info.username) : DialogId(info.channel_id));
MessageId message_id = info.comment_dialog_id.is_valid() ? info.comment_message_id : info.message_id;
td_api::object_ptr<td_api::message> message;
int32 media_timestamp = 0;
bool for_album = false;
bool for_comment = false;
@ -17557,11 +17558,17 @@ td_api::object_ptr<td_api::messageLinkInfo> MessagesManager::get_message_link_in
message = get_message_object(dialog_id, m);
for_album = !info.is_single && m->media_album_id != 0;
for_comment = (info.comment_dialog_id.is_valid() || info.for_comment) && m->top_thread_message_id.is_valid();
if (can_have_media_timestamp(m->content->get_type())) {
auto duration = get_message_content_duration(m->content.get(), td_);
if (duration == 0 || info.media_timestamp <= duration) {
media_timestamp = info.media_timestamp;
}
}
}
}
return td_api::make_object<td_api::messageLinkInfo>(is_public, dialog_id.get(), std::move(message), for_album,
for_comment);
return td_api::make_object<td_api::messageLinkInfo>(is_public, dialog_id.get(), std::move(message), media_timestamp,
for_album, for_comment);
}
InputDialogId MessagesManager::get_input_dialog_id(DialogId dialog_id) const {