Update API scheme on layer 161.

This commit is contained in:
John Preston 2023-08-04 16:49:58 +02:00
parent 6be1a05876
commit 318d75cc63
8 changed files with 100 additions and 146 deletions

View File

@ -862,7 +862,8 @@ void Stories::activateStealthMode(Fn<void()> done) {
using Flag = MTPstories_ActivateStealthMode::Flag; using Flag = MTPstories_ActivateStealthMode::Flag;
api->request(MTPstories_ActivateStealthMode( api->request(MTPstories_ActivateStealthMode(
MTP_flags(Flag::f_past | Flag::f_future) MTP_flags(Flag::f_past | Flag::f_future)
)).done([=](const MTPBool &result) { )).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
if (done) done(); if (done) done();
}).fail([=] { }).fail([=] {
if (done) done(); if (done) done();
@ -1233,11 +1234,11 @@ void Stories::sendIncrementViewsRequests() {
void Stories::loadViewsSlice( void Stories::loadViewsSlice(
StoryId id, StoryId id,
std::optional<StoryView> offset, QString offset,
Fn<void(std::vector<StoryView>)> done) { Fn<void(StoryViews)> done) {
if (_viewsStoryId == id if (_viewsStoryId == id
&& _viewsOffset == offset && _viewsOffset == offset
&& (offset || _viewsRequestId)) { && (!offset.isEmpty() || _viewsRequestId)) {
if (_viewsRequestId) { if (_viewsRequestId) {
_viewsDone = std::move(done); _viewsDone = std::move(done);
} }
@ -1251,21 +1252,27 @@ void Stories::loadViewsSlice(
const auto perPage = _viewsDone ? kViewsPerPage : kPollingViewsPerPage; const auto perPage = _viewsDone ? kViewsPerPage : kPollingViewsPerPage;
api->request(_viewsRequestId).cancel(); api->request(_viewsRequestId).cancel();
_viewsRequestId = api->request(MTPstories_GetStoryViewsList( _viewsRequestId = api->request(MTPstories_GetStoryViewsList(
MTP_flags(0),
MTPstring(), // q
MTP_int(id), MTP_int(id),
MTP_int(offset ? offset->date : 0), MTP_string(offset),
MTP_long(offset ? peerToUser(offset->peer->id).bare : 0),
MTP_int(perPage) MTP_int(perPage)
)).done([=](const MTPstories_StoryViewsList &result) { )).done([=](const MTPstories_StoryViewsList &result) {
_viewsRequestId = 0; _viewsRequestId = 0;
auto slice = std::vector<StoryView>();
const auto &data = result.data(); const auto &data = result.data();
auto slice = StoryViews{
.nextOffset = data.vnext_offset().value_or_empty(),
.total = data.vcount().v,
};
_owner->processUsers(data.vusers()); _owner->processUsers(data.vusers());
slice.reserve(data.vviews().v.size()); slice.list.reserve(data.vviews().v.size());
for (const auto &view : data.vviews().v) { for (const auto &view : data.vviews().v) {
slice.push_back({ slice.list.push_back({
.peer = _owner->peer(peerFromUser(view.data().vuser_id())), .peer = _owner->peer(peerFromUser(view.data().vuser_id())),
.reaction = (view.data().vreaction()
? ReactionFromMTP(*view.data().vreaction())
: Data::ReactionId()),
.date = view.data().vdate().v, .date = view.data().vdate().v,
}); });
} }
@ -1274,7 +1281,7 @@ void Stories::loadViewsSlice(
.story = _viewsStoryId, .story = _viewsStoryId,
}; };
if (const auto story = lookup(fullId)) { if (const auto story = lookup(fullId)) {
(*story)->applyViewsSlice(_viewsOffset, slice, data.vcount().v); (*story)->applyViewsSlice(_viewsOffset, slice);
} }
if (const auto done = base::take(_viewsDone)) { if (const auto done = base::take(_viewsDone)) {
done(std::move(slice)); done(std::move(slice));
@ -1713,7 +1720,7 @@ void Stories::sendPollingViewsRequests() {
return; return;
} else if (!_viewsRequestId) { } else if (!_viewsRequestId) {
Assert(_viewsDone == nullptr); Assert(_viewsDone == nullptr);
loadViewsSlice(_pollingViews.front()->id(), std::nullopt, nullptr); loadViewsSlice(_pollingViews.front()->id(), QString(), nullptr);
} }
_pollingViewsTimer.callOnce(kPollViewsInterval); _pollingViewsTimer.callOnce(kPollViewsInterval);
} }

View File

@ -179,8 +179,8 @@ public:
static constexpr auto kViewsPerPage = 50; static constexpr auto kViewsPerPage = 50;
void loadViewsSlice( void loadViewsSlice(
StoryId id, StoryId id,
std::optional<StoryView> offset, QString offset,
Fn<void(std::vector<StoryView>)> done); Fn<void(StoryViews)> done);
[[nodiscard]] const StoriesIds &archive() const; [[nodiscard]] const StoriesIds &archive() const;
[[nodiscard]] rpl::producer<> archiveChanged() const; [[nodiscard]] rpl::producer<> archiveChanged() const;
@ -366,8 +366,8 @@ private:
base::flat_set<PeerId> _incrementViewsRequests; base::flat_set<PeerId> _incrementViewsRequests;
StoryId _viewsStoryId = 0; StoryId _viewsStoryId = 0;
std::optional<StoryView> _viewsOffset; QString _viewsOffset;
Fn<void(std::vector<StoryView>)> _viewsDone; Fn<void(StoryViews)> _viewsDone;
mtpRequestId _viewsRequestId = 0; mtpRequestId _viewsRequestId = 0;
base::flat_set<FullStoryId> _preloaded; base::flat_set<FullStoryId> _preloaded;

View File

@ -339,51 +339,35 @@ const std::vector<not_null<PeerData*>> &Story::recentViewers() const {
return _recentViewers; return _recentViewers;
} }
const std::vector<StoryView> &Story::viewsList() const { const StoryViews &Story::viewsList() const {
return _viewsList;
}
int Story::views() const {
return _views; return _views;
} }
int Story::views() const {
return _views.total;
}
void Story::applyViewsSlice( void Story::applyViewsSlice(
const std::optional<StoryView> &offset, const QString &offset,
const std::vector<StoryView> &slice, const StoryViews &slice) {
int total) { const auto changed = (_views.total != slice.total);
const auto changed = (_views != total); _views.total = slice.total;
_views = total; if (offset.isEmpty()) {
if (!offset) { _views = slice;
const auto i = _viewsList.empty() } else if (_views.nextOffset == offset) {
? end(slice) _views.list.insert(
: ranges::find(slice, _viewsList.front()); end(_views.list),
const auto merge = (i != end(slice)) begin(slice.list),
&& !ranges::contains(slice, _viewsList.back()); end(slice.list));
if (merge) { _views.nextOffset = slice.nextOffset;
_viewsList.insert(begin(_viewsList), begin(slice), i); if (_views.nextOffset.isEmpty()) {
} else { _views.total = int(_views.list.size());
_viewsList = slice;
}
} else if (!slice.empty()) {
const auto i = ranges::find(_viewsList, *offset);
const auto merge = (i != end(_viewsList))
&& !ranges::contains(_viewsList, slice.back());
if (merge) {
const auto after = i + 1;
if (after == end(_viewsList)) {
_viewsList.insert(after, begin(slice), end(slice));
} else {
const auto j = ranges::find(slice, _viewsList.back());
if (j != end(slice)) {
_viewsList.insert(end(_viewsList), j + 1, end(slice));
}
}
} }
} }
const auto known = int(_viewsList.size()); const auto known = int(_views.list.size());
if (known >= _recentViewers.size()) { if (known >= _recentViewers.size()) {
const auto take = std::min(known, kRecentViewersMax); const auto take = std::min(known, kRecentViewersMax);
auto viewers = _viewsList auto viewers = _views.list
| ranges::views::take(take) | ranges::views::take(take)
| ranges::views::transform(&StoryView::peer) | ranges::views::transform(&StoryView::peer)
| ranges::to_vector; | ranges::to_vector;
@ -436,7 +420,7 @@ void Story::applyFields(
&owner().session(), &owner().session(),
data.ventities().value_or_empty()), data.ventities().value_or_empty()),
}; };
auto views = _views; auto views = _views.total;
auto viewers = std::vector<not_null<PeerData*>>(); auto viewers = std::vector<not_null<PeerData*>>();
if (!data.is_min()) { if (!data.is_min()) {
if (const auto info = data.vviews()) { if (const auto info = data.vviews()) {
@ -457,7 +441,7 @@ void Story::applyFields(
const auto editedChanged = (_edited != edited); const auto editedChanged = (_edited != edited);
const auto mediaChanged = (_media != media); const auto mediaChanged = (_media != media);
const auto captionChanged = (_caption != caption); const auto captionChanged = (_caption != caption);
const auto viewsChanged = (_views != views) const auto viewsChanged = (_views.total != views)
|| (_recentViewers != viewers); || (_recentViewers != viewers);
_privacyPublic = (privacy == StoryPrivacy::Public); _privacyPublic = (privacy == StoryPrivacy::Public);
@ -468,8 +452,10 @@ void Story::applyFields(
_edited = edited; _edited = edited;
_pinned = pinned; _pinned = pinned;
_noForwards = noForwards; _noForwards = noForwards;
if (_views.total != views) {
_views = StoryViews{ .total = views };
}
if (viewsChanged) { if (viewsChanged) {
_views = views;
_recentViewers = std::move(viewers); _recentViewers = std::move(viewers);
} }
if (mediaChanged) { if (mediaChanged) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "data/data_message_reaction_id.h"
class Image; class Image;
class PhotoData; class PhotoData;
@ -58,11 +59,18 @@ struct StoryMedia {
struct StoryView { struct StoryView {
not_null<PeerData*> peer; not_null<PeerData*> peer;
Data::ReactionId reaction;
TimeId date = 0; TimeId date = 0;
friend inline bool operator==(StoryView, StoryView) = default; friend inline bool operator==(StoryView, StoryView) = default;
}; };
struct StoryViews {
std::vector<StoryView> list;
QString nextOffset;
int total = 0;
};
class Story final { class Story final {
public: public:
Story( Story(
@ -115,12 +123,9 @@ public:
[[nodiscard]] auto recentViewers() const [[nodiscard]] auto recentViewers() const
-> const std::vector<not_null<PeerData*>> &; -> const std::vector<not_null<PeerData*>> &;
[[nodiscard]] const std::vector<StoryView> &viewsList() const; [[nodiscard]] const StoryViews &viewsList() const;
[[nodiscard]] int views() const; [[nodiscard]] int views() const;
void applyViewsSlice( void applyViewsSlice(const QString &offset, const StoryViews &slice);
const std::optional<StoryView> &offset,
const std::vector<StoryView> &slice,
int total);
void applyChanges( void applyChanges(
StoryMedia media, StoryMedia media,
@ -140,8 +145,7 @@ private:
StoryMedia _media; StoryMedia _media;
TextWithEntities _caption; TextWithEntities _caption;
std::vector<not_null<PeerData*>> _recentViewers; std::vector<not_null<PeerData*>> _recentViewers;
std::vector<StoryView> _viewsList; StoryViews _views;
int _views = 0;
const TimeId _date = 0; const TimeId _date = 0;
const TimeId _expires = 0; const TimeId _expires = 0;
TimeId _lastUpdateTime = 0; TimeId _lastUpdateTime = 0;

View File

@ -1254,12 +1254,17 @@ SiblingView Controller::sibling(SiblingType type) const {
return {}; return {};
} }
ViewsSlice Controller::views(PeerId offset) { const Data::StoryViews &Controller::views(int limit, bool initial) {
invalidate_weak_ptrs(&_viewsLoadGuard); invalidate_weak_ptrs(&_viewsLoadGuard);
if (!offset) { if (initial) {
refreshViewsFromData(); refreshViewsFromData();
} else if (!sliceViewsTo(offset)) { }
return { .left = _viewsSlice.left }; if (_viewsSlice.total > _viewsSlice.list.size()
&& _viewsSlice.list.size() < limit) {
const auto done = viewsGotMoreCallback();
const auto user = shownUser();
auto &stories = user->owner().stories();
stories.loadViewsSlice(_shown.story, _viewsSlice.nextOffset, done);
} }
return _viewsSlice; return _viewsSlice;
} }
@ -1268,27 +1273,25 @@ rpl::producer<> Controller::moreViewsLoaded() const {
return _moreViewsLoaded.events(); return _moreViewsLoaded.events();
} }
Fn<void(std::vector<Data::StoryView>)> Controller::viewsGotMoreCallback() { Fn<void(Data::StoryViews)> Controller::viewsGotMoreCallback() {
return crl::guard(&_viewsLoadGuard, [=]( return crl::guard(&_viewsLoadGuard, [=](Data::StoryViews result) {
const std::vector<Data::StoryView> &result) {
if (_viewsSlice.list.empty()) { if (_viewsSlice.list.empty()) {
const auto user = shownUser(); const auto user = shownUser();
auto &stories = user->owner().stories(); auto &stories = user->owner().stories();
if (const auto maybeStory = stories.lookup(_shown)) { if (const auto maybeStory = stories.lookup(_shown)) {
_viewsSlice = { _viewsSlice = (*maybeStory)->viewsList();
.list = result,
.left = (*maybeStory)->views() - int(result.size()),
};
} else { } else {
_viewsSlice = {}; _viewsSlice = {};
} }
} else { } else {
_viewsSlice.list.insert( _viewsSlice.list.insert(
end(_viewsSlice.list), end(_viewsSlice.list),
begin(result), begin(result.list),
end(result)); end(result.list));
_viewsSlice.left _viewsSlice.total = result.nextOffset.isEmpty()
= std::max(_viewsSlice.left - int(result.size()), 0); ? int(_viewsSlice.list.size())
: std::max(result.total, int(_viewsSlice.list.size()));
_viewsSlice.nextOffset = result.nextOffset;
} }
_moreViewsLoaded.fire({}); _moreViewsLoaded.fire({});
}); });
@ -1439,46 +1442,9 @@ void Controller::refreshViewsFromData() {
return; return;
} }
const auto story = *maybeStory; const auto story = *maybeStory;
const auto &list = story->viewsList(); const auto &views = story->viewsList();
const auto total = story->views(); const auto total = story->views();
_viewsSlice.list = list _viewsSlice = story->viewsList();
| ranges::views::take(Data::Stories::kViewsPerPage)
| ranges::to_vector;
_viewsSlice.left = total - int(_viewsSlice.list.size());
if (_viewsSlice.list.empty() && _viewsSlice.left > 0) {
const auto done = viewsGotMoreCallback();
stories.loadViewsSlice(_shown.story, std::nullopt, done);
}
}
bool Controller::sliceViewsTo(PeerId offset) {
Expects(shown());
const auto user = shownUser();
auto &stories = user->owner().stories();
const auto maybeStory = stories.lookup(_shown);
if (!maybeStory || !user->isSelf()) {
_viewsSlice = {};
return true;
}
const auto story = *maybeStory;
const auto &list = story->viewsList();
const auto proj = [&](const Data::StoryView &single) {
return single.peer->id;
};
const auto i = ranges::find(list, _viewsSlice.list.back());
const auto add = (i != end(list)) ? int(end(list) - i - 1) : 0;
const auto j = ranges::find(_viewsSlice.list, offset, proj);
Assert(j != end(_viewsSlice.list));
if (!add && (j + 1) == end(_viewsSlice.list)) {
const auto done = viewsGotMoreCallback();
stories.loadViewsSlice(_shown.story, _viewsSlice.list.back(), done);
return false;
}
_viewsSlice.list.erase(begin(_viewsSlice.list), j + 1);
_viewsSlice.list.insert(end(_viewsSlice.list), i + 1, end(list));
_viewsSlice.left -= add;
return true;
} }
void Controller::unfocusReply() { void Controller::unfocusReply() {

View File

@ -104,11 +104,6 @@ struct Layout {
friend inline bool operator==(Layout, Layout) = default; friend inline bool operator==(Layout, Layout) = default;
}; };
struct ViewsSlice {
std::vector<Data::StoryView> list;
int left = 0;
};
class Controller final : public base::has_weak_ptr { class Controller final : public base::has_weak_ptr {
public: public:
explicit Controller(not_null<Delegate*> delegate); explicit Controller(not_null<Delegate*> delegate);
@ -158,7 +153,7 @@ public:
void repaintSibling(not_null<Sibling*> sibling); void repaintSibling(not_null<Sibling*> sibling);
[[nodiscard]] SiblingView sibling(SiblingType type) const; [[nodiscard]] SiblingView sibling(SiblingType type) const;
[[nodiscard]] ViewsSlice views(PeerId offset); [[nodiscard]] const Data::StoryViews &views(int limit, bool initial);
[[nodiscard]] rpl::producer<> moreViewsLoaded() const; [[nodiscard]] rpl::producer<> moreViewsLoaded() const;
void unfocusReply(); void unfocusReply();
@ -221,9 +216,8 @@ private:
void moveFromShown(); void moveFromShown();
void refreshViewsFromData(); void refreshViewsFromData();
bool sliceViewsTo(PeerId offset);
[[nodiscard]] auto viewsGotMoreCallback() [[nodiscard]] auto viewsGotMoreCallback()
-> Fn<void(std::vector<Data::StoryView>)>; -> Fn<void(Data::StoryViews)>;
[[nodiscard]] bool shown() const; [[nodiscard]] bool shown() const;
[[nodiscard]] UserData *shownUser() const; [[nodiscard]] UserData *shownUser() const;
@ -285,7 +279,7 @@ private:
int _cachedSourceIndex = -1; int _cachedSourceIndex = -1;
bool _showingUnreadSources = false; bool _showingUnreadSources = false;
ViewsSlice _viewsSlice; Data::StoryViews _viewsSlice;
rpl::event_stream<> _moreViewsLoaded; rpl::event_stream<> _moreViewsLoaded;
base::has_weak_ptr _viewsLoadGuard; base::has_weak_ptr _viewsLoadGuard;

View File

@ -264,8 +264,8 @@ void RecentViews::showMenu() {
return; return;
} }
const auto views = _controller->views(PeerId()); const auto views = _controller->views(kAddPerPage * 2, true);
if (views.list.empty() && !views.left) { if (views.list.empty() && !views.total) {
return; return;
} }
@ -276,7 +276,7 @@ void RecentViews::showMenu() {
st::storiesViewsMenu); st::storiesViewsMenu);
auto count = 0; auto count = 0;
const auto added = std::min(int(views.list.size()), kAddPerPage); const auto added = std::min(int(views.list.size()), kAddPerPage);
const auto add = std::min(added + views.left, kAddPerPage); const auto add = std::min(views.total, kAddPerPage);
const auto now = QDateTime::currentDateTime(); const auto now = QDateTime::currentDateTime();
for (const auto &entry : views.list) { for (const auto &entry : views.list) {
addMenuRow(entry, now); addMenuRow(entry, now);
@ -393,23 +393,18 @@ void RecentViews::addMenuRowPlaceholder() {
} }
void RecentViews::rebuildMenuTail() { void RecentViews::rebuildMenuTail() {
const auto offset = (_menuPlaceholderCount < _menuEntries.size()) const auto elements = _menuEntries.size() - _menuPlaceholderCount;
? (end(_menuEntries) - _menuPlaceholderCount - 1)->peer->id const auto views = _controller->views(elements + kAddPerPage, false);
: PeerId(); if (views.list.size() <= elements) {
const auto views = _controller->views(offset);
if (views.list.empty()) {
return; return;
} }
const auto now = QDateTime::currentDateTime(); const auto now = QDateTime::currentDateTime();
const auto added = std::min( const auto added = std::min(
_menuPlaceholderCount + kAddPerPage, _menuPlaceholderCount + kAddPerPage,
int(views.list.size())); int(views.list.size() - elements));
auto add = added; for (auto i = elements, till = i + added; i != till; ++i) {
for (const auto &entry : views.list) { const auto &entry = views.list[i];
addMenuRow(entry, now); addMenuRow(entry, now);
if (!--add) {
break;
}
} }
_menuEntriesCount = _menuEntriesCount.current() + added; _menuEntriesCount = _menuEntriesCount.current() + added;
} }

View File

@ -386,6 +386,7 @@ updateStory#205a4133 user_id:long story:StoryItem = Update;
updateReadStories#feb5345a user_id:long max_id:int = Update; updateReadStories#feb5345a user_id:long max_id:int = Update;
updateStoryID#1bf335b9 id:int random_id:long = Update; updateStoryID#1bf335b9 id:int random_id:long = Update;
updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = Update; updateStoriesStealthMode#2c084dc1 stealth_mode:StoriesStealthMode = Update;
updateSentStoryReaction#e3a73d20 user_id:long story_id:int reaction:Reaction = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -1527,11 +1528,11 @@ messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector<bytes> date:int = Mess
sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage; sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage;
storyViews#d36760cf flags:# views_count:int recent_viewers:flags.0?Vector<long> = StoryViews; storyViews#c64c0b97 flags:# views_count:int reactions_count:int recent_viewers:flags.0?Vector<long> = StoryViews;
storyItemDeleted#51e6ee4f id:int = StoryItem; storyItemDeleted#51e6ee4f id:int = StoryItem;
storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem; storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem;
storyItem#945953ba flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews = StoryItem; storyItem#44c457ce flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true id:int date:int expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories; userStories#8611a200 flags:# user_id:long max_read_id:flags.0?int stories:Vector<StoryItem> = UserStories;
@ -1542,9 +1543,9 @@ stories.stories#4fe57df1 count:int stories:Vector<StoryItem> users:Vector<User>
stories.userStories#37a6ff5f stories:UserStories users:Vector<User> = stories.UserStories; stories.userStories#37a6ff5f stories:UserStories users:Vector<User> = stories.UserStories;
storyView#d0b0a7de flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int = StoryView; storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
stories.storyViewsList#fb3f77ac count:int views:Vector<StoryView> users:Vector<User> = stories.StoryViewsList; stories.storyViewsList#46e9b9ec flags:# count:int reactions_count:int views:Vector<StoryView> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews; stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
@ -2111,8 +2112,9 @@ stories.toggleAllStoriesHidden#7c2557c4 hidden:Bool = Bool;
stories.getAllReadUserStories#729c562c = Updates; stories.getAllReadUserStories#729c562c = Updates;
stories.readStories#edc5105b user_id:InputUser max_id:int = Vector<int>; stories.readStories#edc5105b user_id:InputUser max_id:int = Vector<int>;
stories.incrementStoryViews#22126127 user_id:InputUser id:Vector<int> = Bool; stories.incrementStoryViews#22126127 user_id:InputUser id:Vector<int> = Bool;
stories.getStoryViewsList#4b3b5e97 id:int offset_date:int offset_id:long limit:int = stories.StoryViewsList; stories.getStoryViewsList#f95f61a4 flags:# just_contacts:flags.0?true q:flags.1?string id:int offset:string limit:int = stories.StoryViewsList;
stories.getStoriesViews#9a75d6a6 id:Vector<int> = stories.StoryViews; stories.getStoriesViews#9a75d6a6 id:Vector<int> = stories.StoryViews;
stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink; stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink;
stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool; stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool;
stories.activateStealthMode#11d7ddae flags:# past:flags.0?true future:flags.1?true = Bool; stories.activateStealthMode#57bbd166 flags:# past:flags.0?true future:flags.1?true = Updates;
stories.sendReaction#49aaa9b3 flags:# add_to_recent:flags.0?true user_id:InputUser story_id:int reaction:Reaction = Updates;