Update layer to 128. Remove photo volume_id/local_id.

This commit is contained in:
levlam 2021-04-16 17:43:51 +03:00
parent e1ebf74398
commit 4bb76a7b6f
15 changed files with 595 additions and 208 deletions

View File

@ -19,6 +19,9 @@ ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort;
accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector<IpPort> = AccessPointRule;
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
inputPeerPhotoFileLocationLegacy#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
inputStickerSetThumbLegacy#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
---functions---
test.useError = Error;
@ -77,8 +80,8 @@ inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
inputTakeoutFileLocation#29be5899 = InputFileLocation;
inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
inputPeerPhotoFileLocation#37257e99 flags:# big:flags.0?true peer:InputPeer photo_id:long = InputFileLocation;
inputStickerSetThumb#9d84f3db stickerset:InputStickerSet thumb_version:int = InputFileLocation;
inputGroupCallStream#bba51639 call:InputGroupCall time_ms:long scale:int = InputFileLocation;
peerUser#9db1bc6d user_id:int = Peer;
@ -100,7 +103,7 @@ userEmpty#200250ba id:int = User;
user#938458c1 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 id:int 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<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#cc656077 flags:# has_video:flags.0?true photo_id:long photo_small:FileLocation photo_big:FileLocation stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
userStatusEmpty#9d05049 = UserStatus;
userStatusOnline#edb93949 expires:int = UserStatus;
@ -126,7 +129,7 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#4790ee05 flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#bce383d2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
@ -182,10 +185,10 @@ photoEmpty#2331b22d id:long = Photo;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
photoSize#75c78e60 type:string w:int h:int size:int = PhotoSize;
photoCachedSize#21e1ad6 type:string 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;
photoSizeProgressive#fa3efb95 type:string w:int h:int sizes:Vector<int> = PhotoSize;
photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;
geoPointEmpty#1117dd5f = GeoPoint;
@ -1078,8 +1081,6 @@ emojiURL#a575739d url:string = EmojiURL;
emojiLanguage#b3fb5361 lang_code:string = EmojiLanguage;
fileLocationToBeDeprecated#bc7fc6cd volume_id:long local_id:int = FileLocation;
folder#ff544e65 flags:# autofill_new_broadcasts:flags.0?true autofill_public_groups:flags.1?true autofill_new_correspondents:flags.2?true id:int title:string photo:flags.3?ChatPhoto = Folder;
inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer;
@ -1159,7 +1160,7 @@ stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueA
help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> psa_type:flags.1?string psa_message:flags.2?string = help.PromoData;
videoSize#e831c556 flags:# type:string location:FileLocation w:int h:int size:int video_start_ts:flags.0?double = VideoSize;
videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize;
statsGroupTopPoster#18f3d0f7 user_id:int messages:int avg_chars:int = StatsGroupTopPoster;

View File

@ -8410,8 +8410,6 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
int32 flags = telegram_api::user::ACCESS_HASH_MASK | telegram_api::user::FIRST_NAME_MASK |
telegram_api::user::APPLY_MIN_PHOTO_MASK;
int64 profile_photo_id = 0;
int64 profile_photo_volume_id = 0;
int32 profile_photo_local_id = 0;
int32 profile_photo_dc_id = 1;
string first_name;
string last_name;
@ -8428,8 +8426,6 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
}
phone_number = "42777";
profile_photo_id = 3337190045231023;
profile_photo_volume_id = 107738948;
profile_photo_local_id = 13226;
} else if (user_id == get_replies_bot_user_id()) {
flags |= telegram_api::user::USERNAME_MASK | telegram_api::user::BOT_MASK;
if (!G()->is_test_dc()) {
@ -8447,20 +8443,13 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
username = G()->is_test_dc() ? "izgroupbot" : "GroupAnonymousBot";
bot_info_version = G()->is_test_dc() ? 1 : 3;
profile_photo_id = 5159307831025969322;
profile_photo_volume_id = 806529792;
profile_photo_local_id = 188482;
}
telegram_api::object_ptr<telegram_api::userProfilePhoto> profile_photo;
if (!G()->is_test_dc() && profile_photo_id != 0) {
flags |= telegram_api::user::PHOTO_MASK;
profile_photo = telegram_api::make_object<telegram_api::userProfilePhoto>(
0, false /*ignored*/, profile_photo_id,
telegram_api::make_object<telegram_api::fileLocationToBeDeprecated>(profile_photo_volume_id,
profile_photo_local_id),
telegram_api::make_object<telegram_api::fileLocationToBeDeprecated>(profile_photo_volume_id,
profile_photo_local_id + 2),
BufferSlice(), profile_photo_dc_id);
profile_photo = telegram_api::make_object<telegram_api::userProfilePhoto>(0, false /*ignored*/, profile_photo_id,
BufferSlice(), profile_photo_dc_id);
}
auto user = telegram_api::make_object<telegram_api::user>(

View File

@ -354,16 +354,25 @@ void FileReferenceManager::reload_photo(PhotoSizeSource source, Promise<Unit> pr
switch (source.get_type()) {
case PhotoSizeSource::Type::DialogPhotoBig:
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBigLegacy:
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
send_closure(G()->contacts_manager(), &ContactsManager::reload_dialog_info, source.dialog_photo().dialog_id,
std::move(promise));
break;
case PhotoSizeSource::Type::StickerSetThumbnail:
case PhotoSizeSource::Type::StickerSetThumbnailLegacy:
case PhotoSizeSource::Type::StickerSetThumbnailVersion:
send_closure(G()->stickers_manager(), &StickersManager::reload_sticker_set,
StickerSetId(source.sticker_set_thumbnail().sticker_set_id),
source.sticker_set_thumbnail().sticker_set_access_hash, std::move(promise));
break;
default:
case PhotoSizeSource::Type::Legacy:
case PhotoSizeSource::Type::FullLegacy:
case PhotoSizeSource::Type::Thumbnail:
promise.set_error(Status::Error("Unexpected PhotoSizeSource type"));
break;
default:
UNREACHABLE();
}
}

View File

@ -3091,10 +3091,9 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
new_file_view.remote_location().get_file_reference() ||
old_file_view.main_remote_location().get_access_hash() !=
new_file_view.remote_location().get_access_hash()) {
auto volume_id = -new_file_view.remote_location().get_id();
FileId file_id = td->file_manager_->register_remote(
FullRemoteFileLocation({FileType::Photo, 'i'}, new_file_view.remote_location().get_id(),
new_file_view.remote_location().get_access_hash(), 0, volume_id, DcId::invalid(),
new_file_view.remote_location().get_access_hash(), DcId::invalid(),
new_file_view.remote_location().get_file_reference().str()),
FileLocationSource::FromServer, dialog_id, old_photo->photos.back().size, 0, "");
LOG_STATUS(td->file_manager_->merge(file_id, old_file_id));
@ -3592,16 +3591,6 @@ void unregister_message_content(Td *td, const MessageContent *content, FullMessa
template <class ToT, class FromT>
static tl_object_ptr<ToT> secret_to_telegram(FromT &from);
// fileLocationUnavailable volume_id:long local_id:int secret:long = FileLocation;
static auto secret_to_telegram(secret_api::fileLocationUnavailable &file_location) {
return make_tl_object<telegram_api::fileLocationToBeDeprecated>(file_location.volume_id_, file_location.local_id_);
}
// fileLocation dc_id:int volume_id:long local_id:int secret:long = FileLocation;
static auto secret_to_telegram(secret_api::fileLocation &file_location) {
return make_tl_object<telegram_api::fileLocationToBeDeprecated>(file_location.volume_id_, file_location.local_id_);
}
// photoSizeEmpty type:string = PhotoSize;
static auto secret_to_telegram(secret_api::photoSizeEmpty &empty) {
if (!clean_input_string(empty.type_)) {
@ -3615,9 +3604,7 @@ static auto secret_to_telegram(secret_api::photoSize &photo_size) {
if (!clean_input_string(photo_size.type_)) {
photo_size.type_.clear();
}
return make_tl_object<telegram_api::photoSize>(
photo_size.type_, secret_to_telegram<telegram_api::fileLocationToBeDeprecated>(*photo_size.location_),
photo_size.w_, photo_size.h_, photo_size.size_);
return make_tl_object<telegram_api::photoSize>(photo_size.type_, photo_size.w_, photo_size.h_, photo_size.size_);
}
// photoCachedSize type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
@ -3625,9 +3612,8 @@ static auto secret_to_telegram(secret_api::photoCachedSize &photo_size) {
if (!clean_input_string(photo_size.type_)) {
photo_size.type_.clear();
}
return make_tl_object<telegram_api::photoCachedSize>(
photo_size.type_, secret_to_telegram<telegram_api::fileLocationToBeDeprecated>(*photo_size.location_),
photo_size.w_, photo_size.h_, photo_size.bytes_.clone());
return make_tl_object<telegram_api::photoCachedSize>(photo_size.type_, photo_size.w_, photo_size.h_,
photo_size.bytes_.clone());
}
// documentAttributeImageSize w:int h:int = DocumentAttribute;

View File

@ -139,20 +139,15 @@ static StringBuilder &operator<<(StringBuilder &string_builder, PhotoFormat form
}
static FileId register_photo(FileManager *file_manager, const PhotoSizeSource &source, int64 id, int64 access_hash,
std::string file_reference,
tl_object_ptr<telegram_api::fileLocationToBeDeprecated> &&location,
DialogId owner_dialog_id, int32 file_size, DcId dc_id, PhotoFormat format) {
int32 local_id = location->local_id_;
int64 volume_id = location->volume_id_;
LOG(DEBUG) << "Receive " << format << " photo of type " << source.get_file_type() << " in [" << dc_id << ","
<< volume_id << "," << local_id << "]. Id: (" << id << ", " << access_hash << ")";
auto suggested_name = PSTRING() << static_cast<uint64>(volume_id) << "_" << static_cast<uint64>(local_id) << '.'
<< format;
std::string file_reference, DialogId owner_dialog_id, int32 file_size, DcId dc_id,
PhotoFormat format) {
LOG(DEBUG) << "Receive " << format << " photo " << id << " of type " << source.get_file_type() << " from " << dc_id;
auto suggested_name = PSTRING() << source.get_unique_name(id) << '.' << format;
auto file_location_source = owner_dialog_id.get_type() == DialogType::SecretChat ? FileLocationSource::FromUser
: FileLocationSource::FromServer;
return file_manager->register_remote(
FullRemoteFileLocation(source, id, access_hash, local_id, volume_id, dc_id, std::move(file_reference)),
file_location_source, owner_dialog_id, file_size, 0, std::move(suggested_name));
FullRemoteFileLocation(source, id, access_hash, dc_id, std::move(file_reference)), file_location_source,
owner_dialog_id, file_size, 0, std::move(suggested_name));
}
ProfilePhoto get_profile_photo(FileManager *file_manager, UserId user_id, int64 user_access_hash,
@ -171,11 +166,11 @@ ProfilePhoto get_profile_photo(FileManager *file_manager, UserId user_id, int64
result.id = profile_photo->photo_id_;
result.minithumbnail = profile_photo->stripped_thumb_.as_slice().str();
result.small_file_id =
register_photo(file_manager, {DialogId(user_id), user_access_hash, false}, result.id, 0, "",
std::move(profile_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
register_photo(file_manager, {DialogId(user_id), user_access_hash, false}, result.id, 0 /*access_hash*/,
"" /*file_reference*/, DialogId(), 0 /*file_size*/, dc_id, PhotoFormat::Jpeg);
result.big_file_id =
register_photo(file_manager, {DialogId(user_id), user_access_hash, true}, result.id, 0, "",
std::move(profile_photo->photo_big_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
register_photo(file_manager, {DialogId(user_id), user_access_hash, true}, result.id, 0 /*access_hash*/,
"" /*file_reference*/, DialogId(), 0 /*file_size*/, dc_id, PhotoFormat::Jpeg);
break;
}
default:
@ -199,17 +194,9 @@ tl_object_ptr<td_api::profilePhoto> get_profile_photo_object(FileManager *file_m
bool operator==(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
bool location_differs = lhs.small_file_id != rhs.small_file_id || lhs.big_file_id != rhs.big_file_id;
bool id_differs;
if (lhs.id == -1 && rhs.id == -1) {
// group chat photo
id_differs = location_differs;
} else {
id_differs = lhs.id != rhs.id;
}
bool id_differs = lhs.id != rhs.id;
if (location_differs) {
LOG_IF(ERROR, !id_differs) << "Photo " << lhs.id << " location has changed. First profilePhoto: " << lhs
<< ", second profilePhoto: " << rhs;
return false;
}
return lhs.has_animation == rhs.has_animation && lhs.minithumbnail == rhs.minithumbnail && !id_differs;
@ -239,11 +226,10 @@ DialogPhoto get_dialog_photo(FileManager *file_manager, DialogId dialog_id, int6
auto dc_id = DcId::create(chat_photo->dc_id_);
result.has_animation = (chat_photo->flags_ & telegram_api::chatPhoto::HAS_VIDEO_MASK) != 0;
result.minithumbnail = chat_photo->stripped_thumb_.as_slice().str();
result.small_file_id =
register_photo(file_manager, {dialog_id, dialog_access_hash, false}, 0, 0, "",
std::move(chat_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
result.big_file_id = register_photo(file_manager, {dialog_id, dialog_access_hash, true}, 0, 0, "",
std::move(chat_photo->photo_big_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
result.small_file_id = register_photo(file_manager, {dialog_id, dialog_access_hash, false}, chat_photo->photo_id_,
0, "", DialogId(), 0, dc_id, PhotoFormat::Jpeg);
result.big_file_id = register_photo(file_manager, {dialog_id, dialog_access_hash, true}, chat_photo->photo_id_, 0,
"", DialogId(), 0, dc_id, PhotoFormat::Jpeg);
break;
}
@ -287,6 +273,7 @@ DialogPhoto as_fake_dialog_photo(const Photo &photo) {
result.big_file_id = size.file_id;
}
}
result.minithumbnail = photo.minithumbnail;
result.has_animation = !photo.animations.empty();
if (!result.small_file_id.is_valid() || !result.big_file_id.is_valid()) {
LOG(ERROR) << "Failed to convert " << photo << " to chat photo";
@ -348,14 +335,12 @@ PhotoSize get_secret_thumbnail_photo_size(FileManager *file_manager, BufferSlice
// generate some random remote location to save
auto dc_id = DcId::invalid();
auto local_id = -(Random::secure_int32() & 0x7FFFFFFF);
auto volume_id = Random::secure_int64();
auto photo_id = -(Random::secure_int64() & std::numeric_limits<int64>::max());
res.file_id = file_manager->register_remote(
FullRemoteFileLocation(PhotoSizeSource(FileType::EncryptedThumbnail, 't'), 0, 0, local_id, volume_id, dc_id,
string()),
FullRemoteFileLocation(PhotoSizeSource(FileType::EncryptedThumbnail, 't'), photo_id, 0, dc_id, string()),
FileLocationSource::FromServer, owner_dialog_id, res.size, 0,
PSTRING() << static_cast<uint64>(volume_id) << "_" << static_cast<uint64>(local_id) << ".jpg");
PSTRING() << static_cast<uint64>(photo_id) << ".jpg");
file_manager->set_content(res.file_id, std::move(bytes));
return res;
@ -367,7 +352,6 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
PhotoFormat format) {
CHECK(size_ptr != nullptr);
tl_object_ptr<telegram_api::fileLocationToBeDeprecated> location;
string type;
PhotoSize res;
BufferSlice content;
@ -378,7 +362,6 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
auto size = move_tl_object_as<telegram_api::photoSize>(size_ptr);
type = std::move(size->type_);
location = std::move(size->location_);
res.dimensions = get_dimensions(size->w_, size->h_, "photoSize");
res.size = size->size_;
@ -388,7 +371,6 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
auto size = move_tl_object_as<telegram_api::photoCachedSize>(size_ptr);
type = std::move(size->type_);
location = std::move(size->location_);
CHECK(size->bytes_.size() <= static_cast<size_t>(std::numeric_limits<int32>::max()));
res.dimensions = get_dimensions(size->w_, size->h_, "photoCachedSize");
res.size = static_cast<int32>(size->bytes_.size());
@ -415,7 +397,6 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
std::sort(size->sizes_.begin(), size->sizes_.end());
type = std::move(size->type_);
location = std::move(size->location_);
res.dimensions = get_dimensions(size->w_, size->h_, "photoSizeProgressive");
res.size = size->sizes_.back();
size->sizes_.pop_back();
@ -437,17 +418,21 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
}
if (type.size() != 1) {
res.type = 0;
LOG(ERROR) << "Wrong photoSize \"" << type << "\" " << res;
res.type = 0;
} else {
res.type = static_cast<uint8>(type[0]);
if (res.type >= 128) {
LOG(ERROR) << "Wrong photoSize \"" << type << "\" " << res;
res.type = 0;
}
}
if (source.get_type() == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail().thumbnail_type = res.type;
}
res.file_id = register_photo(file_manager, source, id, access_hash, file_reference, std::move(location),
owner_dialog_id, res.size, dc_id, format);
res.file_id =
register_photo(file_manager, source, id, access_hash, file_reference, owner_dialog_id, res.size, dc_id, format);
if (!content.empty()) {
file_manager->set_content(res.file_id, std::move(content));
@ -465,6 +450,10 @@ AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource sour
LOG(ERROR) << "Wrong videoSize \"" << size->type_ << "\" in " << to_string(size);
}
res.type = static_cast<uint8>(size->type_[0]);
if (res.type >= 128) {
LOG(ERROR) << "Wrong videoSize \"" << res.type << "\" " << res;
res.type = 0;
}
res.dimensions = get_dimensions(size->w_, size->h_, "get_animation_size");
res.size = size->size_;
if ((size->flags_ & telegram_api::videoSize::VIDEO_START_TS_MASK) != 0) {
@ -475,8 +464,8 @@ AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource sour
source.thumbnail().thumbnail_type = res.type;
}
res.file_id = register_photo(file_manager, source, id, access_hash, file_reference, std::move(size->location_),
owner_dialog_id, res.size, dc_id, PhotoFormat::Mpeg4);
res.file_id = register_photo(file_manager, source, id, access_hash, file_reference, owner_dialog_id, res.size, dc_id,
PhotoFormat::Mpeg4);
return res;
}
@ -937,20 +926,14 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
return string_builder << ']';
}
static tl_object_ptr<telegram_api::fileLocationToBeDeprecated> copy_location(
const tl_object_ptr<telegram_api::fileLocationToBeDeprecated> &location) {
CHECK(location != nullptr);
return make_tl_object<telegram_api::fileLocationToBeDeprecated>(location->volume_id_, location->local_id_);
}
tl_object_ptr<telegram_api::userProfilePhoto> convert_photo_to_profile_photo(
const tl_object_ptr<telegram_api::photo> &photo) {
if (photo == nullptr) {
return nullptr;
}
tl_object_ptr<telegram_api::fileLocationToBeDeprecated> photo_small;
tl_object_ptr<telegram_api::fileLocationToBeDeprecated> photo_big;
bool have_photo_small = false;
bool have_photo_big = false;
for (auto &size_ptr : photo->sizes_) {
switch (size_ptr->get_id()) {
case telegram_api::photoSizeEmpty::ID:
@ -958,18 +941,18 @@ tl_object_ptr<telegram_api::userProfilePhoto> convert_photo_to_profile_photo(
case telegram_api::photoSize::ID: {
auto size = static_cast<const telegram_api::photoSize *>(size_ptr.get());
if (size->type_ == "a") {
photo_small = copy_location(size->location_);
have_photo_small = true;
} else if (size->type_ == "c") {
photo_big = copy_location(size->location_);
have_photo_big = true;
}
break;
}
case telegram_api::photoCachedSize::ID: {
auto size = static_cast<const telegram_api::photoCachedSize *>(size_ptr.get());
if (size->type_ == "a") {
photo_small = copy_location(size->location_);
have_photo_small = true;
} else if (size->type_ == "c") {
photo_big = copy_location(size->location_);
have_photo_big = true;
}
break;
}
@ -978,9 +961,9 @@ tl_object_ptr<telegram_api::userProfilePhoto> convert_photo_to_profile_photo(
case telegram_api::photoSizeProgressive::ID: {
auto size = static_cast<const telegram_api::photoSizeProgressive *>(size_ptr.get());
if (size->type_ == "a") {
photo_small = copy_location(size->location_);
have_photo_small = true;
} else if (size->type_ == "c") {
photo_big = copy_location(size->location_);
have_photo_big = true;
}
break;
}
@ -989,15 +972,15 @@ tl_object_ptr<telegram_api::userProfilePhoto> convert_photo_to_profile_photo(
break;
}
}
if (photo_small == nullptr || photo_big == nullptr) {
if (!have_photo_small || !have_photo_big) {
return nullptr;
}
int32 flags = 0;
if (!photo->video_sizes_.empty()) {
flags |= telegram_api::userProfilePhoto::HAS_VIDEO_MASK;
}
return make_tl_object<telegram_api::userProfilePhoto>(flags, false /*ignored*/, photo->id_, std::move(photo_small),
std::move(photo_big), BufferSlice(), photo->dc_id_);
return make_tl_object<telegram_api::userProfilePhoto>(flags, false /*ignored*/, photo->id_, BufferSlice(),
photo->dc_id_);
}
} // namespace td

View File

@ -99,6 +99,10 @@ void parse(PhotoSize &photo_size, ParserT &parser) {
} else {
photo_size.progressive_sizes.clear();
}
if (photo_size.type < 0 || photo_size.type >= 128) {
parser.set_error("Wrong PhotoSize type");
return;
}
LOG(DEBUG) << "Parsed photo size " << photo_size;
}

View File

@ -11,6 +11,9 @@
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/tl_storers.h"
namespace td {
@ -40,22 +43,117 @@ tl_object_ptr<telegram_api::InputPeer> PhotoSizeSource::DialogPhoto::get_input_p
FileType PhotoSizeSource::get_file_type() const {
switch (get_type()) {
case PhotoSizeSource::Type::Thumbnail:
case Type::Thumbnail:
return thumbnail().file_type;
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBig:
case Type::DialogPhotoSmall:
case Type::DialogPhotoBig:
case Type::DialogPhotoSmallLegacy:
case Type::DialogPhotoBigLegacy:
return FileType::ProfilePhoto;
case PhotoSizeSource::Type::StickerSetThumbnail:
case Type::StickerSetThumbnail:
case Type::StickerSetThumbnailLegacy:
case Type::StickerSetThumbnailVersion:
return FileType::Thumbnail;
case PhotoSizeSource::Type::Legacy:
case Type::Legacy:
case Type::FullLegacy:
default:
UNREACHABLE();
return FileType::Thumbnail;
}
}
string PhotoSizeSource::get_unique() const {
auto ptr = StackAllocator::alloc(16);
MutableSlice data = ptr.as_slice();
TlStorerUnsafe storer(data.ubegin());
switch (get_type()) {
case Type::Legacy:
UNREACHABLE();
break;
case Type::Thumbnail: {
auto type = thumbnail().thumbnail_type;
CHECK(0 <= type && type <= 127);
if (type == 'a') {
type = 0;
} else if (type == 'c') {
type = 1;
} else {
type += 5;
}
return string(1, static_cast<char>(type));
}
case Type::DialogPhotoSmall:
// it doesn't matter to which Dialog the photo belongs
return string(1, '\x00');
case Type::DialogPhotoBig:
// it doesn't matter to which Dialog the photo belongs
return string(1, '\x01');
case Type::StickerSetThumbnail:
UNREACHABLE();
break;
case Type::FullLegacy: {
auto &legacy = full_legacy();
td::store(legacy.volume_id, storer);
td::store(legacy.local_id, storer);
break;
}
case Type::DialogPhotoSmallLegacy:
case Type::DialogPhotoBigLegacy: {
auto &legacy = dialog_photo_legacy();
td::store(legacy.volume_id, storer);
td::store(legacy.local_id, storer);
break;
}
case Type::StickerSetThumbnailLegacy: {
auto &legacy = sticker_set_thumbnail_legacy();
td::store(legacy.volume_id, storer);
td::store(legacy.local_id, storer);
break;
}
case Type::StickerSetThumbnailVersion: {
auto &thumbnail = sticker_set_thumbnail_version();
storer.store_slice(Slice("\x02"));
td::store(thumbnail.sticker_set_id, storer);
td::store(thumbnail.version, storer);
break;
}
default:
UNREACHABLE();
break;
}
auto size = storer.get_buf() - data.ubegin();
CHECK(size <= 13);
return string(data.begin(), size);
}
string PhotoSizeSource::get_unique_name(int64 photo_id) const {
switch (get_type()) {
case Type::Thumbnail:
CHECK(0 <= thumbnail().thumbnail_type && thumbnail().thumbnail_type <= 127);
return PSTRING() << photo_id << '_' << thumbnail().thumbnail_type;
case Type::DialogPhotoSmall:
return to_string(photo_id);
case Type::DialogPhotoBig:
return PSTRING() << photo_id << '_' << 1;
case Type::StickerSetThumbnailVersion:
return PSTRING() << sticker_set_thumbnail_version().sticker_set_id << '_'
<< static_cast<uint32>(sticker_set_thumbnail_version().version);
case Type::Legacy:
case Type::StickerSetThumbnail:
case Type::FullLegacy:
case Type::DialogPhotoSmallLegacy:
case Type::DialogPhotoBigLegacy:
case Type::StickerSetThumbnailLegacy:
default:
UNREACHABLE();
break;
}
return 0;
}
static bool operator==(const PhotoSizeSource::Legacy &lhs, const PhotoSizeSource::Legacy &rhs) {
return lhs.secret == rhs.secret;
UNREACHABLE();
return false;
}
static bool operator==(const PhotoSizeSource::Thumbnail &lhs, const PhotoSizeSource::Thumbnail &rhs) {
@ -81,6 +179,42 @@ static bool operator==(const PhotoSizeSource::StickerSetThumbnail &lhs,
return lhs.sticker_set_id == rhs.sticker_set_id && lhs.sticker_set_access_hash == rhs.sticker_set_access_hash;
}
static bool operator==(const PhotoSizeSource::FullLegacy &lhs, const PhotoSizeSource::FullLegacy &rhs) {
return lhs.volume_id == rhs.volume_id && lhs.local_id == rhs.local_id && lhs.secret == rhs.secret;
}
static bool operator==(const PhotoSizeSource::DialogPhotoLegacy &lhs, const PhotoSizeSource::DialogPhotoLegacy &rhs) {
return static_cast<const PhotoSizeSource::DialogPhoto &>(lhs) ==
static_cast<const PhotoSizeSource::DialogPhoto &>(rhs) &&
lhs.volume_id == rhs.volume_id && lhs.local_id == rhs.local_id;
}
static bool operator==(const PhotoSizeSource::DialogPhotoSmallLegacy &lhs,
const PhotoSizeSource::DialogPhotoSmallLegacy &rhs) {
return static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(lhs) ==
static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(rhs);
}
static bool operator==(const PhotoSizeSource::DialogPhotoBigLegacy &lhs,
const PhotoSizeSource::DialogPhotoBigLegacy &rhs) {
return static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(lhs) ==
static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(rhs);
}
static bool operator==(const PhotoSizeSource::StickerSetThumbnailLegacy &lhs,
const PhotoSizeSource::StickerSetThumbnailLegacy &rhs) {
return static_cast<const PhotoSizeSource::StickerSetThumbnail &>(lhs) ==
static_cast<const PhotoSizeSource::StickerSetThumbnail &>(rhs) &&
lhs.volume_id == rhs.volume_id && lhs.local_id == rhs.local_id;
}
static bool operator==(const PhotoSizeSource::StickerSetThumbnailVersion &lhs,
const PhotoSizeSource::StickerSetThumbnailVersion &rhs) {
return static_cast<const PhotoSizeSource::StickerSetThumbnail &>(lhs) ==
static_cast<const PhotoSizeSource::StickerSetThumbnail &>(rhs) &&
lhs.version == rhs.version;
}
bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
return lhs.variant == rhs.variant;
}
@ -91,6 +225,8 @@ bool operator!=(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
StringBuilder &operator<<(StringBuilder &string_builder, const PhotoSizeSource &source) {
switch (source.get_type()) {
case PhotoSizeSource::Type::Legacy:
return string_builder << "PhotoSizeSourceLegacy[]";
case PhotoSizeSource::Type::Thumbnail:
return string_builder << "PhotoSizeSourceThumbnail[" << source.thumbnail().file_type
<< ", type = " << source.thumbnail().thumbnail_type << ']';
@ -101,8 +237,19 @@ StringBuilder &operator<<(StringBuilder &string_builder, const PhotoSizeSource &
case PhotoSizeSource::Type::StickerSetThumbnail:
return string_builder << "PhotoSizeSourceStickerSetThumbnail[" << source.sticker_set_thumbnail().sticker_set_id
<< ']';
case PhotoSizeSource::Type::Legacy:
return string_builder << "PhotoSizeSourceLegacy[]";
case PhotoSizeSource::Type::FullLegacy:
return string_builder << "PhotoSizeSourceFullLegacy[]";
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
return string_builder << "PhotoSizeSourceChatPhotoSmallLegacy[" << source.dialog_photo().dialog_id << ']';
case PhotoSizeSource::Type::DialogPhotoBigLegacy:
return string_builder << "PhotoSizeSourceChatPhotoBigLegacy[" << source.dialog_photo().dialog_id << ']';
case PhotoSizeSource::Type::StickerSetThumbnailLegacy:
return string_builder << "PhotoSizeSourceStickerSetThumbnailLegacy["
<< source.sticker_set_thumbnail().sticker_set_id << ']';
case PhotoSizeSource::Type::StickerSetThumbnailVersion:
return string_builder << "PhotoSizeSourceStickerSetThumbnailVersion["
<< source.sticker_set_thumbnail().sticker_set_id << '_'
<< source.sticker_set_thumbnail_version().version << ']';
default:
UNREACHABLE();
return string_builder;

View File

@ -15,10 +15,23 @@
#include "td/utils/StringBuilder.h"
#include "td/utils/Variant.h"
#include <cstddef>
namespace td {
struct PhotoSizeSource {
enum class Type : int32 { Legacy, Thumbnail, DialogPhotoSmall, DialogPhotoBig, StickerSetThumbnail };
enum class Type : int32 {
Legacy,
Thumbnail,
DialogPhotoSmall,
DialogPhotoBig,
StickerSetThumbnail,
FullLegacy,
DialogPhotoSmallLegacy,
DialogPhotoBigLegacy,
StickerSetThumbnailLegacy,
StickerSetThumbnailVersion
};
// for legacy photos with secret
struct Legacy {
@ -75,9 +88,59 @@ struct PhotoSizeSource {
}
};
// for legacy photos with volume_id, local_id, secret
struct FullLegacy {
FullLegacy() = default;
FullLegacy(int64 volume_id, int32 local_id, int64 secret)
: volume_id(volume_id), local_id(local_id), secret(secret) {
}
int64 volume_id = 0;
int32 local_id = 0;
int64 secret = 0;
};
// for legacy dialog photos
struct DialogPhotoLegacy : public DialogPhoto {
DialogPhotoLegacy() = default;
DialogPhotoLegacy(DialogId dialog_id, int64 dialog_access_hash, int64 volume_id, int32 local_id)
: DialogPhoto(dialog_id, dialog_access_hash), volume_id(volume_id), local_id(local_id) {
}
int64 volume_id = 0;
int32 local_id = 0;
};
struct DialogPhotoSmallLegacy : public DialogPhotoLegacy {
using DialogPhotoLegacy::DialogPhotoLegacy;
};
struct DialogPhotoBigLegacy : public DialogPhotoLegacy {
using DialogPhotoLegacy::DialogPhotoLegacy;
};
// for legacy sticker set thumbnails
struct StickerSetThumbnailLegacy : public StickerSetThumbnail {
StickerSetThumbnailLegacy() = default;
StickerSetThumbnailLegacy(int64 sticker_set_id, int64 sticker_set_access_hash, int64 volume_id, int32 local_id)
: StickerSetThumbnail(sticker_set_id, sticker_set_access_hash), volume_id(volume_id), local_id(local_id) {
}
int64 volume_id = 0;
int32 local_id = 0;
};
// for sticker set thumbnails identified by version
struct StickerSetThumbnailVersion : public StickerSetThumbnail {
StickerSetThumbnailVersion() = default;
StickerSetThumbnailVersion(int64 sticker_set_id, int64 sticker_set_access_hash, int32 version)
: StickerSetThumbnail(sticker_set_id, sticker_set_access_hash), version(version) {
}
int32 version = 0;
};
PhotoSizeSource() = default;
explicit PhotoSizeSource(int64 secret) : variant(Legacy(secret)) {
}
PhotoSizeSource(FileType file_type, int32 thumbnail_type) : variant(Thumbnail(file_type, thumbnail_type)) {
}
PhotoSizeSource(DialogId dialog_id, int64 dialog_access_hash, bool is_big) {
@ -90,6 +153,22 @@ struct PhotoSizeSource {
PhotoSizeSource(int64 sticker_set_id, int64 sticker_set_access_hash)
: variant(StickerSetThumbnail(sticker_set_id, sticker_set_access_hash)) {
}
PhotoSizeSource(std::nullptr_t, int64 volume_id, int32 local_id, int64 secret)
: variant(FullLegacy(volume_id, local_id, secret)) {
}
PhotoSizeSource(DialogId dialog_id, int64 dialog_access_hash, bool is_big, int64 volume_id, int32 local_id) {
if (is_big) {
variant = DialogPhotoBigLegacy(dialog_id, dialog_access_hash, volume_id, local_id);
} else {
variant = DialogPhotoSmallLegacy(dialog_id, dialog_access_hash, volume_id, local_id);
}
}
PhotoSizeSource(int64 sticker_set_id, int64 sticker_set_access_hash, int64 volume_id, int32 local_id)
: variant(StickerSetThumbnailLegacy(sticker_set_id, sticker_set_access_hash, volume_id, local_id)) {
}
PhotoSizeSource(int64 sticker_set_id, int64 sticker_set_access_hash, int32 version)
: variant(StickerSetThumbnailVersion(sticker_set_id, sticker_set_access_hash, version)) {
}
Type get_type() const {
auto offset = variant.get_offset();
@ -110,15 +189,55 @@ struct PhotoSizeSource {
return variant.get<Thumbnail>();
}
const DialogPhoto &dialog_photo() const {
if (variant.get_offset() == 2) {
return variant.get<DialogPhotoSmall>();
} else {
return variant.get<DialogPhotoBig>();
switch (variant.get_offset()) {
case 2:
return variant.get<DialogPhotoSmall>();
case 3:
return variant.get<DialogPhotoBig>();
case 6:
return variant.get<DialogPhotoSmallLegacy>();
case 7:
return variant.get<DialogPhotoBigLegacy>();
default:
UNREACHABLE();
return variant.get<DialogPhotoSmall>();
}
}
const StickerSetThumbnail &sticker_set_thumbnail() const {
return variant.get<StickerSetThumbnail>();
switch (variant.get_offset()) {
case 4:
return variant.get<StickerSetThumbnail>();
case 8:
return variant.get<StickerSetThumbnailLegacy>();
case 9:
return variant.get<StickerSetThumbnailVersion>();
default:
UNREACHABLE();
return variant.get<StickerSetThumbnail>();
}
}
const FullLegacy &full_legacy() const {
return variant.get<FullLegacy>();
}
const DialogPhotoLegacy &dialog_photo_legacy() const {
if (variant.get_offset() == 6) {
return variant.get<DialogPhotoSmallLegacy>();
} else {
return variant.get<DialogPhotoBigLegacy>();
}
}
const StickerSetThumbnailLegacy &sticker_set_thumbnail_legacy() const {
return variant.get<StickerSetThumbnailLegacy>();
}
const StickerSetThumbnailVersion &sticker_set_thumbnail_version() const {
return variant.get<StickerSetThumbnailVersion>();
}
// returns unique representation of the source
string get_unique() const;
// can't be called for Legacy sources
string get_unique_name(int64 photo_id) const;
template <class StorerT>
void store(StorerT &storer) const;
@ -128,7 +247,9 @@ struct PhotoSizeSource {
friend bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs);
private:
Variant<Legacy, Thumbnail, DialogPhotoSmall, DialogPhotoBig, StickerSetThumbnail> variant;
Variant<Legacy, Thumbnail, DialogPhotoSmall, DialogPhotoBig, StickerSetThumbnail, FullLegacy, DialogPhotoSmallLegacy,
DialogPhotoBigLegacy, StickerSetThumbnailLegacy, StickerSetThumbnailVersion>
variant;
};
bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs);

View File

@ -15,6 +15,7 @@ namespace td {
template <class StorerT>
void store(const PhotoSizeSource::Legacy &source, StorerT &storer) {
UNREACHABLE();
store(source.secret, storer);
}
@ -39,23 +40,11 @@ void parse(PhotoSizeSource::Thumbnail &source, ParserT &parser) {
source.file_type = static_cast<FileType>(raw_type);
parse(source.thumbnail_type, parser);
if (source.thumbnail_type < 0 || source.thumbnail_type > 255) {
if (source.thumbnail_type < 0 || source.thumbnail_type > 127) {
parser.set_error("Wrong thumbnail type");
}
}
template <class StorerT>
void store(const PhotoSizeSource::StickerSetThumbnail &source, StorerT &storer) {
store(source.sticker_set_id, storer);
store(source.sticker_set_access_hash, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::StickerSetThumbnail &source, ParserT &parser) {
parse(source.sticker_set_id, parser);
parse(source.sticker_set_access_hash, parser);
}
template <class StorerT>
void store(const PhotoSizeSource::DialogPhoto &source, StorerT &storer) {
store(source.dialog_id, storer);
@ -96,6 +85,101 @@ void parse(PhotoSizeSource::DialogPhotoBig &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::DialogPhoto &>(source), parser);
}
template <class StorerT>
void store(const PhotoSizeSource::StickerSetThumbnail &source, StorerT &storer) {
store(source.sticker_set_id, storer);
store(source.sticker_set_access_hash, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::StickerSetThumbnail &source, ParserT &parser) {
parse(source.sticker_set_id, parser);
parse(source.sticker_set_access_hash, parser);
}
template <class StorerT>
void store(const PhotoSizeSource::FullLegacy &source, StorerT &storer) {
store(source.volume_id, storer);
store(source.secret, storer);
store(source.local_id, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::FullLegacy &source, ParserT &parser) {
parse(source.volume_id, parser);
parse(source.secret, parser);
parse(source.local_id, parser);
if (source.local_id < 0) {
parser.set_error("Wrong local_id");
}
}
template <class StorerT>
void store(const PhotoSizeSource::DialogPhotoLegacy &source, StorerT &storer) {
store(static_cast<const PhotoSizeSource::DialogPhoto &>(source), storer);
store(source.volume_id, storer);
store(source.local_id, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::DialogPhotoLegacy &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::DialogPhoto &>(source), parser);
parse(source.volume_id, parser);
parse(source.local_id, parser);
if (source.local_id < 0) {
parser.set_error("Wrong local_id");
}
}
template <class StorerT>
void store(const PhotoSizeSource::DialogPhotoSmallLegacy &source, StorerT &storer) {
store(static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(source), storer);
}
template <class ParserT>
void parse(PhotoSizeSource::DialogPhotoSmallLegacy &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::DialogPhotoLegacy &>(source), parser);
}
template <class StorerT>
void store(const PhotoSizeSource::DialogPhotoBigLegacy &source, StorerT &storer) {
store(static_cast<const PhotoSizeSource::DialogPhotoLegacy &>(source), storer);
}
template <class ParserT>
void parse(PhotoSizeSource::DialogPhotoBigLegacy &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::DialogPhotoLegacy &>(source), parser);
}
template <class StorerT>
void store(const PhotoSizeSource::StickerSetThumbnailLegacy &source, StorerT &storer) {
store(static_cast<const PhotoSizeSource::StickerSetThumbnail &>(source), storer);
store(source.volume_id, storer);
store(source.local_id, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::StickerSetThumbnailLegacy &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::StickerSetThumbnail &>(source), parser);
parse(source.volume_id, parser);
parse(source.local_id, parser);
if (source.local_id < 0) {
parser.set_error("Wrong local_id");
}
}
template <class StorerT>
void store(const PhotoSizeSource::StickerSetThumbnailVersion &source, StorerT &storer) {
store(static_cast<const PhotoSizeSource::StickerSetThumbnail &>(source), storer);
store(source.version, storer);
}
template <class ParserT>
void parse(PhotoSizeSource::StickerSetThumbnailVersion &source, ParserT &parser) {
parse(static_cast<PhotoSizeSource::StickerSetThumbnail &>(source), parser);
parse(source.version, parser);
}
template <class StorerT>
void PhotoSizeSource::store(StorerT &storer) const {
td::store(variant, storer);

View File

@ -2445,8 +2445,8 @@ StickerSetId StickersManager::on_get_sticker_set(tl_object_ptr<telegram_api::sti
PhotoSize thumbnail;
string minithumbnail;
for (auto &thumb : set->thumbs_) {
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(thumb),
auto photo_size = get_photo_size(td_->file_manager_.get(), {set_id.get(), s->access_hash, set->thumb_version_}, 0,
0, "", DcId::create(set->thumb_dc_id_), DialogId(), std::move(thumb),
is_animated ? PhotoFormat::Tgs : PhotoFormat::Webp);
if (photo_size.get_offset() == 0) {
if (!thumbnail.file_id.is_valid()) {

View File

@ -8,7 +8,7 @@
namespace td {
constexpr int32 MTPROTO_LAYER = 127;
constexpr int32 MTPROTO_LAYER = 128;
enum class Version : int32 {
Initial, // 0
@ -43,6 +43,7 @@ enum class Version : int32 {
AddLiveLocationHeading,
AddLiveLocationProximityAlertDistance, // 30
SupportBannedChannels,
RemovePhotoVolumeAndLocalId,
Next
};

View File

@ -40,7 +40,6 @@ Status drop_file_db(SqliteDb &db, int32 version) {
return Status::OK();
}
Status fix_file_remote_location_key_bug(SqliteDb &db);
Status init_file_db(SqliteDb &db, int32 version) {
LOG(INFO) << "Init file database " << tag("version", version);
@ -49,11 +48,9 @@ Status init_file_db(SqliteDb &db, int32 version) {
if (!has_table) {
version = 0;
} else if (version < static_cast<int32>(DbVersion::DialogDbCreated)) {
} else if (version < static_cast<int32>(DbVersion::FixFileRemoteLocationKeyBug)) {
TRY_STATUS(drop_file_db(db, version));
version = 0;
} else if (version < static_cast<int>(DbVersion::FixFileRemoteLocationKeyBug)) {
TRY_STATUS(fix_file_remote_location_key_bug(db));
}
if (version == 0) {
@ -306,30 +303,4 @@ std::shared_ptr<FileDbInterface> create_file_db(std::shared_ptr<SqliteConnection
return std::make_shared<FileDb>(std::move(kv), scheduler_id);
}
Status fix_file_remote_location_key_bug(SqliteDb &db) {
static const int32 OLD_KEY_MAGIC = 0x64378433;
SqliteKeyValue kv;
kv.init_with_connection(db.clone(), "files").ensure();
auto ptr = StackAllocator::alloc(4);
MutableSlice prefix = ptr.as_slice();
TlStorerUnsafe(prefix.ubegin()).store_int(OLD_KEY_MAGIC);
kv.get_by_prefix(prefix, [&](Slice key, Slice value) {
CHECK(TlParser(key).fetch_int() == OLD_KEY_MAGIC);
auto remote_str = PSTRING() << key.substr(4, 4) << Slice("\0\0\0\0") << key.substr(8);
FullRemoteFileLocation remote;
log_event::WithVersion<TlParser> parser(remote_str);
parser.set_version(static_cast<int32>(Version::Initial));
parse(remote, parser);
parser.fetch_end();
auto status = parser.get_status();
if (status.is_ok()) {
kv.set(FileDbInterface::as_key(remote), value);
}
LOG(DEBUG) << "ERASE " << format::as_hex_dump<4>(Slice(key));
kv.erase(key);
return true;
});
return Status::OK();
}
} // namespace td

View File

@ -81,8 +81,6 @@ inline StringBuilder &operator<<(StringBuilder &sb, const PartialRemoteFileLocat
struct PhotoRemoteFileLocation {
int64 id_;
int64 access_hash_;
int64 volume_id_;
int32 local_id_;
PhotoSizeSource source_;
template <class StorerT>
@ -102,16 +100,19 @@ struct PhotoRemoteFileLocation {
}
bool operator<(const PhotoRemoteFileLocation &other) const {
return std::tie(id_, volume_id_, local_id_) < std::tie(other.id_, other.volume_id_, other.local_id_);
if (id_ != other.id_) {
return id_ < other.id_;
}
return source_.get_unique() < other.source_.get_unique();
}
bool operator==(const PhotoRemoteFileLocation &other) const {
return std::tie(id_, volume_id_, local_id_) == std::tie(other.id_, other.volume_id_, other.local_id_);
return id_ == other.id_ && source_.get_unique() == other.source_.get_unique();
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, const PhotoRemoteFileLocation &location) {
return string_builder << "[ID = " << location.id_ << ", access_hash = " << location.access_hash_
<< ", volume_id = " << location.volume_id_ << ", local_id = " << location.local_id_ << "]";
return string_builder << "[ID = " << location.id_ << ", access_hash = " << location.access_hash_ << ", "
<< location.source_ << "]";
}
struct WebRemoteFileLocation {
@ -165,10 +166,10 @@ struct CommonRemoteFileLocation {
}
bool operator<(const CommonRemoteFileLocation &other) const {
return std::tie(id_) < std::tie(other.id_);
return id_ < other.id_;
}
bool operator==(const CommonRemoteFileLocation &other) const {
return std::tie(id_) == std::tie(other.id_);
return id_ == other.id_;
}
};
@ -324,11 +325,11 @@ class FullRemoteFileLocation {
return photo().source_;
case LocationType::Common:
case LocationType::Web:
return PhotoSizeSource(0);
return PhotoSizeSource(nullptr, 0, 0, 0);
case LocationType::None:
default:
UNREACHABLE();
return PhotoSizeSource(0);
return PhotoSizeSource(nullptr, 0, 0, 0);
}
}
@ -395,22 +396,24 @@ class FullRemoteFileLocation {
tl_object_ptr<telegram_api::InputFileLocation> as_input_file_location() const {
switch (location_type()) {
case LocationType::Photo:
switch (photo().source_.get_type()) {
case LocationType::Photo: {
const auto &id = photo().id_;
const auto &access_hash = photo().access_hash_;
const auto &source = photo().source_;
switch (source.get_type()) {
case PhotoSizeSource::Type::Legacy:
return make_tl_object<telegram_api::inputPhotoLegacyFileLocation>(
photo().id_, photo().access_hash_, BufferSlice(file_reference_), photo().volume_id_, photo().local_id_,
photo().source_.legacy().secret);
UNREACHABLE();
break;
case PhotoSizeSource::Type::Thumbnail: {
auto &thumbnail = photo().source_.thumbnail();
auto &thumbnail = source.thumbnail();
switch (thumbnail.file_type) {
case FileType::Photo:
return make_tl_object<telegram_api::inputPhotoFileLocation>(
photo().id_, photo().access_hash_, BufferSlice(file_reference_),
id, access_hash, BufferSlice(file_reference_),
std::string(1, static_cast<char>(static_cast<uint8>(thumbnail.thumbnail_type))));
case FileType::Thumbnail:
return make_tl_object<telegram_api::inputDocumentFileLocation>(
photo().id_, photo().access_hash_, BufferSlice(file_reference_),
id, access_hash, BufferSlice(file_reference_),
std::string(1, static_cast<char>(static_cast<uint8>(thumbnail.thumbnail_type))));
default:
UNREACHABLE();
@ -420,22 +423,46 @@ class FullRemoteFileLocation {
}
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBig: {
auto &dialog_photo = photo().source_.dialog_photo();
bool is_big = photo().source_.get_type() == PhotoSizeSource::Type::DialogPhotoBig;
auto &dialog_photo = source.dialog_photo();
bool is_big = source.get_type() == PhotoSizeSource::Type::DialogPhotoBig;
return make_tl_object<telegram_api::inputPeerPhotoFileLocation>(
is_big * telegram_api::inputPeerPhotoFileLocation::Flags::BIG_MASK, false /*ignored*/,
dialog_photo.get_input_peer(), photo().volume_id_, photo().local_id_);
is_big * telegram_api::inputPeerPhotoFileLocation::BIG_MASK, false /*ignored*/,
dialog_photo.get_input_peer(), id);
}
case PhotoSizeSource::Type::StickerSetThumbnail: {
auto &sticker_set_thumbnail = photo().source_.sticker_set_thumbnail();
case PhotoSizeSource::Type::StickerSetThumbnail:
UNREACHABLE();
break;
case PhotoSizeSource::Type::FullLegacy: {
const auto &full_legacy = source.full_legacy();
return make_tl_object<telegram_api::inputPhotoLegacyFileLocation>(
id, access_hash, BufferSlice(file_reference_), full_legacy.volume_id, full_legacy.local_id,
full_legacy.secret);
}
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
case PhotoSizeSource::Type::DialogPhotoBigLegacy: {
auto &dialog_photo = source.dialog_photo_legacy();
bool is_big = source.get_type() == PhotoSizeSource::Type::DialogPhotoBigLegacy;
return make_tl_object<telegram_api::inputPeerPhotoFileLocationLegacy>(
is_big * telegram_api::inputPeerPhotoFileLocationLegacy::BIG_MASK, false /*ignored*/,
dialog_photo.get_input_peer(), dialog_photo.volume_id, dialog_photo.local_id);
}
case PhotoSizeSource::Type::StickerSetThumbnailLegacy: {
auto &sticker_set_thumbnail = source.sticker_set_thumbnail_legacy();
return make_tl_object<telegram_api::inputStickerSetThumbLegacy>(
sticker_set_thumbnail.get_input_sticker_set(), sticker_set_thumbnail.volume_id,
sticker_set_thumbnail.local_id);
}
case PhotoSizeSource::Type::StickerSetThumbnailVersion: {
auto &sticker_set_thumbnail = source.sticker_set_thumbnail_version();
return make_tl_object<telegram_api::inputStickerSetThumb>(sticker_set_thumbnail.get_input_sticker_set(),
photo().volume_id_, photo().local_id_);
sticker_set_thumbnail.version);
}
default:
break;
}
UNREACHABLE();
return nullptr;
}
case LocationType::Common:
if (is_encrypted_secret()) {
return make_tl_object<telegram_api::inputEncryptedFileLocation>(common().id_, common().access_hash_);
@ -478,16 +505,16 @@ class FullRemoteFileLocation {
return make_tl_object<telegram_api::inputSecureFile>(common().id_, common().access_hash_);
}
// TODO: this constructor is just for immediate unserialize
// this constructor is just for immediate unserialize
FullRemoteFileLocation() = default;
// photo
FullRemoteFileLocation(const PhotoSizeSource &source, int64 id, int64 access_hash, int32 local_id, int64 volume_id,
DcId dc_id, std::string file_reference)
FullRemoteFileLocation(const PhotoSizeSource &source, int64 id, int64 access_hash, DcId dc_id,
std::string file_reference)
: file_type_(source.get_file_type())
, dc_id_(dc_id)
, file_reference_(std::move(file_reference))
, variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, local_id, source}) {
, variant_(PhotoRemoteFileLocation{id, access_hash, source}) {
CHECK(is_photo());
check_file_reference();
}

View File

@ -44,9 +44,7 @@ void PhotoRemoteFileLocation::store(StorerT &storer) const {
using td::store;
store(id_, storer);
store(access_hash_, storer);
store(volume_id_, storer);
store(source_, storer);
store(local_id_, storer);
}
template <class ParserT>
@ -54,25 +52,87 @@ void PhotoRemoteFileLocation::parse(ParserT &parser) {
using td::parse;
parse(id_, parser);
parse(access_hash_, parser);
parse(volume_id_, parser);
if (parser.version() >= static_cast<int32>(Version::AddPhotoSizeSource)) {
if (parser.version() >= static_cast<int32>(Version::RemovePhotoVolumeAndLocalId)) {
parse(source_, parser);
} else {
int64 secret;
parse(secret, parser);
source_ = PhotoSizeSource(secret);
int64 volume_id;
PhotoSizeSource source;
int32 local_id;
parse(volume_id, parser);
if (parser.version() >= static_cast<int32>(Version::AddPhotoSizeSource)) {
parse(source, parser);
parse(local_id, parser);
} else {
int64 secret;
parse(secret, parser);
parse(local_id, parser);
source = PhotoSizeSource(nullptr, volume_id, local_id, secret);
}
if (parser.get_error() != nullptr) {
return;
}
switch (source.get_type()) {
case PhotoSizeSource::Type::Legacy:
source_ = PhotoSizeSource(nullptr, volume_id, local_id, source.legacy().secret);
break;
case PhotoSizeSource::Type::FullLegacy:
case PhotoSizeSource::Type::Thumbnail:
source_ = source;
break;
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBig: {
auto &dialog_photo = source.dialog_photo();
bool is_big = source.get_type() == PhotoSizeSource::Type::DialogPhotoBig;
source_ = PhotoSizeSource(dialog_photo.dialog_id, dialog_photo.dialog_access_hash, is_big, volume_id, local_id);
break;
}
case PhotoSizeSource::Type::StickerSetThumbnail: {
auto &sticker_set_thumbnail = source.sticker_set_thumbnail();
source_ = PhotoSizeSource(sticker_set_thumbnail.sticker_set_id, sticker_set_thumbnail.sticker_set_access_hash,
volume_id, local_id);
break;
}
default:
parser.set_error("Invalid PhotoSizeSource in legacy PhotoRemoteFileLocation");
break;
}
}
parse(local_id_, parser);
}
template <class StorerT>
void PhotoRemoteFileLocation::AsKey::store(StorerT &storer) const {
using td::store;
if (!is_unique) {
store(key.id_, storer);
auto unique = key.source_.get_unique();
switch (key.source_.get_type()) {
case PhotoSizeSource::Type::Legacy:
case PhotoSizeSource::Type::StickerSetThumbnail:
UNREACHABLE();
break;
case PhotoSizeSource::Type::FullLegacy:
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
case PhotoSizeSource::Type::DialogPhotoBigLegacy:
case PhotoSizeSource::Type::StickerSetThumbnailLegacy: // 12/20 bytes
if (!is_unique) {
store(key.id_, storer);
}
storer.store_slice(unique); // volume_id + local_id
break;
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBig:
case PhotoSizeSource::Type::Thumbnail: // 8 + 1 bytes
store(key.id_, storer); // photo_id or document_id
storer.store_slice(unique);
break;
case PhotoSizeSource::Type::StickerSetThumbnailVersion: // 13 bytes
// sticker set thumbnails has no photo_id or document_id
storer.store_slice(unique);
break;
default:
UNREACHABLE();
break;
}
store(key.volume_id_, storer);
store(key.local_id_, storer);
}
template <class StorerT>
@ -172,6 +232,7 @@ void FullRemoteFileLocation::parse(ParserT &parser) {
}
switch (photo().source_.get_type()) {
case PhotoSizeSource::Type::Legacy:
case PhotoSizeSource::Type::FullLegacy:
break;
case PhotoSizeSource::Type::Thumbnail:
if (photo().source_.get_file_type() != file_type_ ||
@ -182,11 +243,15 @@ void FullRemoteFileLocation::parse(ParserT &parser) {
break;
case PhotoSizeSource::Type::DialogPhotoSmall:
case PhotoSizeSource::Type::DialogPhotoBig:
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
case PhotoSizeSource::Type::DialogPhotoBigLegacy:
if (file_type_ != FileType::ProfilePhoto) {
parser.set_error("Invalid FileType in PhotoRemoteFileLocation DialogPhoto");
}
break;
case PhotoSizeSource::Type::StickerSetThumbnail:
case PhotoSizeSource::Type::StickerSetThumbnailLegacy:
case PhotoSizeSource::Type::StickerSetThumbnailVersion:
if (file_type_ != FileType::Thumbnail) {
parser.set_error("Invalid FileType in PhotoRemoteFileLocation StickerSetThumbnail");
}

View File

@ -324,8 +324,7 @@ class FileView {
return false;
}
auto type = remote_location().get_source().get_type();
return type == PhotoSizeSource::Type::DialogPhotoBig || type == PhotoSizeSource::Type::DialogPhotoSmall ||
type == PhotoSizeSource::Type::StickerSetThumbnail;
return type != PhotoSizeSource::Type::Legacy && type != PhotoSizeSource::Type::FullLegacy;
}
string get_persistent_file_id() const;