Update API and use WebDocument for inline bots.

This commit is contained in:
John Preston 2018-03-04 23:04:13 +03:00
parent 09aba596ac
commit 0f901b3728
18 changed files with 536 additions and 238 deletions

View File

@ -460,11 +460,11 @@ photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> =
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#ea52fe5a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes cdn_file_hashes:Vector<CdnFileHash> = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int = DcOption;
config#e644ec1f flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int = Config;
config#86b5778e flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
@ -569,8 +569,6 @@ stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
messages.allStickersNotModified#e86602c3 = messages.AllStickers;
messages.allStickers#edfd405f hash:int sets:Vector<StickerSet> = messages.AllStickers;
disabledFeature#ae636f24 feature:string description:string = DisabledFeature;
messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;
contactLinkUnknown#5f4f9247 = ContactLink;
@ -697,7 +695,7 @@ inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:s
inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineResult#2cbbe15a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult;
@ -708,7 +706,7 @@ botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:f
botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult;
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;
@ -839,6 +837,7 @@ paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string e
paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;
webDocument#c61acbd8 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> dc_id:int = WebDocument;
webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
@ -927,8 +926,6 @@ channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?tru
popularContact#5ce14175 client_id:long importers:int = PopularContact;
cdnFileHash#77eec38f offset:int limit:int hash:bytes = CdnFileHash;
messages.favedStickersNotModified#9e8fa6d3 = messages.FavedStickers;
messages.favedStickers#f37f2f16 hash:int packs:Vector<StickerPack> stickers:Vector<Document> = messages.FavedStickers;
@ -959,6 +956,8 @@ dialogPeerFeed#da429411 feed_id:int = DialogPeer;
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
feedPosition#5059dc73 date:int peer:Peer id:int = FeedPosition;
messages.feedMessagesNotModified#4678d0cf = messages.FeedMessages;
@ -996,7 +995,7 @@ auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentC
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
account.registerDevice#1389cc token_type:int token:string app_sandbox:Bool other_uids:Vector<int> = Bool;
account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
@ -1061,6 +1060,7 @@ messages.forwardMessages#708e0195 flags:# silent:flags.5?true background:flags.6
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.hideReportSpam#a8f1709b peer:InputPeer = Bool;
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
messages.report#bd82b658 peer:InputPeer id:Vector<int> reason:ReportReason = Bool;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull;
messages.editChatTitle#dc452855 chat_id:int title:string = Updates;
@ -1156,8 +1156,9 @@ upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
upload.reuploadCdnFile#1af91c09 file_token:bytes request_token:bytes = Vector<CdnFileHash>;
upload.getCdnFileHashes#f715c87b file_token:bytes offset:int = Vector<CdnFileHash>;
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector<FileHash>;
upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector<FileHash>;
upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<FileHash>;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;

View File

@ -717,11 +717,14 @@ void DocumentData::save(
if (fromCloud == LoadFromCloudOrLocal) _loader->permitLoadFromCloud();
} else {
status = FileReady;
if (!_access && !_url.isEmpty()) {
if (hasWebLocation()) {
_loader = new mtpFileLoader(&_urlLocation, size, fromCloud, autoLoading);
} else if (!_access && !_url.isEmpty()) {
_loader = new webFileLoader(_url, toFile, fromCloud, autoLoading);
} else {
_loader = new mtpFileLoader(_dc, id, _access, _version, locationType(), toFile, size, (saveToCache() ? LoadToCacheAsWell : LoadToFileOnly), fromCloud, autoLoading);
}
_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*)));
_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
_loader->start();
@ -935,8 +938,12 @@ bool DocumentData::hasRemoteLocation() const {
return (_dc != 0 && _access != 0);
}
bool DocumentData::hasWebLocation() const {
return _urlLocation.dc() != 0 && _urlLocation.accessHash() != 0;
}
bool DocumentData::isValid() const {
return hasRemoteLocation() || !_url.isEmpty();
return hasRemoteLocation() || hasWebLocation() || !_url.isEmpty();
}
MTPInputDocument DocumentData::mtpInput() const {
@ -1086,6 +1093,10 @@ void DocumentData::setContentUrl(const QString &url) {
_url = url;
}
void DocumentData::setWebLocation(const WebFileLocation &location) {
_urlLocation = location;
}
void DocumentData::collectLocalData(DocumentData *local) {
if (local == this) return;

View File

@ -148,7 +148,9 @@ public:
bool setRemoteVersion(int32 version); // Returns true if version has changed.
void setRemoteLocation(int32 dc, uint64 access);
void setContentUrl(const QString &url);
void setWebLocation(const WebFileLocation &location);
bool hasRemoteLocation() const;
bool hasWebLocation() const;
bool isValid() const;
MTPInputDocument mtpInput() const;
@ -198,6 +200,7 @@ private:
QString _url;
QString _filename;
QString _mimeString;
WebFileLocation _urlLocation;
not_null<AuthSession*> _session;

View File

@ -54,43 +54,9 @@ Invoice ComputeInvoiceData(const MTPDmessageMediaInvoice &data) {
if (data.has_receipt_msg_id()) {
result.receiptMsgId = data.vreceipt_msg_id.v;
}
if (data.has_photo() && data.vphoto.type() == mtpc_webDocument) {
auto &doc = data.vphoto.c_webDocument();
auto imageSize = QSize();
for (auto &attribute : doc.vattributes.v) {
if (attribute.type() == mtpc_documentAttributeImageSize) {
auto &size = attribute.c_documentAttributeImageSize();
imageSize = QSize(size.vw.v, size.vh.v);
break;
}
}
if (!imageSize.isEmpty()) {
auto thumbsize = shrinkToKeepAspect(imageSize.width(), imageSize.height(), 100, 100);
auto thumb = ImagePtr(thumbsize.width(), thumbsize.height());
auto mediumsize = shrinkToKeepAspect(imageSize.width(), imageSize.height(), 320, 320);
auto medium = ImagePtr(mediumsize.width(), mediumsize.height());
// We don't use size from WebDocument, because it is not reliable.
// It can be > 0 and different from the real size that we get in upload.WebFile result.
auto filesize = 0; // doc.vsize.v;
auto full = ImagePtr(
WebFileImageLocation(
imageSize.width(),
imageSize.height(),
doc.vdc_id.v,
doc.vurl.v,
doc.vaccess_hash.v),
filesize);
auto photoId = rand_value<PhotoId>();
result.photo = Auth().data().photo(
photoId,
uint64(0),
unixtime(),
thumb,
medium,
full);
}
if (data.has_photo()) {
const auto thumb = ImagePtr();
result.photo = Auth().data().photoFromWeb(data.vphoto, thumb);
}
return result;
}

View File

@ -644,6 +644,32 @@ void Session::photoConvert(
photoApplyFields(original, data);
}
PhotoData *Session::photoFromWeb(
const MTPWebDocument &data,
ImagePtr thumb) {
const auto full = ImagePtr(data);
if (full->isNull()) {
return nullptr;
}
const auto width = full->width();
const auto height = full->height();
if (thumb->isNull()) {
auto thumbsize = shrinkToKeepAspect(width, height, 100, 100);
thumb = ImagePtr(thumbsize.width(), thumbsize.height());
}
auto mediumsize = shrinkToKeepAspect(width, height, 320, 320);
auto medium = ImagePtr(mediumsize.width(), mediumsize.height());
return photo(
rand_value<PhotoId>(),
uint64(0),
unixtime(),
thumb,
medium,
full);
}
void Session::photoApplyFields(
not_null<PhotoData*> photo,
const MTPPhoto &data) {
@ -850,6 +876,59 @@ void Session::documentConvert(
}
}
DocumentData *Session::documentFromWeb(
const MTPWebDocument &data,
ImagePtr thumb) {
switch (data.type()) {
case mtpc_webDocument:
return documentFromWeb(data.c_webDocument(), thumb);
case mtpc_webDocumentNoProxy:
return documentFromWeb(data.c_webDocumentNoProxy(), thumb);
}
Unexpected("Type in Session::documentFromWeb.");
}
DocumentData *Session::documentFromWeb(
const MTPDwebDocument &data,
ImagePtr thumb) {
const auto result = document(
rand_value<DocumentId>(),
uint64(0),
int32(0),
unixtime(),
data.vattributes.v,
data.vmime_type.v,
thumb,
MTP::maindc(),
int32(0), // data.vsize.v
StorageImageLocation());
result->setWebLocation(WebFileLocation(
data.vdc_id.v,
data.vurl.v,
data.vaccess_hash.v));
return result;
}
DocumentData *Session::documentFromWeb(
const MTPDwebDocumentNoProxy &data,
ImagePtr thumb) {
const auto result = document(
rand_value<DocumentId>(),
uint64(0),
int32(0),
unixtime(),
data.vattributes.v,
data.vmime_type.v,
thumb,
MTP::maindc(),
int32(0), // data.vsize.v
StorageImageLocation());
result->setContentUrl(qs(data.vurl));
return result;
}
void Session::documentApplyFields(
not_null<DocumentData*> document,
const MTPDocument &data) {

View File

@ -226,6 +226,7 @@ public:
void photoConvert(
not_null<PhotoData*> original,
const MTPPhoto &data);
PhotoData *photoFromWeb(const MTPWebDocument &data, ImagePtr thumb);
not_null<DocumentData*> document(DocumentId id);
not_null<DocumentData*> document(const MTPDocument &data);
@ -247,6 +248,9 @@ public:
void documentConvert(
not_null<DocumentData*> original,
const MTPDocument &data);
DocumentData *documentFromWeb(
const MTPWebDocument &data,
ImagePtr thumb);
not_null<WebPageData*> webpage(WebPageId id);
not_null<WebPageData*> webpage(const MTPWebPage &data);
@ -397,6 +401,12 @@ private:
int32 dc,
int32 size,
const StorageImageLocation &thumbLocation);
DocumentData *documentFromWeb(
const MTPDwebDocument &data,
ImagePtr thumb);
DocumentData *documentFromWeb(
const MTPDwebDocumentNoProxy &data,
ImagePtr thumb);
void webpageApplyFields(
not_null<WebPageData*> page,

View File

@ -511,7 +511,6 @@ struct Data {
int32 OnlineCloudTimeout = 300000;
int32 NotifyCloudDelay = 30000;
int32 NotifyDefaultDelay = 1500;
int32 ChatBigSize = 10;
int32 PushChatPeriod = 60000;
int32 PushChatLimit = 2;
int32 SavedGifsLimit = 200;
@ -631,7 +630,6 @@ DefineVar(Global, int32, OnlineFocusTimeout);
DefineVar(Global, int32, OnlineCloudTimeout);
DefineVar(Global, int32, NotifyCloudDelay);
DefineVar(Global, int32, NotifyDefaultDelay);
DefineVar(Global, int32, ChatBigSize);
DefineVar(Global, int32, PushChatPeriod);
DefineVar(Global, int32, PushChatLimit);
DefineVar(Global, int32, SavedGifsLimit);

View File

@ -328,7 +328,6 @@ DeclareVar(int32, OnlineFocusTimeout); // not from config
DeclareVar(int32, OnlineCloudTimeout);
DeclareVar(int32, NotifyCloudDelay);
DeclareVar(int32, NotifyDefaultDelay);
DeclareVar(int32, ChatBigSize);
DeclareVar(int32, PushChatPeriod);
DeclareVar(int32, PushChatLimit);
DeclareVar(int32, SavedGifsLimit);

View File

@ -154,7 +154,7 @@ QPixmap ItemBase::getResultContactAvatar(int width, int height) const {
}
int ItemBase::getResultDuration() const {
return _result->_duration;
return 0;
}
QString ItemBase::getResultUrl() const {

View File

@ -18,6 +18,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "auth_session.h"
namespace InlineBots {
namespace {
QString GetContentUrl(const MTPWebDocument &document) {
switch (document.type()) {
case mtpc_webDocument:
return qs(document.c_webDocument().vurl);
case mtpc_webDocumentNoProxy:
return qs(document.c_webDocumentNoProxy().vurl);
}
Unexpected("Type in GetContentUrl.");
}
} // namespace
Result::Result(const Creator &creator) : _queryId(creator.queryId), _type(creator.type) {
}
@ -58,24 +71,30 @@ std::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
const MTPBotInlineMessage *message = nullptr;
switch (mtpData.type()) {
case mtpc_botInlineResult: {
const auto &r(mtpData.c_botInlineResult());
const auto &r = mtpData.c_botInlineResult();
result->_id = qs(r.vid);
if (r.has_title()) result->_title = qs(r.vtitle);
if (r.has_description()) result->_description = qs(r.vdescription);
if (r.has_url()) result->_url = qs(r.vurl);
if (r.has_thumb_url()) result->_thumb_url = qs(r.vthumb_url);
if (r.has_content_type()) result->_content_type = qs(r.vcontent_type);
if (r.has_content_url()) result->_content_url = qs(r.vcontent_url);
if (r.has_w()) result->_width = r.vw.v;
if (r.has_h()) result->_height = r.vh.v;
if (r.has_duration()) result->_duration = r.vduration.v;
if (!result->_thumb_url.startsWith(qstr("http://"), Qt::CaseInsensitive) && !result->_thumb_url.startsWith(qstr("https://"), Qt::CaseInsensitive)) {
result->_thumb_url = QString();
if (r.has_thumb()) {
result->_thumb = ImagePtr(r.vthumb, result->thumbBox());
}
if (r.has_content()) {
result->_content_url = GetContentUrl(r.vcontent);
if (result->_type == Type::Photo) {
result->_photo = Auth().data().photoFromWeb(
r.vcontent,
result->_thumb);
} else {
result->_document = Auth().data().documentFromWeb(
result->adjustAttributes(r.vcontent),
result->_thumb);
}
}
message = &r.vsend_message;
} break;
case mtpc_botInlineMediaResult: {
const auto &r(mtpData.c_botInlineMediaResult());
const auto &r = mtpData.c_botInlineMediaResult();
result->_id = qs(r.vid);
if (r.has_title()) result->_title = qs(r.vtitle);
if (r.has_description()) result->_description = qs(r.vdescription);
@ -96,15 +115,17 @@ std::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
// Ensure required media fields for layouts.
if (result->_type == Type::Photo) {
if (!result->_photo && result->_content_url.isEmpty()) {
if (!result->_photo) {
return nullptr;
}
result->createPhoto();
} else if (result->_type == Type::File || result->_type == Type::Gif || result->_type == Type::Sticker) {
if (!result->_document && result->_content_url.isEmpty()) {
} else if (result->_type == Type::Audio
|| result->_type == Type::File
|| result->_type == Type::Video
|| result->_type == Type::Sticker
|| result->_type == Type::Gif) {
if (!result->_document) {
return nullptr;
}
result->createDocument();
}
switch (message->type()) {
@ -114,13 +135,17 @@ std::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
? TextUtilities::EntitiesFromMTP(r.ventities.v)
: EntitiesInText();
if (result->_type == Type::Photo) {
result->createPhoto();
if (!result->_photo) {
return nullptr;
}
result->sendData = std::make_unique<internal::SendPhoto>(result->_photo, qs(r.vmessage), entities);
} else if (result->_type == Type::Game) {
result->createGame();
result->sendData = std::make_unique<internal::SendGame>(result->_game);
} else {
result->createDocument();
if (!result->_document) {
return nullptr;
}
result->sendData = std::make_unique<internal::SendFile>(result->_document, qs(r.vmessage), entities);
}
if (r.has_reply_markup()) {
@ -135,9 +160,17 @@ std::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
: EntitiesInText();
result->sendData = std::make_unique<internal::SendText>(qs(r.vmessage), entities, r.is_no_webpage());
if (result->_type == Type::Photo) {
result->createPhoto();
} else if (result->_type == Type::Audio || result->_type == Type::File || result->_type == Type::Video || result->_type == Type::Sticker || result->_type == Type::Gif) {
result->createDocument();
if (!result->_photo) {
return nullptr;
}
} else if (result->_type == Type::Audio
|| result->_type == Type::File
|| result->_type == Type::Video
|| result->_type == Type::Sticker
|| result->_type == Type::Gif) {
if (!result->_document) {
return nullptr;
}
}
if (r.has_reply_markup()) {
result->_mtpKeyboard = std::make_unique<MTPReplyMarkup>(r.vreply_markup);
@ -186,9 +219,6 @@ std::unique_ptr<Result> Result::create(uint64 queryId, const MTPBotInlineResult
return nullptr;
}
if (result->_thumb->isNull() && !result->_thumb_url.isEmpty()) {
result->_thumb = ImagePtr(result->_thumb_url);
}
LocationCoords location;
if (result->getLocationCoords(&location)) {
int32 w = st::inlineThumbSize, h = st::inlineThumbSize;
@ -307,80 +337,6 @@ QString Result::getLayoutDescription() const {
Result::~Result() {
}
void Result::createPhoto() {
if (_photo) return;
if (_thumb_url.isEmpty()) {
QSize thumbsize = shrinkToKeepAspect(_width, _height, 100, 100);
_thumb = ImagePtr(thumbsize.width(), thumbsize.height());
} else {
_thumb = ImagePtr(_thumb_url, QSize(320, 320));
}
// ImagePtr medium = ImagePtr(_content_url, QSize(320, 320));
QSize mediumsize = shrinkToKeepAspect(_width, _height, 320, 320);
ImagePtr medium = ImagePtr(mediumsize.width(), mediumsize.height());
ImagePtr full = ImagePtr(_content_url, _width, _height);
auto photoId = rand_value<PhotoId>();
_photo = Auth().data().photo(
photoId,
uint64(0),
unixtime(),
_thumb,
medium,
full);
_photo->thumb = _thumb;
}
void Result::createDocument() {
if (_document) return;
if (!_thumb_url.isEmpty()) {
_thumb = ImagePtr(_thumb_url, QSize(90, 90));
}
QString mime = _content_type;
QVector<MTPDocumentAttribute> attributes;
auto dimensions = QSize(_width, _height);
if (_type == Type::Gif) {
auto filename = (mime == qstr("video/mp4") ? "animation.gif.mp4" : "animation.gif");
attributes.push_back(MTP_documentAttributeFilename(MTP_string(filename)));
attributes.push_back(MTP_documentAttributeAnimated());
auto flags = MTPDdocumentAttributeVideo::Flags(0);
attributes.push_back(MTP_documentAttributeVideo(MTP_flags(flags), MTP_int(_duration), MTP_int(_width), MTP_int(_height)));
} else if (_type == Type::Video) {
auto flags = MTPDdocumentAttributeVideo::Flags(0);
attributes.push_back(MTP_documentAttributeVideo(MTP_flags(flags), MTP_int(_duration), MTP_int(_width), MTP_int(_height)));
} else if (_type == Type::Audio) {
auto flags = MTPDdocumentAttributeAudio::Flags(0);
if (mime == qstr("audio/ogg")) {
flags |= MTPDdocumentAttributeAudio::Flag::f_voice;
} else {
QStringList p = mimeTypeForName(mime).globPatterns();
QString pattern = p.isEmpty() ? QString() : p.front();
QString extension = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
QString filename = filedialogDefaultName(qsl("inline"), extension, QString(), true);
attributes.push_back(MTP_documentAttributeFilename(MTP_string(filename)));
}
attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
}
auto documentId = rand_value<DocumentId>();
_document = Auth().data().document(
documentId,
uint64(0),
int32(0),
unixtime(),
attributes,
mime,
_thumb,
MTP::maindc(),
int32(0),
StorageImageLocation());
_document->setContentUrl(_content_url);
}
void Result::createGame() {
if (_game) return;
@ -395,4 +351,97 @@ void Result::createGame() {
_document);
}
QSize Result::thumbBox() const {
return (_type == Type::Photo) ? QSize(100, 100) : QSize(90, 90);
}
MTPWebDocument Result::adjustAttributes(const MTPWebDocument &document) {
switch (document.type()) {
case mtpc_webDocument: {
const auto &data = document.c_webDocument();
return MTP_webDocument(
data.vurl,
data.vaccess_hash,
data.vsize,
data.vmime_type,
adjustAttributes(data.vattributes, data.vmime_type),
data.vdc_id);
} break;
case mtpc_webDocumentNoProxy: {
const auto &data = document.c_webDocumentNoProxy();
return MTP_webDocumentNoProxy(
data.vurl,
data.vsize,
data.vmime_type,
adjustAttributes(data.vattributes, data.vmime_type));
} break;
}
Unexpected("Type in InlineBots::Result::adjustAttributes.");
}
MTPVector<MTPDocumentAttribute> Result::adjustAttributes(
const MTPVector<MTPDocumentAttribute> &existing,
const MTPstring &mimeType) {
auto result = existing.v;
const auto find = [&](mtpTypeId attributeType) {
return ranges::find(
result,
attributeType,
[](const MTPDocumentAttribute &value) { return value.type(); });
};
const auto exists = [&](mtpTypeId attributeType) {
return find(attributeType) != result.cend();
};
const auto mime = qs(mimeType);
if (_type == Type::Gif) {
if (!exists(mtpc_documentAttributeFilename)) {
auto filename = (mime == qstr("video/mp4")
? "animation.gif.mp4"
: "animation.gif");
result.push_back(MTP_documentAttributeFilename(
MTP_string(filename)));
}
if (!exists(mtpc_documentAttributeAnimated)) {
result.push_back(MTP_documentAttributeAnimated());
}
} else if (_type == Type::Audio) {
const auto audio = find(mtpc_documentAttributeAudio);
if (audio != result.cend()) {
using Flag = MTPDdocumentAttributeAudio::Flag;
if (mime == qstr("audio/ogg")) {
// We always treat audio/ogg as a voice message.
// It was that way before we started to get attributes here.
const auto &fields = audio->c_documentAttributeAudio();
if (!(fields.vflags.v & Flag::f_voice)) {
*audio = MTP_documentAttributeAudio(
MTP_flags(fields.vflags.v | Flag::f_voice),
fields.vduration,
fields.vtitle,
fields.vperformer,
fields.vwaveform);
}
}
const auto &fields = audio->c_documentAttributeAudio();
if (!exists(mtpc_documentAttributeFilename)
&& !(fields.vflags.v & Flag::f_voice)) {
const auto p = mimeTypeForName(mime).globPatterns();
auto pattern = p.isEmpty() ? QString() : p.front();
const auto extension = pattern.isEmpty()
? qsl(".unknown")
: pattern.replace('*', QString());
const auto filename = filedialogDefaultName(
qsl("inline"),
extension,
QString(),
true);
result.push_back(
MTP_documentAttributeFilename(MTP_string(filename)));
}
}
}
return MTP_vector<MTPDocumentAttribute>(std::move(result));
}
} // namespace InlineBots

View File

@ -63,9 +63,12 @@ public:
~Result();
private:
void createPhoto();
void createDocument();
void createGame();
QSize thumbBox() const;
MTPWebDocument adjustAttributes(const MTPWebDocument &document);
MTPVector<MTPDocumentAttribute> adjustAttributes(
const MTPVector<MTPDocumentAttribute> &document,
const MTPstring &mimeType);
enum class Type {
Unknown,
@ -92,12 +95,8 @@ private:
uint64 _queryId = 0;
QString _id;
Type _type = Type::Unknown;
QString _title, _description, _url, _thumb_url;
QString _content_type, _content_url;
int _width = 0;
int _height = 0;
int _duration = 0;
QString _title, _description, _url;
QString _content_url;
DocumentData *_document = nullptr;
PhotoData *_photo = nullptr;
GameData *_game = nullptr;

View File

@ -112,6 +112,8 @@ bool Inner::isRestrictedView() {
int Inner::countHeight() {
if (isRestrictedView()) {
return st::stickerPanPadding + _restrictedLabel->height() + st::stickerPanPadding;
} else if (_rows.isEmpty() && !_switchPmButton) {
return st::stickerPanPadding + st::normalFont->height + st::stickerPanPadding;
}
auto result = st::stickerPanPadding;
if (_switchPmButton) {
@ -1087,7 +1089,9 @@ void Widget::onInlineRequest() {
auto it = _inlineCache.find(_inlineQuery);
if (it != _inlineCache.cend()) {
nextOffset = it->second->nextOffset;
if (nextOffset.isEmpty()) return;
if (nextOffset.isEmpty()) {
return;
}
}
Notify::inlineBotRequesting(true);
_inlineRequestId = request(MTPmessages_GetInlineBotResults(MTP_flags(0), _inlineBot->inputUser, _inlineQueryPeer->input, MTPInputGeoPoint(), MTP_string(_inlineQuery), MTP_string(nextOffset))).done([this](const MTPmessages_BotResults &result, mtpRequestId requestId) {

View File

@ -2030,8 +2030,15 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
QWriteLocker locker(sessionData->haveReceivedMutex());
sessionData->haveReceivedUpdates().push_back(SerializedMessage(update));
if (cons != mtpc_updatesTooLong && cons != mtpc_updateShortMessage && cons != mtpc_updateShortChatMessage && cons != mtpc_updateShortSentMessage && cons != mtpc_updateShort && cons != mtpc_updatesCombined && cons != mtpc_updates) {
LOG(("Message Error: unknown constructor %1").arg(cons)); // maybe new api?..
if (cons != mtpc_updatesTooLong
&& cons != mtpc_updateShortMessage
&& cons != mtpc_updateShortChatMessage
&& cons != mtpc_updateShortSentMessage
&& cons != mtpc_updateShort
&& cons != mtpc_updatesCombined
&& cons != mtpc_updates) {
// Maybe some new unknown update?
LOG(("Message Error: unknown constructor %1").arg(cons));
}
} else {
LOG(("Message Error: unexpected updates in dcType: %1").arg(static_cast<int>(_dcType)));

View File

@ -598,7 +598,6 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
Global::SetOnlineCloudTimeout(data.vonline_cloud_timeout_ms.v);
Global::SetNotifyCloudDelay(data.vnotify_cloud_delay_ms.v);
Global::SetNotifyDefaultDelay(data.vnotify_default_delay_ms.v);
Global::SetChatBigSize(data.vchat_big_size.v);
Global::SetPushChatPeriod(data.vpush_chat_period_ms.v);
Global::SetPushChatLimit(data.vpush_chat_limit.v);
Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v);

View File

@ -416,7 +416,7 @@ mtpFileLoader::mtpFileLoader(int32 dc, uint64 id, uint64 accessHash, int32 versi
_queue = &i.value();
}
mtpFileLoader::mtpFileLoader(const WebFileImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
mtpFileLoader::mtpFileLoader(const WebFileLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading)
: FileLoader(QString(), size, UnknownFileLocation, LoadToCacheAsWell, fromCloud, autoLoading)
, _dcId(location->dc())
, _urlLocation(location) {
@ -484,18 +484,19 @@ void mtpFileLoader::makeRequest(int offset) {
return MTP::send(MTPupload_GetWebFile(MTP_inputWebFileLocation(MTP_bytes(_urlLocation->url()), MTP_long(_urlLocation->accessHash())), MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::webPartLoaded), rpcFail(&mtpFileLoader::partFailed), shiftedDcId, 50);
} else {
Assert(requestData.dcId == _dcId);
auto location = [this] {
if (_location) {
return MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
}
return MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_accessHash), MTP_int(_version));
};
return MTP::send(MTPupload_GetFile(location(), MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::normalPartLoaded), rpcFail(&mtpFileLoader::partFailed), shiftedDcId, 50);
return MTP::send(MTPupload_GetFile(computeLocation(), MTP_int(offset), MTP_int(limit)), rpcDone(&mtpFileLoader::normalPartLoaded), rpcFail(&mtpFileLoader::partFailed), shiftedDcId, 50);
}
};
placeSentRequest(send(), requestData);
}
MTPInputFileLocation mtpFileLoader::computeLocation() const {
if (_location) {
return MTP_inputFileLocation(MTP_long(_location->volume()), MTP_int(_location->local()), MTP_long(_location->secret()));
}
return MTP_inputDocumentFileLocation(MTP_long(_id), MTP_long(_accessHash), MTP_int(_version));
}
void mtpFileLoader::requestMoreCdnFileHashes() {
Expects(!_finished);
@ -609,13 +610,13 @@ mtpFileLoader::CheckCdnHashResult mtpFileLoader::checkCdnFileHash(int offset, ba
return CheckCdnHashResult::Good;
}
void mtpFileLoader::reuploadDone(const MTPVector<MTPCdnFileHash> &result, mtpRequestId requestId) {
void mtpFileLoader::reuploadDone(const MTPVector<MTPFileHash> &result, mtpRequestId requestId) {
auto offset = finishSentRequestGetOffset(requestId);
addCdnHashes(result.v);
makeRequest(offset);
}
void mtpFileLoader::getCdnFileHashesDone(const MTPVector<MTPCdnFileHash> &result, mtpRequestId requestId) {
void mtpFileLoader::getCdnFileHashesDone(const MTPVector<MTPFileHash> &result, mtpRequestId requestId) {
Expects(!_finished);
Expects(_cdnHashesRequestId == requestId);
@ -805,7 +806,7 @@ bool mtpFileLoader::cdnPartFailed(const RPCError &error, mtpRequestId requestId)
}
if (error.type() == qstr("FILE_TOKEN_INVALID") || error.type() == qstr("REQUEST_TOKEN_INVALID")) {
auto offset = finishSentRequestGetOffset(requestId);
changeCDNParams(offset, 0, QByteArray(), QByteArray(), QByteArray(), QVector<MTPCdnFileHash>());
changeCDNParams(offset, 0, QByteArray(), QByteArray(), QByteArray(), QVector<MTPFileHash>());
return true;
}
return partFailed(error);
@ -819,19 +820,29 @@ void mtpFileLoader::cancelRequests() {
}
}
void mtpFileLoader::switchToCDN(int offset, const MTPDupload_fileCdnRedirect &redirect) {
changeCDNParams(offset, redirect.vdc_id.v, redirect.vfile_token.v, redirect.vencryption_key.v, redirect.vencryption_iv.v, redirect.vcdn_file_hashes.v);
void mtpFileLoader::switchToCDN(
int offset,
const MTPDupload_fileCdnRedirect &redirect) {
changeCDNParams(
offset,
redirect.vdc_id.v,
redirect.vfile_token.v,
redirect.vencryption_key.v,
redirect.vencryption_iv.v,
redirect.vfile_hashes.v);
}
void mtpFileLoader::addCdnHashes(const QVector<MTPCdnFileHash> &hashes) {
void mtpFileLoader::addCdnHashes(const QVector<MTPFileHash> &hashes) {
for_const (auto &hash, hashes) {
Assert(hash.type() == mtpc_cdnFileHash);
auto &data = hash.c_cdnFileHash();
_cdnFileHashes.emplace(data.voffset.v, CdnFileHash { data.vlimit.v, data.vhash.v });
Assert(hash.type() == mtpc_fileHash);
auto &data = hash.c_fileHash();
_cdnFileHashes.emplace(
data.voffset.v,
CdnFileHash { data.vlimit.v, data.vhash.v });
}
}
void mtpFileLoader::changeCDNParams(int offset, MTP::DcId dcId, const QByteArray &token, const QByteArray &encryptionKey, const QByteArray &encryptionIV, const QVector<MTPCdnFileHash> &hashes) {
void mtpFileLoader::changeCDNParams(int offset, MTP::DcId dcId, const QByteArray &token, const QByteArray &encryptionKey, const QByteArray &encryptionIV, const QVector<MTPFileHash> &hashes) {
if (dcId != 0 && (encryptionKey.size() != MTP::CTRState::KeySize || encryptionIV.size() != MTP::CTRState::IvecSize)) {
LOG(("Message Error: Wrong key (%1) / iv (%2) size in CDN params").arg(encryptionKey.size()).arg(encryptionIV.size()));
cancel(true);

View File

@ -176,14 +176,14 @@ protected:
};
class StorageImageLocation;
class WebFileImageLocation;
class WebFileLocation;
class mtpFileLoader : public FileLoader, public RPCSender {
Q_OBJECT
public:
mtpFileLoader(const StorageImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
mtpFileLoader(int32 dc, uint64 id, uint64 accessHash, int32 version, LocationType type, const QString &toFile, int32 size, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading);
mtpFileLoader(const WebFileImageLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
mtpFileLoader(const WebFileLocation *location, int32 size, LoadFromCloudSetting fromCloud, bool autoLoading);
int32 currentOffset(bool includeSkipped = false) const override;
@ -217,13 +217,14 @@ private:
RequestData prepareRequest(int offset) const;
void makeRequest(int offset);
MTPInputFileLocation computeLocation() const;
bool loadPart() override;
void normalPartLoaded(const MTPupload_File &result, mtpRequestId requestId);
void webPartLoaded(const MTPupload_WebFile &result, mtpRequestId requestId);
void cdnPartLoaded(const MTPupload_CdnFile &result, mtpRequestId requestId);
void reuploadDone(const MTPVector<MTPCdnFileHash> &result, mtpRequestId requestId);
void reuploadDone(const MTPVector<MTPFileHash> &result, mtpRequestId requestId);
void requestMoreCdnFileHashes();
void getCdnFileHashesDone(const MTPVector<MTPCdnFileHash> &result, mtpRequestId requestId);
void getCdnFileHashesDone(const MTPVector<MTPFileHash> &result, mtpRequestId requestId);
bool feedPart(int offset, base::const_byte_span bytes);
void partLoaded(int offset, base::const_byte_span bytes);
@ -234,8 +235,8 @@ private:
void placeSentRequest(mtpRequestId requestId, const RequestData &requestData);
int finishSentRequestGetOffset(mtpRequestId requestId);
void switchToCDN(int offset, const MTPDupload_fileCdnRedirect &redirect);
void addCdnHashes(const QVector<MTPCdnFileHash> &hashes);
void changeCDNParams(int offset, MTP::DcId dcId, const QByteArray &token, const QByteArray &encryptionKey, const QByteArray &encryptionIV, const QVector<MTPCdnFileHash> &hashes);
void addCdnHashes(const QVector<MTPFileHash> &hashes);
void changeCDNParams(int offset, MTP::DcId dcId, const QByteArray &token, const QByteArray &encryptionKey, const QByteArray &encryptionIV, const QVector<MTPFileHash> &hashes);
enum class CheckCdnHashResult {
NoHash,
@ -257,7 +258,7 @@ private:
uint64 _accessHash = 0;
int32 _version = 0;
const WebFileImageLocation *_urlLocation = nullptr; // for webdocument locations
const WebFileLocation *_urlLocation = nullptr; // for webdocument locations
MTP::DcId _cdnDcId = 0;
QByteArray _cdnToken;

View File

@ -403,7 +403,7 @@ uint64 SinglePixKey(Images::Options options) {
} // namespace
StorageImageLocation StorageImageLocation::Null;
WebFileImageLocation WebFileImageLocation::Null;
WebFileLocation WebFileLocation::Null;
bool Image::isNull() const {
return (this == blank());
@ -1040,25 +1040,45 @@ FileLoader *StorageImage::createLoader(LoadFromCloudSetting fromCloud, bool auto
return new mtpFileLoader(&_location, _size, fromCloud, autoLoading);
}
WebFileImage::WebFileImage(const WebFileImageLocation &location, int32 size)
WebFileImage::WebFileImage(
const WebFileLocation &location,
QSize box,
int size)
: _location(location)
, _box(box)
, _width(0)
, _height(0)
, _size(size) {
}
int32 WebFileImage::countWidth() const {
return _location.width();
WebFileImage::WebFileImage(
const WebFileLocation &location,
int width,
int height,
int size)
: _location(location)
, _width(width)
, _height(height)
, _size(size) {
}
int32 WebFileImage::countHeight() const {
return _location.height();
int WebFileImage::countWidth() const {
return _width;
}
void WebFileImage::setInformation(int32 size, int32 width, int32 height) {
int WebFileImage::countHeight() const {
return _height;
}
void WebFileImage::setInformation(int size, int width, int height) {
_size = size;
_location.setSize(width, height);
_width = width;
_height = height;
}
FileLoader *WebFileImage::createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) {
FileLoader *WebFileImage::createLoader(
LoadFromCloudSetting fromCloud,
bool autoLoading) {
if (_location.isNull()) return 0;
return new mtpFileLoader(&_location, _size, fromCloud, autoLoading);
}
@ -1146,10 +1166,19 @@ void DelayedStorageImage::cancel() {
StorageImage::cancel();
}
WebImage::WebImage(const QString &url, QSize box) : _url(url), _box(box), _size(0), _width(0), _height(0) {
WebImage::WebImage(const QString &url, QSize box)
: _url(url)
, _box(box)
, _size(0)
, _width(0)
, _height(0) {
}
WebImage::WebImage(const QString &url, int width, int height) : _url(url), _size(0), _width(width), _height(height) {
WebImage::WebImage(const QString &url, int width, int height)
: _url(url)
, _size(0)
, _width(width)
, _height(height) {
}
void WebImage::setSize(int width, int height) {
@ -1256,11 +1285,116 @@ StorageImage *getImage(const StorageImageLocation &location, const QByteArray &b
return i.value();
}
WebFileImage *getImage(const WebFileImageLocation &location, int32 size) {
QSize getImageSize(const QVector<MTPDocumentAttribute> &attributes) {
for (const auto &attribute : attributes) {
if (attribute.type() == mtpc_documentAttributeImageSize) {
auto &size = attribute.c_documentAttributeImageSize();
return QSize(size.vw.v, size.vh.v);
}
}
return QSize();
}
Image *getImage(const MTPDwebDocument &document) {
const auto size = getImageSize(document.vattributes.v);
if (size.isEmpty()) {
return blank();
}
// We don't use size from WebDocument, because it is not reliable.
// It can be > 0 and different from the real size that we get in upload.WebFile result.
auto filesize = 0; // document.vsize.v;
return getImage(
WebFileLocation(
document.vdc_id.v,
document.vurl.v,
document.vaccess_hash.v),
size.width(),
size.height(),
filesize);
}
Image *getImage(const MTPDwebDocumentNoProxy &document) {
const auto size = getImageSize(document.vattributes.v);
if (size.isEmpty()) {
return blank();
}
return getImage(qs(document.vurl), size.width(), size.height());
}
Image *getImage(const MTPDwebDocument &document, QSize box) {
const auto size = getImageSize(document.vattributes.v);
if (size.isEmpty()) {
return blank();
}
// We don't use size from WebDocument, because it is not reliable.
// It can be > 0 and different from the real size that we get in upload.WebFile result.
auto filesize = 0; // document.vsize.v;
return getImage(
WebFileLocation(
document.vdc_id.v,
document.vurl.v,
document.vaccess_hash.v),
box,
filesize);
}
Image *getImage(const MTPDwebDocumentNoProxy &document, QSize box) {
const auto size = getImageSize(document.vattributes.v);
if (size.isEmpty()) {
return blank();
}
return getImage(qs(document.vurl), box);
}
Image *getImage(const MTPWebDocument &document) {
switch (document.type()) {
case mtpc_webDocument:
return getImage(document.c_webDocument());
case mtpc_webDocumentNoProxy:
return getImage(document.c_webDocumentNoProxy());
}
Unexpected("Type in getImage(MTPWebDocument).");
}
Image *getImage(const MTPWebDocument &document, QSize box) {
switch (document.type()) {
case mtpc_webDocument:
return getImage(document.c_webDocument(), box);
case mtpc_webDocumentNoProxy:
return getImage(document.c_webDocumentNoProxy(), box);
}
Unexpected("Type in getImage(MTPWebDocument).");
}
WebFileImage *getImage(
const WebFileLocation &location,
QSize box,
int size) {
auto key = storageKey(location);
auto i = webFileImages.constFind(key);
if (i == webFileImages.cend()) {
i = webFileImages.insert(key, new WebFileImage(location, size));
i = webFileImages.insert(
key,
new WebFileImage(location, box, size));
}
return i.value();
}
WebFileImage *getImage(
const WebFileLocation &location,
int width,
int height,
int size) {
auto key = storageKey(location);
auto i = webFileImages.constFind(key);
if (i == webFileImages.cend()) {
i = webFileImages.insert(
key,
new WebFileImage(location, width, height, size));
}
return i.value();
}

View File

@ -183,23 +183,17 @@ inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation
return !(a == b);
}
class WebFileImageLocation {
class WebFileLocation {
public:
WebFileImageLocation() = default;
WebFileImageLocation(int32 width, int32 height, int32 dc, const QByteArray &url, uint64 accessHash) : _widthheight(packIntInt(width, height)), _accessHash(accessHash), _url(url), _dc(dc) {
WebFileLocation() = default;
WebFileLocation(int32 dc, const QByteArray &url, uint64 accessHash)
: _accessHash(accessHash)
, _url(url)
, _dc(dc) {
}
bool isNull() const {
return !_dc;
}
int32 width() const {
return unpackIntFirst(_widthheight);
}
int32 height() const {
return unpackIntSecond(_widthheight);
}
void setSize(int32 width, int32 height) {
_widthheight = packIntInt(width, height);
}
int32 dc() const {
return _dc;
}
@ -210,21 +204,20 @@ public:
return _url;
}
static WebFileImageLocation Null;
static WebFileLocation Null;
private:
uint64 _widthheight = 0;
uint64 _accessHash = 0;
QByteArray _url;
int32 _dc = 0;
friend inline bool operator==(const WebFileImageLocation &a, const WebFileImageLocation &b) {
friend inline bool operator==(const WebFileLocation &a, const WebFileLocation &b) {
return (a._dc == b._dc) && (a._accessHash == b._accessHash) && (a._url == b._url);
}
};
inline bool operator!=(const WebFileImageLocation &a, const WebFileImageLocation &b) {
inline bool operator!=(const WebFileLocation &a, const WebFileLocation &b) {
return !(a == b);
}
@ -354,10 +347,13 @@ inline StorageKey storageKey(const MTPDfileLocation &location) {
inline StorageKey storageKey(const StorageImageLocation &location) {
return storageKey(location.dc(), location.volume(), location.local());
}
inline StorageKey storageKey(const WebFileImageLocation &location) {
inline StorageKey storageKey(const WebFileLocation &location) {
auto url = location.url();
auto sha = hashSha1(url.data(), url.size());
return storageKey(location.dc(), *reinterpret_cast<const uint64*>(sha.data()), *reinterpret_cast<const int32*>(sha.data() + sizeof(uint64)));
return storageKey(
location.dc(),
*reinterpret_cast<const uint64*>(sha.data()),
*reinterpret_cast<const int32*>(sha.data() + sizeof(uint64)));
}
class RemoteImage : public Image {
@ -427,17 +423,25 @@ protected:
class WebFileImage : public RemoteImage {
public:
WebFileImage(const WebFileImageLocation &location, int32 size = 0);
WebFileImage(const WebFileLocation &location, QSize box, int size = 0);
WebFileImage(const WebFileLocation &location, int width, int height, int size = 0);
protected:
void setInformation(int32 size, int32 width, int32 height) override;
void setInformation(int size, int width, int height) override;
FileLoader *createLoader(LoadFromCloudSetting fromCloud, bool autoLoading) override;
WebFileImageLocation _location;
int32 _size;
QSize shrinkBox() const override {
return _box;
}
int32 countWidth() const override;
int32 countHeight() const override;
WebFileLocation _location;
QSize _box;
int _width = 0;
int _height = 0;
int _size = 0;
int countWidth() const override;
int countHeight() const override;
};
@ -476,7 +480,6 @@ private:
class WebImage : public RemoteImage {
public:
// If !box.isEmpty() then resize the image to fit in this box.
WebImage(const QString &url, QSize box = QSize());
WebImage(const QString &url, int width, int height);
@ -484,7 +487,6 @@ public:
void setSize(int width, int height);
protected:
QSize shrinkBox() const override {
return _box;
}
@ -502,16 +504,33 @@ private:
};
namespace internal {
Image *getImage(const QString &file, QByteArray format);
Image *getImage(const QString &url, QSize box);
Image *getImage(const QString &url, int width, int height);
Image *getImage(const QByteArray &filecontent, QByteArray format);
Image *getImage(const QPixmap &pixmap, QByteArray format);
Image *getImage(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
Image *getImage(int32 width, int32 height);
StorageImage *getImage(const StorageImageLocation &location, int32 size = 0);
StorageImage *getImage(const StorageImageLocation &location, const QByteArray &bytes);
WebFileImage *getImage(const WebFileImageLocation &location, int32 size = 0);
Image *getImage(const QString &file, QByteArray format);
Image *getImage(const QString &url, QSize box);
Image *getImage(const QString &url, int width, int height);
Image *getImage(const QByteArray &filecontent, QByteArray format);
Image *getImage(const QPixmap &pixmap, QByteArray format);
Image *getImage(
const QByteArray &filecontent,
QByteArray format,
const QPixmap &pixmap);
Image *getImage(int32 width, int32 height);
StorageImage *getImage(const StorageImageLocation &location, int size = 0);
StorageImage *getImage(
const StorageImageLocation &location,
const QByteArray &bytes);
Image *getImage(const MTPWebDocument &location);
Image *getImage(const MTPWebDocument &location, QSize box);
WebFileImage *getImage(
const WebFileLocation &location,
int width,
int height,
int size = 0);
WebFileImage *getImage(
const WebFileLocation &location,
QSize box,
int size = 0);
} // namespace internal
class ImagePtr : public ManagedPtr<Image> {
@ -533,7 +552,15 @@ public:
}
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes) : Parent(internal::getImage(location, bytes)) {
}
ImagePtr(const WebFileImageLocation &location, int32 size = 0) : Parent(internal::getImage(location, size)) {
ImagePtr(const MTPWebDocument &location) : Parent(internal::getImage(location)) {
}
ImagePtr(const MTPWebDocument &location, QSize box) : Parent(internal::getImage(location, box)) {
}
ImagePtr(const WebFileLocation &location, int width, int height, int size = 0)
: Parent(internal::getImage(location, width, height, size)) {
}
ImagePtr(const WebFileLocation &location, QSize box, int size = 0)
: Parent(internal::getImage(location, box, size)) {
}
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
ImagePtr(int32 width, int32 height) : Parent(internal::getImage(width, height)) {