Update API scheme on layer 144.

This commit is contained in:
John Preston 2022-07-05 23:36:25 +04:00
parent c01d9747e7
commit b87fd601ab
5 changed files with 79 additions and 88 deletions

View file

@ -629,7 +629,7 @@ messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity; messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity; messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
messageEntitySpoiler#32ca960f offset:int length:int = MessageEntity; messageEntitySpoiler#32ca960f offset:int length:int = MessageEntity;
messageEntityCustomEmoji#d4a00ed5 offset:int length:int stickerset:InputStickerSet document_id:long = MessageEntity; messageEntityCustomEmoji#c8cf05f8 offset:int length:int document_id:long = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel; inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel; inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel;
@ -1696,6 +1696,7 @@ messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInl
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates; messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio; messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;
messages.rateTranscribedAudio#7f1d072f peer:InputPeer msg_id:int transcription_id:long good:Bool = Bool; messages.rateTranscribedAudio#7f1d072f peer:InputPeer msg_id:int transcription_id:long good:Bool = Bool;
messages.getCustomEmojiDocuments#d9ab0f54 document_id:Vector<long> = Vector<Document>;
updates.getState#edd4882a = updates.State; updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1800,7 +1801,7 @@ payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?t
payments.getBankCardData#2e79d779 number:string = payments.BankCardData; payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice; payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice;
payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates; payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates;
payments.assignPlayMarketTransaction#f546d3fe purchase_token:string purpose:InputStorePaymentPurpose = Updates; payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates;
payments.canPurchasePremium#aa6a90c8 = Bool; payments.canPurchasePremium#aa6a90c8 = Bool;
payments.requestRecurringPayment#146e958d user_id:InputUser recurring_init_charge:string invoice_media:InputMedia = Updates; payments.requestRecurringPayment#146e958d user_id:InputUser recurring_init_charge:string invoice_media:InputMedia = Updates;

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers_set.h" #include "data/stickers/data_stickers_set.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_user.h" #include "data/data_user.h"
namespace Api { namespace Api {
@ -24,7 +25,6 @@ using namespace TextUtilities;
return Data::SerializeCustomEmojiId({ return Data::SerializeCustomEmojiId({
.selfId = session->userId().bare, .selfId = session->userId().bare,
.id = data.vdocument_id().v, .id = data.vdocument_id().v,
.set = Data::FromInputSet(data.vstickerset()),
}); });
} }
@ -37,11 +37,14 @@ using namespace TextUtilities;
if (!parsed.id || parsed.selfId != session->userId().bare) { if (!parsed.id || parsed.selfId != session->userId().bare) {
return {}; return {};
} }
const auto document = session->data().document(parsed.id);
if (!document->sticker()) {
return {};
}
return MTP_messageEntityCustomEmoji( return MTP_messageEntityCustomEmoji(
offset, offset,
length, length,
Data::InputStickerSet(parsed.set), MTP_long(document->id));
MTP_long(parsed.id));
} }
[[nodiscard]] std::optional<MTPMessageEntity> MentionNameEntity( [[nodiscard]] std::optional<MTPMessageEntity> MentionNameEntity(

View file

@ -22,10 +22,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "ui/widgets/input_fields.h"
#include "ui/text/text_block.h"
namespace Data { namespace Data {
namespace { namespace {
constexpr auto kMaxPerRequest = 100;
using SizeTag = CustomEmojiManager::SizeTag; using SizeTag = CustomEmojiManager::SizeTag;
[[nodiscard]] ChatHelpers::StickerLottieSize LottieSizeFromTag(SizeTag tag) { [[nodiscard]] ChatHelpers::StickerLottieSize LottieSizeFromTag(SizeTag tag) {
@ -306,7 +310,7 @@ auto CustomEmojiLoader::InitialState(
const CustomEmojiId &id) const CustomEmojiId &id)
-> std::variant<Resolve, Lookup, Load> { -> std::variant<Resolve, Lookup, Load> {
const auto document = owner->document(id.id); const auto document = owner->document(id.id);
if (!document->isNull()) { if (document->sticker()) {
return Lookup{ document }; return Lookup{ document };
} }
return Resolve{ .entityData = SerializeCustomEmojiId(id) }; return Resolve{ .entityData = SerializeCustomEmojiId(id) };
@ -353,15 +357,11 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
QStringView data, QStringView data,
Fn<void()> update) { Fn<void()> update) {
const auto parsed = ParseCustomEmojiData(data); const auto parsed = ParseCustomEmojiData(data);
if (!parsed.id || !parsed.set.id) { if (!parsed.id) {
return nullptr; return nullptr;
} }
auto i = _instances.find(parsed.set.id); auto i = _instances.find(parsed.id);
if (i == end(_instances)) { if (i == end(_instances)) {
i = _instances.emplace(parsed.set.id).first;
}
auto j = i->second.find(parsed.id);
if (j == end(i->second)) {
using Loading = Ui::CustomEmoji::Loading; using Loading = Ui::CustomEmoji::Loading;
auto loader = std::make_unique<CustomEmojiLoader>( auto loader = std::make_unique<CustomEmojiLoader>(
_owner, _owner,
@ -369,76 +369,69 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
SizeTag::Normal); SizeTag::Normal);
if (loader->resolving()) { if (loader->resolving()) {
_loaders[parsed.id].push_back(base::make_weak(loader.get())); _loaders[parsed.id].push_back(base::make_weak(loader.get()));
_pendingForRequest.emplace(parsed.id);
if (!_requestId && _pendingForRequest.size() == 1) {
crl::on_main(this, [=] { request(); });
}
} }
const auto repaint = [=]( const auto repaint = [=](
not_null<Ui::CustomEmoji::Instance*> instance, not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request) { Ui::CustomEmoji::RepaintRequest request) {
repaintLater(instance, request); repaintLater(instance, request);
}; };
j = i->second.emplace( i = _instances.emplace(
parsed.id, parsed.id,
std::make_unique<Ui::CustomEmoji::Instance>(Loading{ std::make_unique<Ui::CustomEmoji::Instance>(Loading{
std::move(loader), std::move(loader),
Ui::CustomEmoji::Preview() Ui::CustomEmoji::Preview()
}, std::move(repaint))).first; }, std::move(repaint))).first;
} }
requestSetIfNeeded(parsed);
return std::make_unique<Ui::CustomEmoji::Object>( return std::make_unique<Ui::CustomEmoji::Object>(
j->second.get(), i->second.get(),
std::move(update)); std::move(update));
} }
void CustomEmojiManager::requestSetIfNeeded(const CustomEmojiId &id) { void CustomEmojiManager::request() {
const auto setId = id.set.id; auto ids = QVector<MTPlong>();
auto i = _sets.find(setId); ids.reserve(std::min(kMaxPerRequest, int(_pendingForRequest.size())));
if (i == end(_sets)) { while (!_pendingForRequest.empty() && ids.size() < kMaxPerRequest) {
i = _sets.emplace(setId).first; const auto i = _pendingForRequest.end() - 1;
ids.push_back(MTP_long(*i));
_pendingForRequest.erase(i);
} }
if (i->second.documents.contains(id.id)) { if (ids.isEmpty()) {
return;
} else if (!i->second.waiting.emplace(id.id).second
|| i->second.requestId) {
return; return;
} }
const auto api = &_owner->session().api(); const auto api = &_owner->session().api();
i->second.requestId = api->request(MTPmessages_GetStickerSet( _requestId = api->request(MTPmessages_GetCustomEmojiDocuments(
InputStickerSet(id.set), MTP_vector<MTPlong>(ids)
MTP_int(i->second.hash) )).done([=](const MTPVector<MTPDocument> &result) {
)).done([=](const MTPmessages_StickerSet &result) { for (const auto &entry : result.v) {
const auto i = _sets.find(setId); const auto document = _owner->processDocument(entry);
Assert(i != end(_sets)); const auto id = document->id;
i->second.requestId = 0; if (const auto loaders = _loaders.take(id)) {
result.match([&](const MTPDmessages_stickerSet &data) { for (const auto &weak : *loaders) {
data.vset().match([&](const MTPDstickerSet &data) { if (const auto strong = weak.get()) {
i->second.hash = data.vhash().v; strong->resolved(document);
});
for (const auto &entry : data.vdocuments().v) {
const auto document = _owner->processDocument(entry);
const auto id = document->id;
i->second.documents.emplace(id);
i->second.waiting.remove(id);
if (const auto loaders = _loaders.take(id)) {
for (const auto &weak : *loaders) {
if (const auto strong = weak.get()) {
strong->resolved(document);
}
} }
} }
} }
}, [&](const MTPDmessages_stickerSetNotModified &) {
});
for (const auto &id : base::take(i->second.waiting)) {
DEBUG_LOG(("API Error: Sticker '%1' not found for emoji.").arg(id));
} }
requestFinished();
}).fail([=] { }).fail([=] {
const auto i = _sets.find(setId); LOG(("API Error: Failed to get documents for emoji."));
Assert(i != end(_sets)); requestFinished();
i->second.requestId = 0;
LOG(("API Error: Failed getting set '%1' for emoji.").arg(setId));
}).send(); }).send();
} }
void CustomEmojiManager::requestFinished() {
_requestId = 0;
if (!_pendingForRequest.empty()) {
request();
}
}
void CustomEmojiManager::repaintLater( void CustomEmojiManager::repaintLater(
not_null<Ui::CustomEmoji::Instance*> instance, not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request) { Ui::CustomEmoji::RepaintRequest request) {
@ -506,45 +499,40 @@ Session &CustomEmojiManager::owner() const {
} }
QString SerializeCustomEmojiId(const CustomEmojiId &id) { QString SerializeCustomEmojiId(const CustomEmojiId &id) {
return QString::number(id.set.id) return QString::number(id.id)
+ '.'
+ QString::number(id.set.accessHash)
+ ':' + ':'
+ QString::number(id.selfId) + QString::number(id.selfId);
+ '/'
+ QString::number(id.id);
} }
QString SerializeCustomEmojiId(not_null<DocumentData*> document) { QString SerializeCustomEmojiId(not_null<DocumentData*> document) {
const auto sticker = document->sticker();
return SerializeCustomEmojiId({ return SerializeCustomEmojiId({
.selfId = document->session().userId().bare, .selfId = document->session().userId().bare,
.id = document->id, .id = document->id,
.set = sticker ? sticker->set : StickerSetIdentifier(),
}); });
} }
CustomEmojiId ParseCustomEmojiData(QStringView data) { CustomEmojiId ParseCustomEmojiData(QStringView data) {
const auto components = data.split('.'); const auto components = data.split(':');
if (components.size() != 2) { if (components.size() != 2) {
return {}; return {};
} }
const auto parts = components[1].split(':');
if (parts.size() != 2) {
return {};
}
const auto endings = parts[1].split('/');
if (endings.size() != 2) {
return {};
}
return { return {
.selfId = endings[0].toULongLong(), .selfId = components[1].toULongLong(),
.id = endings[1].toULongLong(), .id = components[0].toULongLong(),
.set = {
.id = components[0].toULongLong(),
.accessHash = parts[0].toULongLong(),
},
}; };
} }
void InsertCustomEmoji(
not_null<Ui::InputField*> field,
not_null<DocumentData*> document) {
const auto sticker = document->sticker();
if (!sticker || sticker->alt.isEmpty()) {
return;
}
Ui::InsertCustomEmojiAtCursor(
field->textCursor(),
sticker->alt,
Ui::InputField::CustomEmojiLink(SerializeCustomEmojiId(document)));
}
} // namespace Data } // namespace Data

View file

@ -26,7 +26,6 @@ class CustomEmojiLoader;
struct CustomEmojiId { struct CustomEmojiId {
uint64 selfId = 0; uint64 selfId = 0;
uint64 id = 0; uint64 id = 0;
StickerSetIdentifier set;
}; };
class CustomEmojiManager final : public base::has_weak_ptr { class CustomEmojiManager final : public base::has_weak_ptr {
@ -47,18 +46,13 @@ public:
[[nodiscard]] Session &owner() const; [[nodiscard]] Session &owner() const;
private: private:
struct Set {
int32 hash = 0;
mtpRequestId requestId = 0;
base::flat_set<uint64> documents;
base::flat_set<uint64> waiting;
};
struct RepaintBunch { struct RepaintBunch {
crl::time when = 0; crl::time when = 0;
std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances; std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
}; };
void requestSetIfNeeded(const CustomEmojiId &id); void request();
void requestFinished();
void repaintLater( void repaintLater(
not_null<Ui::CustomEmoji::Instance*> instance, not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request); Ui::CustomEmoji::RepaintRequest request);
@ -67,13 +61,14 @@ private:
const not_null<Session*> _owner; const not_null<Session*> _owner;
base::flat_map<uint64, base::flat_map< base::flat_map<
uint64, uint64,
std::unique_ptr<Ui::CustomEmoji::Instance>>> _instances; std::unique_ptr<Ui::CustomEmoji::Instance>> _instances;
base::flat_map<uint64, Set> _sets;
base::flat_map< base::flat_map<
uint64, uint64,
std::vector<base::weak_ptr<CustomEmojiLoader>>> _loaders; std::vector<base::weak_ptr<CustomEmojiLoader>>> _loaders;
base::flat_set<uint64> _pendingForRequest;
mtpRequestId _requestId = 0;
base::flat_map<crl::time, RepaintBunch> _repaints; base::flat_map<crl::time, RepaintBunch> _repaints;
crl::time _repaintNext = 0; crl::time _repaintNext = 0;
@ -87,4 +82,8 @@ private:
not_null<DocumentData*> document); not_null<DocumentData*> document);
[[nodiscard]] CustomEmojiId ParseCustomEmojiData(QStringView data); [[nodiscard]] CustomEmojiId ParseCustomEmojiData(QStringView data);
void InsertCustomEmoji(
not_null<Ui::InputField*> field,
not_null<DocumentData*> document);
} // namespace Data } // namespace Data

@ -1 +1 @@
Subproject commit 464c6a61711fa7b66d45829bde582d36e23f0b1a Subproject commit 9cb7bb58f658d7603f9493b9d051cf8a78a2cd41