Add PhotoSizeSource into FullRemoteFileLocation

GitOrigin-RevId: ce4e2c6a4dcd62684aa0916ead9c910afd6e932d
This commit is contained in:
Arseny Smirnov 2019-06-11 13:10:14 +03:00
parent 93d45b6502
commit e38afe63cc
10 changed files with 347 additions and 53 deletions

View File

@ -331,7 +331,7 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
res.type = static_cast<unsigned char>(type[0]);
}
if (source.type == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail_type = res.type;
source.thumbnail().thumbnail_type = res.type;
}
res.file_id = register_photo(file_manager, source, id, access_hash, file_reference, std::move(location),

View File

@ -47,38 +47,146 @@ struct PhotoSize {
FileId file_id;
};
struct OfflineInputStickerSet {
int64 sticker_set_id = 0;
int64 sticker_set_access_hash = 0;
OfflineInputStickerSet() = default;
OfflineInputStickerSet(int64 sticker_set_id, int64 sticker_set_access_hash)
: sticker_set_id(sticker_set_id), sticker_set_access_hash(sticker_set_access_hash) {
}
tl_object_ptr<telegram_api::InputStickerSet> as_telegram_api() const {
return make_tl_object<telegram_api::inputStickerSetID>(sticker_set_id, sticker_set_access_hash);
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
struct AsKey {
const OfflineInputStickerSet &key;
template <class StorerT>
void store(StorerT &storer) const;
};
AsKey as_key() const {
return AsKey{*this};
}
};
struct OfflineInputPeer {
DialogId dialog_id;
int64 dialog_access_hash = 0;
OfflineInputPeer() = default;
OfflineInputPeer(DialogId dialog_id, int64 dialog_access_hash)
: dialog_id(dialog_id), dialog_access_hash(dialog_access_hash) {
}
tl_object_ptr<telegram_api::InputPeer> as_telegram_api() const {
switch (dialog_id.get_type()) {
case DialogType::User: {
UserId user_id = dialog_id.get_user_id();
return make_tl_object<telegram_api::inputPeerUser>(user_id.get(), dialog_access_hash);
}
case DialogType::Chat: {
ChatId chat_id = dialog_id.get_chat_id();
return make_tl_object<telegram_api::inputPeerChat>(chat_id.get());
}
case DialogType::Channel: {
ChannelId channel_id = dialog_id.get_channel_id();
return make_tl_object<telegram_api::inputPeerChannel>(channel_id.get(), dialog_access_hash);
}
case DialogType::SecretChat:
return nullptr;
case DialogType::None:
return make_tl_object<telegram_api::inputPeerEmpty>();
default:
UNREACHABLE();
return nullptr;
} // namespace td
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
struct AsKey {
const OfflineInputPeer &key;
template <class StorerT>
void store(StorerT &storer) const;
};
AsKey as_key() const {
return AsKey{*this};
}
};
struct PhotoSizeSource {
enum class Type : int32 { Thumbnail, DialogPhoto, StickerSetThumbnail };
enum class Type : int32 { Empty, Thumbnail, DialogPhoto, StickerSetThumbnail };
Type type;
FileType file_type;
// for photos, document thumbnails, encrypted thumbnails
int32 thumbnail_type = 0;
struct Thumbnail {
Thumbnail() = default;
Thumbnail(int32 thumbnail_type) : thumbnail_type(thumbnail_type) {
}
int32 thumbnail_type = 0;
};
// for dialog photos
DialogId dialog_id;
int64 dialog_access_hash = 0;
bool is_big = false;
struct DialogPhoto {
DialogPhoto() = default;
DialogPhoto(OfflineInputPeer input_peer, bool is_big) : input_peer(input_peer), is_big(is_big) {
}
OfflineInputPeer input_peer;
bool is_big = false;
};
// for sticker set thumbnails
int64 sticker_set_id = 0;
int64 sticker_set_access_hash = 0;
struct StickerSetThumbnail {
StickerSetThumbnail() = default;
explicit StickerSetThumbnail(OfflineInputStickerSet input_sticker_set) : input_sticker_set(input_sticker_set) {
}
OfflineInputStickerSet input_sticker_set;
};
Variant<Thumbnail, DialogPhoto, StickerSetThumbnail> variant;
PhotoSizeSource() : type(Type::Empty), file_type(FileType::None) {
}
PhotoSizeSource(FileType file_type, int32 thumbnail_type)
: type(Type::Thumbnail), file_type(file_type), thumbnail_type(thumbnail_type) {
: type(Type::Thumbnail), file_type(file_type), variant(Thumbnail(thumbnail_type)) {
}
PhotoSizeSource(DialogId dialog_id, int64 dialog_access_hash, bool is_big)
: type(Type::DialogPhoto)
, file_type(FileType::ProfilePhoto)
, dialog_id(dialog_id)
, dialog_access_hash(dialog_access_hash)
, is_big(is_big) {
, variant(DialogPhoto(OfflineInputPeer(dialog_id, dialog_access_hash), is_big)) {
}
PhotoSizeSource(int64 sticker_set_id, int64 sticker_set_access_hash)
: type(Type::StickerSetThumbnail)
, file_type(FileType::Thumbnail)
, sticker_set_id(sticker_set_id)
, sticker_set_access_hash(sticker_set_access_hash) {
, variant(StickerSetThumbnail(OfflineInputStickerSet(sticker_set_id, sticker_set_access_hash))) {
}
Thumbnail &thumbnail() {
return variant.get<Thumbnail>();
}
const Thumbnail &thumbnail() const {
return variant.get<Thumbnail>();
}
const DialogPhoto &dialog_photo() const {
return variant.get<DialogPhoto>();
}
const StickerSetThumbnail &sticker_set_thumbnail() const {
return variant.get<StickerSetThumbnail>();
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
struct AsKey {
const PhotoSizeSource &key;
template <class StorerT>
void store(StorerT &storer) const;
};
AsKey as_key() const {
return AsKey{*this};
}
};

View File

@ -14,6 +14,126 @@
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
void OfflineInputStickerSet::store(StorerT &storer) const {
using td::store;
store(sticker_set_id, storer);
store(sticker_set_access_hash, storer);
}
template <class ParserT>
void OfflineInputStickerSet::parse(ParserT &parser) {
using td::parse;
parse(sticker_set_id, parser);
parse(sticker_set_access_hash, parser);
}
template <class StorerT>
void OfflineInputStickerSet::AsKey::store(StorerT &storer) const {
using td::store;
store(key.sticker_set_id, storer);
}
template <class StorerT>
void OfflineInputPeer::store(StorerT &storer) const {
using td::store;
store(dialog_id, storer);
store(dialog_access_hash, storer);
}
template <class ParserT>
void OfflineInputPeer::parse(ParserT &parser) {
using td::parse;
parse(dialog_id, parser);
parse(dialog_access_hash, parser);
}
template <class StorerT>
void OfflineInputPeer::AsKey::store(StorerT &storer) const {
using td::store;
store(key.dialog_id, storer);
}
template <class StorerT>
void PhotoSizeSource::store(StorerT &storer) const {
using td::store;
store(file_type, storer);
store(type, storer);
switch (type) {
case Type::DialogPhoto: {
auto &dialog_photo = this->dialog_photo();
store(dialog_photo.input_peer, storer);
store(dialog_photo.is_big, storer);
break;
}
case Type::StickerSetThumbnail: {
auto &sticker_set_thumbnail = this->sticker_set_thumbnail();
store(sticker_set_thumbnail.input_sticker_set, storer);
break;
}
case Type::Thumbnail: {
auto &thumbnail = this->thumbnail();
store(thumbnail.thumbnail_type, storer);
break;
}
case Type::Empty:
break;
}
}
template <class ParserT>
void PhotoSizeSource::parse(ParserT &parser) {
using td::parse;
parse(file_type, parser);
parse(type, parser);
switch (type) {
case Type::DialogPhoto: {
DialogPhoto dialog_photo;
parse(dialog_photo.input_peer, parser);
parse(dialog_photo.is_big, parser);
variant = dialog_photo;
break;
}
case Type::StickerSetThumbnail: {
StickerSetThumbnail sticker_set_thumbnail;
parse(sticker_set_thumbnail.input_sticker_set, parser);
variant = sticker_set_thumbnail;
break;
}
case Type::Thumbnail: {
Thumbnail thumbnail;
parse(thumbnail.thumbnail_type, parser);
variant = thumbnail;
break;
}
case Type::Empty:
break;
}
}
template <class StorerT>
void PhotoSizeSource::AsKey::store(StorerT &storer) const {
using td::store;
store(key.file_type, storer);
store(key.type, storer);
switch (key.type) {
case Type::DialogPhoto: {
auto &dialog_photo = this->key.dialog_photo();
store(dialog_photo.input_peer.as_key(), storer);
store(dialog_photo.is_big, storer);
break;
}
case Type::StickerSetThumbnail: {
auto &sticker_set_thumbnail = this->key.sticker_set_thumbnail();
store(sticker_set_thumbnail.input_sticker_set.as_key(), storer);
break;
}
case Type::Thumbnail: {
auto &thumbnail = this->key.thumbnail();
store(thumbnail.thumbnail_type, storer);
break;
}
case Type::Empty:
break;
}
}
template <class StorerT>
void store(Dimensions dimensions, StorerT &storer) {

View File

@ -31,6 +31,7 @@ enum class Version : int32 {
AddNotificationGroupInfoMaxRemovedMessageId,
SupportMinithumbnails,
AddVideoCallsSupport,
PhotoSizeSource,
Next
};

View File

@ -29,13 +29,18 @@ void FileData::store(StorerT &storer) const {
bool has_expected_size = size_ == 0 && expected_size_ != 0;
bool encryption_key_is_secure = encryption_key_.is_secure();
bool has_sources = !file_source_ids_.empty();
bool has_version = true;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_owner_dialog_id);
STORE_FLAG(has_expected_size);
STORE_FLAG(encryption_key_is_secure);
STORE_FLAG(has_sources);
STORE_FLAG(has_version);
END_STORE_FLAGS();
if (has_version) {
store(static_cast<int32>(Version::Next) - 1, storer);
}
if (has_owner_dialog_id) {
store(owner_dialog_id_, storer);
}
@ -67,13 +72,20 @@ void FileData::parse(ParserT &parser, bool register_file_sources) {
bool has_expected_size;
bool encryption_key_is_secure;
bool has_sources;
bool has_version;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_owner_dialog_id);
PARSE_FLAG(has_expected_size);
PARSE_FLAG(encryption_key_is_secure);
PARSE_FLAG(has_sources);
PARSE_FLAG(has_version);
END_PARSE_FLAGS_GENERIC();
int32 version = 0;
if (has_version) {
parse(version, parser);
}
parser.set_version(version);
if (has_owner_dialog_id) {
parse(owner_dialog_id_, parser);
}

View File

@ -11,6 +11,7 @@
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileLocation.hpp"
#include "td/telegram/Version.h"
#include "td/telegram/logevent/LogEvent.h" // WithVersion
#include "td/actor/actor.h"
@ -276,7 +277,8 @@ class FileDb : public FileDbInterface {
//LOG(DEBUG) << "By id " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
//LOG(INFO) << attempt_count;
TlParser parser(data_str);
logevent::WithVersion<TlParser> parser(data_str);
parser.set_version(static_cast<int32>(Version::Initial));
FileData data;
data.parse(parser, true);
parser.fetch_end();
@ -313,7 +315,12 @@ Status fix_file_remote_location_key_bug(SqliteDb &db) {
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;
if (unserialize(remote, remote_str).is_ok()) {
logevent::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));

View File

@ -170,6 +170,7 @@ struct PhotoRemoteFileLocation {
int64 volume_id_;
int64 secret_;
int32 local_id_;
PhotoSizeSource source_;
template <class StorerT>
void store(StorerT &storer) const;
@ -474,10 +475,43 @@ class FullRemoteFileLocation {
tl_object_ptr<telegram_api::InputFileLocation> as_input_file_location() const {
switch (location_type()) {
case LocationType::Photo:
return make_tl_object<telegram_api::inputFileLocation>(
photo().volume_id_, photo().local_id_, photo().secret_,
BufferSlice(FileReferenceView(file_reference_).download()));
case LocationType::Photo: {
switch (photo().source_.type) {
case PhotoSizeSource::Type::Empty:
return make_tl_object<telegram_api::inputFileLocation>(
photo().volume_id_, photo().local_id_, photo().secret_,
BufferSlice(FileReferenceView(file_reference_).download()));
case PhotoSizeSource::Type::Thumbnail: {
auto &thumbnail = photo().source_.thumbnail();
switch (file_type_) {
case FileType::Photo:
return make_tl_object<telegram_api::inputPhotoFileLocation>(
photo().id_, photo().access_hash_, BufferSlice(FileReferenceView(file_reference_).download()),
std::string(1, thumbnail.thumbnail_type));
case FileType::Thumbnail:
return make_tl_object<telegram_api::inputDocumentFileLocation>(
photo().id_, photo().access_hash_, BufferSlice(FileReferenceView(file_reference_).download()),
std::string(1, thumbnail.thumbnail_type));
default:
case FileType::EncryptedThumbnail:
UNREACHABLE();
}
}
case PhotoSizeSource::Type::DialogPhoto: {
LOG(ERROR) << "DIALOG PHOTO";
auto &dialog_photo = photo().source_.dialog_photo();
return make_tl_object<telegram_api::inputPeerPhotoFileLocation>(
dialog_photo.is_big * telegram_api::inputPeerPhotoFileLocation::Flags::BIG_MASK, dialog_photo.is_big,
dialog_photo.input_peer.as_telegram_api(), photo().volume_id_, photo().local_id_);
}
case PhotoSizeSource::Type::StickerSetThumbnail: {
LOG(ERROR) << "StickerSetThumbnail";
auto &sticker_set_thumbnail = photo().source_.sticker_set_thumbnail();
return make_tl_object<telegram_api::inputStickerSetThumb>(
sticker_set_thumbnail.input_sticker_set.as_telegram_api(), photo().volume_id_, photo().local_id_);
}
}
}
case LocationType::Common:
if (is_encrypted_secret()) {
return make_tl_object<telegram_api::inputEncryptedFileLocation>(common().id_, common().access_hash_);
@ -531,7 +565,7 @@ class FullRemoteFileLocation {
: file_type_(source.file_type)
, dc_id_(dc_id)
, file_reference_(FileReferenceView::create_one(file_reference))
, variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, -1, local_id}) { // TODO(now) use source
, variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, -1, local_id, source}) {
CHECK(is_photo());
check_file_reference();
}

View File

@ -9,12 +9,14 @@
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileType.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/Version.h"
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/Variant.h"
#include "td/telegram/Photo.hpp"
namespace td {
template <class StorerT>
@ -45,6 +47,7 @@ void PhotoRemoteFileLocation::store(StorerT &storer) const {
store(volume_id_, storer);
store(secret_, storer);
store(local_id_, storer);
store(source_, storer);
}
template <class ParserT>
@ -55,6 +58,9 @@ void PhotoRemoteFileLocation::parse(ParserT &parser) {
parse(volume_id_, parser);
parse(secret_, parser);
parse(local_id_, parser);
if (parser.version() >= static_cast<int32>(Version::PhotoSizeSource)) {
parse(source_, parser);
}
}
template <class StorerT>
@ -63,6 +69,7 @@ void PhotoRemoteFileLocation::AsKey::store(StorerT &storer) const {
store(key.id_, storer);
store(key.volume_id_, storer);
store(key.local_id_, storer);
store(key.source_.as_key(), storer);
}
template <class StorerT>

View File

@ -19,6 +19,7 @@
#include "td/telegram/misc.h"
#include "td/telegram/SecureStorage.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/actor/SleepActor.h"
@ -2618,7 +2619,12 @@ Result<FileId> FileManager::from_persistent_id_v2(Slice binary, FileType file_ty
binary.remove_suffix(1);
auto decoded_binary = zero_decode(binary);
FullRemoteFileLocation remote_location;
auto status = unserialize(remote_location, decoded_binary);
logevent::WithVersion<TlParser> parser(decoded_binary);
//TODO(now): encode version?
parser.set_version(static_cast<int32>(Version::Initial));
parse(remote_location, parser);
parser.fetch_end();
auto status = parser.get_status();
if (status.is_error()) {
return Status::Error(10, "Wrong remote file id specified: can't unserialize it");
}

View File

@ -14,6 +14,7 @@
#include "td/telegram/files/FileType.h"
#include "td/telegram/Global.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/logevent/LogEvent.h" // WithVersion
#include "td/db/SqliteKeyValue.h"
@ -57,7 +58,7 @@ void scan_db(CancellationToken &token, CallbackT &&callback) {
if (value.substr(0, 2) == "@@") {
return true;
}
TlParser parser(value);
logevent::WithVersion<TlParser> parser(value);
FileData data;
data.parse(parser, false);
if (parser.get_status().is_error()) {
@ -107,35 +108,33 @@ void scan_fs(CancellationToken &token, CallbackT &&callback) {
continue;
}
auto files_dir = get_files_dir(file_type);
td::walk_path(files_dir,
[&](CSlice path, WalkPath::Type type) {
if (token) {
return WalkPath::Action::Abort;
}
if (type != WalkPath::Type::NotDir) {
return WalkPath::Action::Continue;
}
auto r_stat = stat(path);
if (r_stat.is_error()) {
LOG(WARNING) << "Stat in files gc failed: " << r_stat.error();
return WalkPath::Action::Continue;
}
auto stat = r_stat.move_as_ok();
if (ends_with(path, "/.nomedia") && stat.size_ == 0) {
// skip .nomedia file
return WalkPath::Action::Continue;
}
td::walk_path(files_dir, [&](CSlice path, WalkPath::Type type) {
if (token) {
return WalkPath::Action::Abort;
}
if (type != WalkPath::Type::NotDir) {
return WalkPath::Action::Continue;
}
auto r_stat = stat(path);
if (r_stat.is_error()) {
LOG(WARNING) << "Stat in files gc failed: " << r_stat.error();
return WalkPath::Action::Continue;
}
auto stat = r_stat.move_as_ok();
if (ends_with(path, "/.nomedia") && stat.size_ == 0) {
// skip .nomedia file
return WalkPath::Action::Continue;
}
FsFileInfo info;
info.path = path.str();
info.size = stat.size_;
info.file_type = file_type;
info.atime_nsec = stat.atime_nsec_;
info.mtime_nsec = stat.mtime_nsec_;
callback(info);
return WalkPath::Action::Continue;
})
.ignore();
FsFileInfo info;
info.path = path.str();
info.size = stat.size_;
info.file_type = file_type;
info.atime_nsec = stat.atime_nsec_;
info.mtime_nsec = stat.mtime_nsec_;
callback(info);
return WalkPath::Action::Continue;
}).ignore();
}
}
} // namespace