2015-03-19 12:18:19 +03:00
/*
This file is part of Telegram Desktop ,
the official desktop version of Telegram messaging app , see https : //telegram.org
Telegram Desktop is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
It is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2015-10-03 16:16:42 +03:00
In addition , as a special exception , the copyright holders give permission
to link the code of portions of this program with the OpenSSL library .
2015-03-19 12:18:19 +03:00
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2017-01-11 22:31:31 +04:00
Copyright ( c ) 2014 - 2017 John Preston , https : //desktop.telegram.org
2015-03-19 12:18:19 +03:00
*/
2016-04-21 20:57:29 +03:00
# include "apiwrap.h"
2015-03-19 12:18:19 +03:00
2016-06-09 17:31:10 +03:00
# include "data/data_drafts.h"
2016-05-25 15:09:05 +03:00
# include "observer_peer.h"
2017-04-13 11:27:10 +03:00
# include "lang/lang_keys.h"
2015-03-19 12:18:19 +03:00
# include "application.h"
2016-04-13 00:31:28 +03:00
# include "mainwindow.h"
2017-04-29 23:06:32 +03:00
# include "messenger.h"
2015-03-19 12:18:19 +03:00
# include "mainwidget.h"
2017-06-29 13:27:09 +03:00
# include "history/history_widget.h"
2017-03-04 13:23:56 +03:00
# include "storage/localstorage.h"
2017-02-23 12:32:28 +03:00
# include "auth_session.h"
2017-04-06 17:38:10 +03:00
# include "boxes/confirm_box.h"
2017-02-03 23:07:26 +03:00
# include "window/themes/window_theme.h"
2017-03-04 22:36:59 +03:00
# include "window/notifications_manager.h"
2017-04-08 16:27:53 +03:00
# include "chat_helpers/message_field.h"
2015-03-19 12:18:19 +03:00
2017-04-06 19:49:42 +03:00
namespace {
constexpr auto kReloadChannelMembersTimeout = 1000 ; // 1 second wait before reload members in channel after adding
2017-04-07 15:10:10 +03:00
constexpr auto kSaveCloudDraftTimeout = 1000 ; // save draft to the cloud with 1 sec extra delay
2017-04-11 18:44:11 +03:00
constexpr auto kSaveDraftBeforeQuitTimeout = 1500 ; // give the app 1.5 secs to save drafts to cloud when quitting
2017-04-06 22:02:40 +03:00
constexpr auto kSmallDelayMs = 5 ;
2017-04-06 19:49:42 +03:00
} // namespace
2017-06-05 16:33:45 +03:00
ApiWrap : : ApiWrap ( gsl : : not_null < AuthSession * > session )
: _session ( session )
, _messageDataResolveDelayed ( [ this ] { resolveMessageDatas ( ) ; } )
2017-04-07 15:10:10 +03:00
, _webPagesTimer ( [ this ] { resolveWebPages ( ) ; } )
2017-04-29 23:06:32 +03:00
, _draftsSaveTimer ( [ this ] { saveDraftsToCloud ( ) ; } ) {
2017-06-05 16:33:45 +03:00
}
void ApiWrap : : start ( ) {
2016-11-04 22:50:35 +03:00
Window : : Theme : : Background ( ) - > start ( ) ;
2017-06-30 13:32:10 +03:00
requestAppChangelogs ( ) ;
}
void ApiWrap : : requestAppChangelogs ( ) {
auto oldAppVersion = Local : : oldMapVersion ( ) ;
if ( oldAppVersion > 0 & & oldAppVersion < AppVersion ) {
_changelogSubscription = subscribe ( _session - > data ( ) . moreChatsLoaded ( ) , [ this , oldAppVersion ] {
auto oldVersionString = qsl ( " %1.%2.%3 " ) . arg ( oldAppVersion / 1000000 ) . arg ( ( oldAppVersion % 1000000 ) / 1000 ) . arg ( oldAppVersion % 1000 ) ;
request ( MTPhelp_GetAppChangelog ( MTP_string ( oldVersionString ) ) ) . done ( [ this , oldAppVersion ] ( const MTPUpdates & result ) {
2017-06-05 16:33:45 +03:00
applyUpdates ( result ) ;
2017-06-30 09:23:31 +03:00
2017-06-30 13:32:10 +03:00
auto resultEmpty = true ;
switch ( result . type ( ) ) {
case mtpc_updateShortMessage :
case mtpc_updateShortChatMessage :
case mtpc_updateShort : resultEmpty = false ; break ;
case mtpc_updatesCombined : resultEmpty = result . c_updatesCombined ( ) . vupdates . v . isEmpty ( ) ; break ;
case mtpc_updates : resultEmpty = result . c_updates ( ) . vupdates . v . isEmpty ( ) ; break ;
case mtpc_updatesTooLong :
case mtpc_updateShortSentMessage : LOG ( ( " API Error: Bad updates type in app changelog. " ) ) ; break ;
}
2017-07-04 18:30:46 +03:00
if ( resultEmpty ) {
addLocalChangelogs ( oldAppVersion ) ;
2017-06-30 09:23:31 +03:00
}
2017-06-05 16:33:45 +03:00
} ) . send ( ) ;
unsubscribe ( base : : take ( _changelogSubscription ) ) ;
} ) ;
}
2015-03-19 12:18:19 +03:00
}
2017-07-04 18:30:46 +03:00
void ApiWrap : : addLocalChangelogs ( int oldAppVersion ) {
auto addedSome = false ;
auto addLocalChangelog = [ this , & addedSome ] ( const QString & text ) {
auto textWithEntities = TextWithEntities { text } ;
textParseEntities ( textWithEntities . text , TextParseLinks , & textWithEntities . entities ) ;
App : : wnd ( ) - > serviceNotification ( textWithEntities , MTP_messageMediaEmpty ( ) , unixtime ( ) ) ;
addedSome = true ;
2017-06-30 13:32:10 +03:00
} ;
2017-07-04 18:30:46 +03:00
if ( cAlphaVersion ( ) | | cBetaVersion ( ) ) {
auto addLocalAlphaChangelog = [ this , oldAppVersion , addLocalChangelog ] ( int changeVersion , const char * changes ) {
if ( oldAppVersion < changeVersion ) {
auto changeVersionString = QString : : number ( changeVersion / 1000000 ) + ' . ' + QString : : number ( ( changeVersion % 1000000 ) / 1000 ) + ( ( changeVersion % 1000 ) ? ( ' . ' + QString : : number ( changeVersion % 1000 ) ) : QString ( ) ) ;
auto text = qsl ( " New in version %1: \n \n " ) . arg ( changeVersionString ) + QString : : fromUtf8 ( changes ) . trimmed ( ) ;
addLocalChangelog ( text ) ;
}
} ;
addLocalAlphaChangelog ( 1001008 , " \xE2 \x80 \x94 Toggle night mode in the main menu. \n " ) ;
addLocalAlphaChangelog ( 1001010 , " \xE2 \x80 \x94 Filter added to channel and supergroup event log. \n \xE2 \x80 \x94 Search by username in privacy exceptions editor fixed. \n \xE2 \x80 \x94 Adding admins in channels fixed. " ) ;
}
if ( ! addedSome ) {
auto text = lng_new_version_wrap ( lt_version , str_const_toString ( AppVersionStr ) , lt_changes , lang ( lng_new_version_minor ) , lt_link , qsl ( " https://desktop.telegram.org/changelog " ) ) . trimmed ( ) ;
addLocalChangelog ( text ) ;
}
2017-06-30 13:32:10 +03:00
}
2017-04-13 20:59:05 +03:00
void ApiWrap : : applyUpdates ( const MTPUpdates & updates , uint64 sentMessageRandomId ) {
App : : main ( ) - > feedUpdates ( updates , sentMessageRandomId ) ;
}
2017-02-26 14:32:13 +03:00
void ApiWrap : : requestMessageData ( ChannelData * channel , MsgId msgId , RequestMessageDataCallback callback ) {
2017-04-06 19:49:42 +03:00
auto & req = ( channel ? _channelMessageDataRequests [ channel ] [ msgId ] : _messageDataRequests [ msgId ] ) ;
2016-05-09 13:07:25 +03:00
if ( callback ) {
2016-11-20 15:54:07 +03:00
req . callbacks . append ( callback ) ;
2016-05-09 13:07:25 +03:00
}
2017-04-06 22:02:40 +03:00
if ( ! req . requestId ) _messageDataResolveDelayed . call ( ) ;
2015-03-19 12:18:19 +03:00
}
2017-04-06 22:02:40 +03:00
QVector < MTPint > ApiWrap : : collectMessageIds ( const MessageDataRequests & requests ) {
auto result = QVector < MTPint > ( ) ;
2015-09-12 14:59:50 +03:00
result . reserve ( requests . size ( ) ) ;
2016-05-09 13:07:25 +03:00
for ( auto i = requests . cbegin ( ) , e = requests . cend ( ) ; i ! = e ; + + i ) {
2017-04-06 22:02:40 +03:00
if ( i . value ( ) . requestId > 0 ) continue ;
2015-09-12 14:59:50 +03:00
result . push_back ( MTP_int ( i . key ( ) ) ) ;
}
return result ;
}
2015-06-28 15:37:10 +03:00
2016-03-10 13:15:21 +03:00
ApiWrap : : MessageDataRequests * ApiWrap : : messageDataRequests ( ChannelData * channel , bool onlyExisting ) {
2015-09-12 14:59:50 +03:00
if ( channel ) {
2016-05-09 13:07:25 +03:00
auto i = _channelMessageDataRequests . find ( channel ) ;
2016-03-10 13:15:21 +03:00
if ( i = = _channelMessageDataRequests . cend ( ) ) {
2015-09-12 14:59:50 +03:00
if ( onlyExisting ) return 0 ;
2016-03-10 13:15:21 +03:00
i = _channelMessageDataRequests . insert ( channel , MessageDataRequests ( ) ) ;
2015-06-28 15:37:10 +03:00
}
2015-09-12 14:59:50 +03:00
return & i . value ( ) ;
2015-06-28 15:37:10 +03:00
}
2016-03-10 13:15:21 +03:00
return & _messageDataRequests ;
2015-09-12 14:59:50 +03:00
}
2016-03-10 13:15:21 +03:00
void ApiWrap : : resolveMessageDatas ( ) {
if ( _messageDataRequests . isEmpty ( ) & & _channelMessageDataRequests . isEmpty ( ) ) return ;
2015-09-12 14:59:50 +03:00
2017-04-06 22:02:40 +03:00
auto ids = collectMessageIds ( _messageDataRequests ) ;
2015-06-28 15:37:10 +03:00
if ( ! ids . isEmpty ( ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPmessages_GetMessages ( MTP_vector < MTPint > ( ids ) ) ) . done ( [ this ] ( const MTPmessages_Messages & result , mtpRequestId requestId ) {
gotMessageDatas ( nullptr , result , requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
2016-05-09 13:07:25 +03:00
for ( auto & request : _messageDataRequests ) {
2017-04-06 22:02:40 +03:00
if ( request . requestId > 0 ) continue ;
request . requestId = requestId ;
2015-06-28 15:37:10 +03:00
}
}
2016-05-09 13:07:25 +03:00
for ( auto j = _channelMessageDataRequests . begin ( ) ; j ! = _channelMessageDataRequests . cend ( ) ; ) {
2015-09-12 14:59:50 +03:00
if ( j - > isEmpty ( ) ) {
2016-03-10 13:15:21 +03:00
j = _channelMessageDataRequests . erase ( j ) ;
2015-09-12 14:59:50 +03:00
continue ;
}
2017-04-06 22:02:40 +03:00
auto ids = collectMessageIds ( j . value ( ) ) ;
2015-09-12 14:59:50 +03:00
if ( ! ids . isEmpty ( ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_GetMessages ( j . key ( ) - > inputChannel , MTP_vector < MTPint > ( ids ) ) ) . done ( [ this , channel = j . key ( ) ] ( const MTPmessages_Messages & result , mtpRequestId requestId ) {
gotMessageDatas ( channel , result , requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
2016-05-09 13:07:25 +03:00
for ( auto & request : * j ) {
2017-04-06 22:02:40 +03:00
if ( request . requestId > 0 ) continue ;
request . requestId = requestId ;
2015-09-12 14:59:50 +03:00
}
}
+ + j ;
}
2015-06-28 15:37:10 +03:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : gotMessageDatas ( ChannelData * channel , const MTPmessages_Messages & msgs , mtpRequestId requestId ) {
2015-06-28 15:37:10 +03:00
switch ( msgs . type ( ) ) {
2015-09-04 16:01:31 +03:00
case mtpc_messages_messages : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_messages ( ) ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageExisting ) ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_messagesSlice : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_messagesSlice ( ) ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageExisting ) ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_channelMessages : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_channelMessages ( ) ) ;
2015-09-13 11:41:27 +03:00
if ( channel ) {
channel - > ptsReceived ( d . vpts . v ) ;
} else {
2016-03-05 23:12:55 +02:00
LOG ( ( " App Error: received messages.channelMessages when no channel was passed! (ApiWrap::gotDependencyItem) " ) ) ;
2015-09-19 12:13:21 +03:00
}
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageExisting ) ;
2015-09-04 16:01:31 +03:00
} break ;
2015-06-28 15:37:10 +03:00
}
2017-04-06 22:02:40 +03:00
auto requests = messageDataRequests ( channel , true ) ;
2015-09-12 14:59:50 +03:00
if ( requests ) {
2016-05-09 13:07:25 +03:00
for ( auto i = requests - > begin ( ) ; i ! = requests - > cend ( ) ; ) {
2017-04-06 22:02:40 +03:00
if ( i . value ( ) . requestId = = requestId ) {
2016-05-09 13:07:25 +03:00
for_const ( auto & callback , i . value ( ) . callbacks ) {
2016-09-26 15:09:59 +03:00
callback ( channel , i . key ( ) ) ;
2015-06-28 15:37:10 +03:00
}
2015-09-12 14:59:50 +03:00
i = requests - > erase ( i ) ;
} else {
+ + i ;
2015-06-28 15:37:10 +03:00
}
2015-09-12 14:59:50 +03:00
}
if ( channel & & requests - > isEmpty ( ) ) {
2016-03-10 13:15:21 +03:00
_channelMessageDataRequests . remove ( channel ) ;
2015-06-28 15:37:10 +03:00
}
}
}
2015-03-19 12:18:19 +03:00
void ApiWrap : : requestFullPeer ( PeerData * peer ) {
2015-06-30 01:09:23 +03:00
if ( ! peer | | _fullPeerRequests . contains ( peer ) ) return ;
2017-04-06 22:02:40 +03:00
auto sendRequest = [ this , peer ] {
auto failHandler = [ this , peer ] ( const RPCError & error ) {
_fullPeerRequests . remove ( peer ) ;
} ;
if ( auto user = peer - > asUser ( ) ) {
return request ( MTPusers_GetFullUser ( user - > inputUser ) ) . done ( [ this , user ] ( const MTPUserFull & result , mtpRequestId requestId ) {
gotUserFull ( user , result , requestId ) ;
} ) . fail ( failHandler ) . send ( ) ;
} else if ( auto chat = peer - > asChat ( ) ) {
return request ( MTPmessages_GetFullChat ( chat - > inputChat ) ) . done ( [ this , peer ] ( const MTPmessages_ChatFull & result , mtpRequestId requestId ) {
gotChatFull ( peer , result , requestId ) ;
} ) . fail ( failHandler ) . send ( ) ;
} else if ( auto channel = peer - > asChannel ( ) ) {
return request ( MTPchannels_GetFullChannel ( channel - > inputChannel ) ) . done ( [ this , peer ] ( const MTPmessages_ChatFull & result , mtpRequestId requestId ) {
gotChatFull ( peer , result , requestId ) ;
} ) . fail ( failHandler ) . send ( ) ;
}
return 0 ;
} ;
if ( auto requestId = sendRequest ( ) ) {
_fullPeerRequests . insert ( peer , requestId ) ;
2015-03-19 12:18:19 +03:00
}
}
2015-10-30 11:57:22 -04:00
void ApiWrap : : processFullPeer ( PeerData * peer , const MTPmessages_ChatFull & result ) {
2017-04-06 22:02:40 +03:00
gotChatFull ( peer , result , mtpRequestId ( 0 ) ) ;
2015-10-30 11:57:22 -04:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : processFullPeer ( UserData * user , const MTPUserFull & result ) {
gotUserFull ( user , result , mtpRequestId ( 0 ) ) ;
2015-10-30 11:57:22 -04:00
}
void ApiWrap : : gotChatFull ( PeerData * peer , const MTPmessages_ChatFull & result , mtpRequestId req ) {
2017-03-10 22:46:28 +03:00
auto & d = result . c_messages_chatFull ( ) ;
auto & vc = d . vchats . v ;
auto badVersion = false ;
2015-09-03 13:48:40 +03:00
if ( peer - > isChat ( ) ) {
2017-06-04 14:09:29 +03:00
badVersion = ( ! vc . isEmpty ( ) & & vc [ 0 ] . type ( ) = = mtpc_chat & & vc [ 0 ] . c_chat ( ) . vversion . v < peer - > asChat ( ) - > version ) ;
2015-09-03 13:48:40 +03:00
} else if ( peer - > isChannel ( ) ) {
2017-06-04 14:09:29 +03:00
badVersion = ( ! vc . isEmpty ( ) & & vc [ 0 ] . type ( ) = = mtpc_channel & & vc [ 0 ] . c_channel ( ) . vversion . v < peer - > asChannel ( ) - > version ) ;
2015-09-03 13:48:40 +03:00
}
2015-06-30 01:09:23 +03:00
2016-06-02 16:57:49 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-03 13:48:40 +03:00
2017-04-06 22:02:40 +03:00
if ( auto chat = peer - > asChat ( ) ) {
2015-09-03 13:48:40 +03:00
if ( d . vfull_chat . type ( ) ! = mtpc_chatFull ) {
LOG ( ( " MTP Error: bad type in gotChatFull for chat: %1 " ) . arg ( d . vfull_chat . type ( ) ) ) ;
return ;
}
2017-03-10 22:46:28 +03:00
auto & f = d . vfull_chat . c_chatFull ( ) ;
2015-09-03 13:48:40 +03:00
App : : feedParticipants ( f . vparticipants , false , false ) ;
2017-03-10 22:46:28 +03:00
auto & v = f . vbot_info . v ;
for_const ( auto & item , v ) {
switch ( item . type ( ) ) {
2015-09-03 13:48:40 +03:00
case mtpc_botInfo : {
2017-03-10 22:46:28 +03:00
auto & b = item . c_botInfo ( ) ;
if ( auto user = App : : userLoaded ( b . vuser_id . v ) ) {
user - > setBotInfo ( item ) ;
2015-09-03 13:48:40 +03:00
App : : clearPeerUpdated ( user ) ;
2017-04-06 19:49:42 +03:00
fullPeerUpdated ( ) . notify ( user ) ;
2015-09-03 13:48:40 +03:00
}
} break ;
2015-06-15 20:19:24 +03:00
}
}
2017-04-06 22:02:40 +03:00
if ( auto photo = App : : feedPhoto ( f . vchat_photo ) ) {
2015-03-19 12:18:19 +03:00
chat - > photoId = photo - > id ;
2015-09-03 13:48:40 +03:00
photo - > peer = chat ;
2015-06-30 01:09:23 +03:00
} else {
chat - > photoId = 0 ;
2015-03-19 12:18:19 +03:00
}
2016-06-01 16:07:03 +03:00
chat - > setInviteLink ( ( f . vexported_invite . type ( ) = = mtpc_chatInviteExported ) ? qs ( f . vexported_invite . c_chatInviteExported ( ) . vlink ) : QString ( ) ) ;
2015-04-30 16:53:36 +03:00
2016-06-01 16:07:03 +03:00
notifySettingReceived ( MTP_inputNotifyPeer ( peer - > input ) , f . vnotify_settings ) ;
2017-04-06 22:02:40 +03:00
} else if ( auto channel = peer - > asChannel ( ) ) {
2015-09-03 13:48:40 +03:00
if ( d . vfull_chat . type ( ) ! = mtpc_channelFull ) {
LOG ( ( " MTP Error: bad type in gotChatFull for channel: %1 " ) . arg ( d . vfull_chat . type ( ) ) ) ;
return ;
}
2017-04-06 22:02:40 +03:00
auto & f = d . vfull_chat . c_channelFull ( ) ;
2016-06-02 16:02:55 +03:00
auto canViewAdmins = channel - > canViewAdmins ( ) ;
auto canViewMembers = channel - > canViewMembers ( ) ;
2015-10-12 23:02:10 +02:00
channel - > flagsFull = f . vflags . v ;
2017-04-06 22:02:40 +03:00
if ( auto photo = App : : feedPhoto ( f . vchat_photo ) ) {
2015-09-03 13:48:40 +03:00
channel - > photoId = photo - > id ;
photo - > peer = channel ;
} else {
channel - > photoId = 0 ;
}
2015-11-13 18:14:33 +03:00
if ( f . has_migrated_from_chat_id ( ) ) {
if ( ! channel - > mgInfo ) {
2016-03-19 19:55:15 +03:00
channel - > flags | = MTPDchannel : : Flag : : f_megagroup ;
2015-11-13 18:14:33 +03:00
channel - > flagsUpdated ( ) ;
}
2017-04-06 22:02:40 +03:00
auto cfrom = App : : chat ( peerFromChat ( f . vmigrated_from_chat_id ) ) ;
2015-11-20 21:24:44 +03:00
bool updatedTo = ( cfrom - > migrateToPtr ! = channel ) , updatedFrom = ( channel - > mgInfo - > migrateFromPtr ! = cfrom ) ;
if ( updatedTo ) {
2015-11-13 18:14:33 +03:00
cfrom - > migrateToPtr = channel ;
}
2015-11-20 21:24:44 +03:00
if ( updatedFrom ) {
2015-11-13 18:14:33 +03:00
channel - > mgInfo - > migrateFromPtr = cfrom ;
2017-04-06 22:02:40 +03:00
if ( auto h = App : : historyLoaded ( cfrom - > id ) ) {
if ( auto hto = App : : historyLoaded ( channel - > id ) ) {
2015-11-13 18:14:33 +03:00
if ( ! h - > isEmpty ( ) ) {
h - > clear ( true ) ;
}
2016-04-11 14:59:01 +04:00
if ( hto - > inChatList ( Dialogs : : Mode : : All ) & & h - > inChatList ( Dialogs : : Mode : : All ) ) {
2015-11-13 18:14:33 +03:00
App : : removeDialog ( h ) ;
}
}
}
2015-11-20 21:24:44 +03:00
Notify : : migrateUpdated ( channel ) ;
2015-11-13 18:14:33 +03:00
}
2015-11-20 21:24:44 +03:00
if ( updatedTo ) {
Notify : : migrateUpdated ( cfrom ) ;
2015-11-13 18:14:33 +03:00
App : : main ( ) - > peerUpdated ( cfrom ) ;
2015-11-09 12:51:22 +03:00
}
}
2017-03-10 22:46:28 +03:00
auto & v = f . vbot_info . v ;
for_const ( auto & item , v ) {
switch ( item . type ( ) ) {
2015-11-20 16:34:37 +03:00
case mtpc_botInfo : {
2017-03-10 22:46:28 +03:00
auto & b = item . c_botInfo ( ) ;
if ( auto user = App : : userLoaded ( b . vuser_id . v ) ) {
user - > setBotInfo ( item ) ;
2015-11-20 16:34:37 +03:00
App : : clearPeerUpdated ( user ) ;
2017-04-06 19:49:42 +03:00
fullPeerUpdated ( ) . notify ( user ) ;
2015-11-20 16:34:37 +03:00
}
} break ;
}
}
2016-05-31 22:27:11 +03:00
channel - > setAbout ( qs ( f . vabout ) ) ;
2016-06-02 16:02:55 +03:00
channel - > setMembersCount ( f . has_participants_count ( ) ? f . vparticipants_count . v : 0 ) ;
channel - > setAdminsCount ( f . has_admins_count ( ) ? f . vadmins_count . v : 0 ) ;
2017-06-09 18:12:02 +02:00
channel - > setRestrictedCount ( f . has_banned_count ( ) ? f . vbanned_count . v : 0 ) ;
2017-04-07 18:07:26 +03:00
channel - > setKickedCount ( f . has_kicked_count ( ) ? f . vkicked_count . v : 0 ) ;
2016-06-01 16:07:03 +03:00
channel - > setInviteLink ( ( f . vexported_invite . type ( ) = = mtpc_chatInviteExported ) ? qs ( f . vexported_invite . c_chatInviteExported ( ) . vlink ) : QString ( ) ) ;
2017-04-06 22:02:40 +03:00
if ( auto h = App : : historyLoaded ( channel - > id ) ) {
2015-09-21 23:57:42 +03:00
if ( h - > inboxReadBefore < f . vread_inbox_max_id . v + 1 ) {
2016-05-27 19:47:46 +03:00
h - > setUnreadCount ( f . vunread_count . v ) ;
2015-09-21 23:57:42 +03:00
h - > inboxReadBefore = f . vread_inbox_max_id . v + 1 ;
}
2016-05-27 19:47:46 +03:00
accumulate_max ( h - > outboxReadBefore , f . vread_outbox_max_id . v + 1 ) ;
2015-09-21 23:57:42 +03:00
}
2016-03-04 17:34:46 +02:00
if ( channel - > isMegagroup ( ) ) {
if ( f . has_pinned_msg_id ( ) ) {
channel - > mgInfo - > pinnedMsgId = f . vpinned_msg_id . v ;
} else {
channel - > mgInfo - > pinnedMsgId = 0 ;
}
}
2015-09-21 23:57:42 +03:00
channel - > fullUpdated ( ) ;
2015-09-03 13:48:40 +03:00
2017-06-09 18:12:02 +02:00
if ( canViewAdmins ! = channel - > canViewAdmins ( )
| | canViewMembers ! = channel - > canViewMembers ( ) ) Notify : : peerUpdatedDelayed ( channel , Notify : : PeerUpdate : : Flag : : ChannelRightsChanged ) ;
2016-06-02 16:02:55 +03:00
2016-06-01 16:07:03 +03:00
notifySettingReceived ( MTP_inputNotifyPeer ( peer - > input ) , f . vnotify_settings ) ;
2015-09-03 13:48:40 +03:00
}
2015-03-19 12:18:19 +03:00
2015-10-30 11:57:22 -04:00
if ( req ) {
2017-06-04 14:09:29 +03:00
auto i = _fullPeerRequests . find ( peer ) ;
2015-10-30 11:57:22 -04:00
if ( i ! = _fullPeerRequests . cend ( ) & & i . value ( ) = = req ) {
_fullPeerRequests . erase ( i ) ;
}
}
2015-06-30 01:09:23 +03:00
if ( badVersion ) {
2017-06-04 14:09:29 +03:00
if ( auto chat = peer - > asChat ( ) ) {
chat - > version = vc [ 0 ] . c_chat ( ) . vversion . v ;
} else if ( auto channel = peer - > asChannel ( ) ) {
channel - > version = vc [ 0 ] . c_channel ( ) . vversion . v ;
2015-09-03 13:48:40 +03:00
}
2015-06-30 01:09:23 +03:00
requestPeer ( peer ) ;
}
App : : clearPeerUpdated ( peer ) ;
2017-04-06 19:49:42 +03:00
fullPeerUpdated ( ) . notify ( peer ) ;
2015-03-19 12:18:19 +03:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : gotUserFull ( UserData * user , const MTPUserFull & result , mtpRequestId req ) {
2016-10-24 00:03:10 +03:00
auto & d = result . c_userFull ( ) ;
2016-06-02 16:57:49 +03:00
App : : feedUsers ( MTP_vector < MTPUser > ( 1 , d . vuser ) ) ;
2016-03-04 17:34:46 +02:00
if ( d . has_profile_photo ( ) ) {
App : : feedPhoto ( d . vprofile_photo ) ;
}
2017-04-06 22:02:40 +03:00
App : : feedUserLink ( MTP_int ( peerToUser ( user - > id ) ) , d . vlink . c_contacts_link ( ) . vmy_link , d . vlink . c_contacts_link ( ) . vforeign_link ) ;
2016-02-17 20:14:09 +03:00
if ( App : : main ( ) ) {
2017-04-06 22:02:40 +03:00
notifySettingReceived ( MTP_inputNotifyPeer ( user - > input ) , d . vnotify_settings ) ;
2016-02-17 20:14:09 +03:00
}
2015-03-19 12:18:19 +03:00
2016-03-04 17:34:46 +02:00
if ( d . has_bot_info ( ) ) {
2016-10-24 00:03:10 +03:00
user - > setBotInfo ( d . vbot_info ) ;
2016-03-04 17:34:46 +02:00
} else {
2016-10-24 00:03:10 +03:00
user - > setBotInfoVersion ( - 1 ) ;
2016-03-04 17:34:46 +02:00
}
2016-10-24 00:03:10 +03:00
user - > setBlockStatus ( d . is_blocked ( ) ? UserData : : BlockStatus : : Blocked : UserData : : BlockStatus : : NotBlocked ) ;
2017-04-28 20:16:14 +03:00
user - > setCallsStatus ( d . is_phone_calls_private ( ) ? UserData : : CallsStatus : : Private : d . is_phone_calls_available ( ) ? UserData : : CallsStatus : : Enabled : UserData : : CallsStatus : : Disabled ) ;
2016-10-24 00:03:10 +03:00
user - > setAbout ( d . has_about ( ) ? qs ( d . vabout ) : QString ( ) ) ;
user - > setCommonChatsCount ( d . vcommon_chats_count . v ) ;
2015-06-10 18:54:24 +03:00
2015-10-30 11:57:22 -04:00
if ( req ) {
2017-04-06 22:02:40 +03:00
auto i = _fullPeerRequests . find ( user ) ;
2015-10-30 11:57:22 -04:00
if ( i ! = _fullPeerRequests . cend ( ) & & i . value ( ) = = req ) {
_fullPeerRequests . erase ( i ) ;
}
}
2017-04-06 22:02:40 +03:00
App : : clearPeerUpdated ( user ) ;
fullPeerUpdated ( ) . notify ( user ) ;
2015-06-30 01:09:23 +03:00
}
void ApiWrap : : requestPeer ( PeerData * peer ) {
if ( ! peer | | _fullPeerRequests . contains ( peer ) | | _peerRequests . contains ( peer ) ) return ;
2017-04-06 22:02:40 +03:00
auto sendRequest = [ this , peer ] {
auto failHandler = [ this , peer ] ( const RPCError & error ) {
_peerRequests . remove ( peer ) ;
} ;
auto chatHandler = [ this , peer ] ( const MTPmessages_Chats & result ) {
_peerRequests . remove ( peer ) ;
if ( auto chats = Api : : getChatsFromMessagesChats ( result ) ) {
auto & v = chats - > v ;
bool badVersion = false ;
2017-06-04 14:09:29 +03:00
if ( auto chat = peer - > asChat ( ) ) {
badVersion = ( ! v . isEmpty ( ) & & v [ 0 ] . type ( ) = = mtpc_chat & & v [ 0 ] . c_chat ( ) . vversion . v < chat - > version ) ;
} else if ( auto channel = peer - > asChannel ( ) ) {
badVersion = ( ! v . isEmpty ( ) & & v [ 0 ] . type ( ) = = mtpc_channel & & v [ 0 ] . c_channel ( ) . vversion . v < channel - > version ) ;
2017-04-06 22:02:40 +03:00
}
auto chat = App : : feedChats ( * chats ) ;
if ( chat = = peer ) {
if ( badVersion ) {
2017-06-04 14:09:29 +03:00
if ( auto chat = peer - > asChat ( ) ) {
chat - > version = v [ 0 ] . c_chat ( ) . vversion . v ;
} else if ( auto channel = peer - > asChannel ( ) ) {
channel - > version = v [ 0 ] . c_channel ( ) . vversion . v ;
2017-04-06 22:02:40 +03:00
}
requestPeer ( peer ) ;
}
}
}
} ;
if ( auto user = peer - > asUser ( ) ) {
return request ( MTPusers_GetUsers ( MTP_vector < MTPInputUser > ( 1 , user - > inputUser ) ) ) . done ( [ this , user ] ( const MTPVector < MTPUser > & result ) {
_peerRequests . remove ( user ) ;
App : : feedUsers ( result ) ;
} ) . fail ( failHandler ) . send ( ) ;
} else if ( auto chat = peer - > asChat ( ) ) {
return request ( MTPmessages_GetChats ( MTP_vector < MTPint > ( 1 , chat - > inputChat ) ) ) . done ( chatHandler ) . fail ( failHandler ) . send ( ) ;
} else if ( auto channel = peer - > asChannel ( ) ) {
return request ( MTPchannels_GetChannels ( MTP_vector < MTPInputChannel > ( 1 , channel - > inputChannel ) ) ) . done ( chatHandler ) . fail ( failHandler ) . send ( ) ;
}
return 0 ;
} ;
if ( auto requestId = sendRequest ( ) ) {
_peerRequests . insert ( peer , requestId ) ;
2015-06-30 01:09:23 +03:00
}
}
2015-08-07 15:11:50 +03:00
void ApiWrap : : requestPeers ( const QList < PeerData * > & peers ) {
2015-09-17 00:15:13 +03:00
QVector < MTPint > chats ;
QVector < MTPInputChannel > channels ;
2015-08-07 15:11:50 +03:00
QVector < MTPInputUser > users ;
chats . reserve ( peers . size ( ) ) ;
2015-09-17 00:15:13 +03:00
channels . reserve ( peers . size ( ) ) ;
2015-08-07 15:11:50 +03:00
users . reserve ( peers . size ( ) ) ;
for ( QList < PeerData * > : : const_iterator i = peers . cbegin ( ) , e = peers . cend ( ) ; i ! = e ; + + i ) {
if ( ! * i | | _fullPeerRequests . contains ( * i ) | | _peerRequests . contains ( * i ) ) continue ;
2015-09-03 13:48:40 +03:00
if ( ( * i ) - > isUser ( ) ) {
2015-08-07 15:11:50 +03:00
users . push_back ( ( * i ) - > asUser ( ) - > inputUser ) ;
2015-09-03 13:48:40 +03:00
} else if ( ( * i ) - > isChat ( ) ) {
chats . push_back ( ( * i ) - > asChat ( ) - > inputChat ) ;
} else if ( ( * i ) - > isChannel ( ) ) {
2015-09-17 00:15:13 +03:00
channels . push_back ( ( * i ) - > asChannel ( ) - > inputChannel ) ;
2015-08-07 15:11:50 +03:00
}
}
2017-04-06 22:02:40 +03:00
auto handleChats = [ this ] ( const MTPmessages_Chats & result ) {
if ( auto chats = Api : : getChatsFromMessagesChats ( result ) ) {
App : : feedChats ( * chats ) ;
}
} ;
if ( ! chats . isEmpty ( ) ) {
request ( MTPmessages_GetChats ( MTP_vector < MTPint > ( chats ) ) ) . done ( handleChats ) . send ( ) ;
}
if ( ! channels . isEmpty ( ) ) {
request ( MTPchannels_GetChannels ( MTP_vector < MTPInputChannel > ( channels ) ) ) . done ( handleChats ) . send ( ) ;
}
if ( ! users . isEmpty ( ) ) {
request ( MTPusers_GetUsers ( MTP_vector < MTPInputUser > ( users ) ) ) . done ( [ this ] ( const MTPVector < MTPUser > & result ) {
App : : feedUsers ( result ) ;
} ) . send ( ) ;
}
2015-08-07 15:11:50 +03:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : requestLastParticipants ( ChannelData * channel , bool fromStart ) {
if ( ! channel | | ! channel - > isMegagroup ( ) ) {
return ;
}
2017-06-04 14:09:29 +03:00
auto needAdmins = channel - > canViewAdmins ( ) ;
2017-04-06 22:02:40 +03:00
auto adminsOutdated = ( channel - > mgInfo - > lastParticipantsStatus & MegagroupInfo : : LastParticipantsAdminsOutdated ) ! = 0 ;
if ( ( needAdmins & & adminsOutdated ) | | channel - > lastParticipantsCountOutdated ( ) ) {
2015-11-19 18:56:29 +03:00
fromStart = true ;
}
2017-04-06 22:02:40 +03:00
auto i = _participantsRequests . find ( channel ) ;
2015-11-19 18:56:29 +03:00
if ( i ! = _participantsRequests . cend ( ) ) {
if ( fromStart & & i . value ( ) < 0 ) { // was not loading from start
_participantsRequests . erase ( i ) ;
} else {
return ;
}
}
2016-01-09 19:24:16 +08:00
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_GetParticipants ( channel - > inputChannel , MTP_channelParticipantsRecent ( ) , MTP_int ( fromStart ? 0 : channel - > mgInfo - > lastParticipants . size ( ) ) , MTP_int ( Global : : ChatSizeMax ( ) ) ) ) . done ( [ this , channel ] ( const MTPchannels_ChannelParticipants & result , mtpRequestId requestId ) {
lastParticipantsDone ( channel , result , requestId ) ;
} ) . fail ( [ this , channel ] ( const RPCError & error , mtpRequestId requestId ) {
if ( _participantsRequests . value ( channel ) = = requestId | | _participantsRequests . value ( channel ) = = - requestId ) {
_participantsRequests . remove ( channel ) ;
2015-06-30 01:09:23 +03:00
}
2017-04-06 22:02:40 +03:00
} ) . send ( ) ;
2015-06-30 01:09:23 +03:00
2017-04-06 22:02:40 +03:00
_participantsRequests . insert ( channel , fromStart ? requestId : - requestId ) ;
2015-03-19 12:18:19 +03:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : requestBots ( ChannelData * channel ) {
if ( ! channel | | ! channel - > isMegagroup ( ) | | _botsRequests . contains ( channel ) ) {
return ;
2016-08-12 18:22:11 +03:00
}
2015-08-07 15:11:50 +03:00
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_GetParticipants ( channel - > inputChannel , MTP_channelParticipantsBots ( ) , MTP_int ( 0 ) , MTP_int ( Global : : ChatSizeMax ( ) ) ) ) . done ( [ this , channel ] ( const MTPchannels_ChannelParticipants & result , mtpRequestId requestId ) {
lastParticipantsDone ( channel , result , requestId ) ;
} ) . fail ( [ this , channel ] ( const RPCError & error , mtpRequestId requestId ) {
if ( _botsRequests . value ( channel ) = = requestId ) {
_botsRequests . remove ( channel ) ;
}
} ) . send ( ) ;
2015-04-04 23:01:34 +03:00
2017-04-06 22:02:40 +03:00
_botsRequests . insert ( channel , requestId ) ;
2015-03-19 12:18:19 +03:00
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : lastParticipantsDone ( ChannelData * peer , const MTPchannels_ChannelParticipants & result , mtpRequestId requestId ) {
bool bots = ( _botsRequests . value ( peer ) = = requestId ) , fromStart = false ;
2015-11-19 18:56:29 +03:00
if ( bots ) {
_botsRequests . remove ( peer ) ;
} else {
2017-04-06 22:02:40 +03:00
auto was = _participantsRequests . value ( peer ) ;
if ( was = = requestId ) {
2015-11-19 18:56:29 +03:00
fromStart = true ;
2017-04-06 22:02:40 +03:00
} else if ( was ! = - requestId ) {
2015-11-19 18:56:29 +03:00
return ;
}
2015-11-09 12:51:22 +03:00
_participantsRequests . remove ( peer ) ;
}
2015-11-19 18:56:29 +03:00
if ( ! peer - > mgInfo | | result . type ( ) ! = mtpc_channels_channelParticipants ) return ;
2015-11-09 12:51:22 +03:00
2015-11-24 19:19:18 +03:00
History * h = 0 ;
2015-11-19 18:56:29 +03:00
if ( bots ) {
2015-11-24 19:19:18 +03:00
h = App : : historyLoaded ( peer - > id ) ;
2015-11-19 18:56:29 +03:00
peer - > mgInfo - > bots . clear ( ) ;
peer - > mgInfo - > botStatus = - 1 ;
} else if ( fromStart ) {
peer - > mgInfo - > lastAdmins . clear ( ) ;
peer - > mgInfo - > lastParticipants . clear ( ) ;
peer - > mgInfo - > lastParticipantsStatus = MegagroupInfo : : LastParticipantsUpToDate ;
}
2017-03-10 22:46:28 +03:00
auto & d = result . c_channels_channelParticipants ( ) ;
auto & v = d . vparticipants . v ;
2015-11-19 18:56:29 +03:00
App : : feedUsers ( d . vusers ) ;
2017-04-06 22:02:40 +03:00
auto added = false ;
auto needBotsInfos = false ;
auto botStatus = peer - > mgInfo - > botStatus ;
auto keyboardBotFound = ! h | | ! h - > lastKeyboardFrom ;
2017-06-09 18:12:02 +02:00
auto emptyAdminRights = MTP_channelAdminRights ( MTP_flags ( 0 ) ) ;
auto emptyRestrictedRights = MTP_channelBannedRights ( MTP_flags ( 0 ) , MTP_int ( 0 ) ) ;
2017-04-06 22:02:40 +03:00
for_const ( auto & participant , v ) {
auto userId = UserId ( 0 ) ;
2017-06-09 18:12:02 +02:00
auto adminCanEdit = false ;
auto adminRights = emptyAdminRights ;
auto restrictedRights = emptyRestrictedRights ;
2015-11-19 18:56:29 +03:00
2017-04-06 22:02:40 +03:00
switch ( participant . type ( ) ) {
case mtpc_channelParticipant : userId = participant . c_channelParticipant ( ) . vuser_id . v ; break ;
case mtpc_channelParticipantSelf : userId = participant . c_channelParticipantSelf ( ) . vuser_id . v ; break ;
2017-06-09 18:12:02 +02:00
case mtpc_channelParticipantAdmin :
userId = participant . c_channelParticipantAdmin ( ) . vuser_id . v ;
adminCanEdit = participant . c_channelParticipantAdmin ( ) . is_can_edit ( ) ;
adminRights = participant . c_channelParticipantAdmin ( ) . vadmin_rights ;
break ;
case mtpc_channelParticipantBanned :
userId = participant . c_channelParticipantBanned ( ) . vuser_id . v ;
restrictedRights = participant . c_channelParticipantBanned ( ) . vbanned_rights ;
break ;
2017-06-07 15:59:45 +03:00
case mtpc_channelParticipantCreator : userId = participant . c_channelParticipantCreator ( ) . vuser_id . v ; break ;
2015-11-19 18:56:29 +03:00
}
2017-06-04 14:09:29 +03:00
if ( ! userId ) {
continue ;
}
2017-04-06 22:02:40 +03:00
auto u = App : : user ( userId ) ;
2017-06-09 18:12:02 +02:00
if ( participant . type ( ) = = mtpc_channelParticipantCreator ) {
peer - > mgInfo - > creator = u ;
}
2015-11-19 18:56:29 +03:00
if ( bots ) {
if ( u - > botInfo ) {
2016-03-10 18:42:01 +03:00
peer - > mgInfo - > bots . insert ( u ) ;
2015-11-20 16:34:37 +03:00
botStatus = 2 ; // (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
if ( ! u - > botInfo - > inited ) {
needBotsInfos = true ;
}
2015-11-09 12:51:22 +03:00
}
2015-11-24 19:19:18 +03:00
if ( ! keyboardBotFound & & u - > id = = h - > lastKeyboardFrom ) {
keyboardBotFound = true ;
}
2015-11-19 18:56:29 +03:00
} else {
if ( peer - > mgInfo - > lastParticipants . indexOf ( u ) < 0 ) {
2015-11-09 12:51:22 +03:00
peer - > mgInfo - > lastParticipants . push_back ( u ) ;
2017-06-09 18:12:02 +02:00
if ( adminRights . c_channelAdminRights ( ) . vflags . v ) {
peer - > mgInfo - > lastAdmins . insert ( u , MegagroupInfo : : Admin { adminRights , adminCanEdit } ) ;
} else if ( restrictedRights . c_channelBannedRights ( ) . vflags . v ! = 0 ) {
peer - > mgInfo - > lastRestricted . insert ( u , MegagroupInfo : : Restricted { restrictedRights } ) ;
2017-06-07 15:59:45 +03:00
}
2015-11-20 16:34:37 +03:00
if ( u - > botInfo ) {
2016-03-10 18:42:01 +03:00
peer - > mgInfo - > bots . insert ( u ) ;
2015-11-20 16:34:37 +03:00
if ( peer - > mgInfo - > botStatus ! = 0 & & peer - > mgInfo - > botStatus < 2 ) {
peer - > mgInfo - > botStatus = 2 ;
}
}
2015-11-19 18:56:29 +03:00
added = true ;
2015-11-09 12:51:22 +03:00
}
}
}
2015-11-20 16:34:37 +03:00
if ( needBotsInfos ) {
requestFullPeer ( peer ) ;
}
2015-11-24 19:19:18 +03:00
if ( ! keyboardBotFound ) {
h - > clearLastKeyboard ( ) ;
}
2016-06-02 16:02:55 +03:00
int newMembersCount = qMax ( d . vcount . v , v . count ( ) ) ;
if ( newMembersCount > peer - > membersCount ( ) ) {
peer - > setMembersCount ( newMembersCount ) ;
2015-11-19 18:56:29 +03:00
}
2016-06-03 10:20:24 +03:00
if ( ! bots ) {
if ( v . isEmpty ( ) ) {
peer - > setMembersCount ( peer - > mgInfo - > lastParticipants . size ( ) ) ;
}
Notify : : PeerUpdate update ( peer ) ;
update . flags | = Notify : : PeerUpdate : : Flag : : MembersChanged | Notify : : PeerUpdate : : Flag : : AdminsChanged ;
Notify : : peerUpdatedDelayed ( update ) ;
2015-11-19 18:56:29 +03:00
}
2016-06-03 10:20:24 +03:00
2015-11-19 18:56:29 +03:00
peer - > mgInfo - > botStatus = botStatus ;
2017-04-06 19:49:42 +03:00
if ( App : : main ( ) ) fullPeerUpdated ( ) . notify ( peer ) ;
2015-11-09 12:51:22 +03:00
}
2015-09-21 23:57:42 +03:00
void ApiWrap : : requestSelfParticipant ( ChannelData * channel ) {
2017-04-06 22:02:40 +03:00
if ( _selfParticipantRequests . contains ( channel ) ) {
2015-09-21 23:57:42 +03:00
return ;
}
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_GetParticipant ( channel - > inputChannel , MTP_inputUserSelf ( ) ) ) . done ( [ this , channel ] ( const MTPchannels_ChannelParticipant & result ) {
_selfParticipantRequests . remove ( channel ) ;
if ( result . type ( ) ! = mtpc_channels_channelParticipant ) {
LOG ( ( " API Error: unknown type in gotSelfParticipant (%1) " ) . arg ( result . type ( ) ) ) ;
channel - > inviter = - 1 ;
if ( App : : main ( ) ) App : : main ( ) - > onSelfParticipantUpdated ( channel ) ;
return ;
}
2015-09-21 23:57:42 +03:00
2017-04-06 22:02:40 +03:00
auto & p = result . c_channels_channelParticipant ( ) ;
App : : feedUsers ( p . vusers ) ;
switch ( p . vparticipant . type ( ) ) {
case mtpc_channelParticipantSelf : {
auto & d = p . vparticipant . c_channelParticipantSelf ( ) ;
channel - > inviter = d . vinviter_id . v ;
channel - > inviteDate = date ( d . vdate ) ;
} break ;
case mtpc_channelParticipantCreator : {
auto & d = p . vparticipant . c_channelParticipantCreator ( ) ;
2017-06-05 16:33:45 +03:00
channel - > inviter = _session - > userId ( ) ;
2017-04-06 22:02:40 +03:00
channel - > inviteDate = date ( MTP_int ( channel - > date ) ) ;
2017-06-09 18:12:02 +02:00
if ( channel - > mgInfo ) {
channel - > mgInfo - > creator = App : : self ( ) ;
}
2017-04-06 22:02:40 +03:00
} break ;
2017-06-04 14:09:29 +03:00
case mtpc_channelParticipantAdmin : {
auto & d = p . vparticipant . c_channelParticipantAdmin ( ) ;
2017-04-06 22:02:40 +03:00
channel - > inviter = d . vinviter_id . v ;
channel - > inviteDate = date ( d . vdate ) ;
} break ;
}
2015-09-21 23:57:42 +03:00
2017-04-06 22:02:40 +03:00
if ( App : : main ( ) ) App : : main ( ) - > onSelfParticipantUpdated ( channel ) ;
} ) . fail ( [ this , channel ] ( const RPCError & error ) {
_selfParticipantRequests . remove ( channel ) ;
if ( error . type ( ) = = qstr ( " USER_NOT_PARTICIPANT " ) ) {
channel - > inviter = - 1 ;
}
} ) . after ( kSmallDelayMs ) . send ( ) ;
2015-09-21 23:57:42 +03:00
2017-04-06 22:02:40 +03:00
_selfParticipantRequests . insert ( channel , requestId ) ;
2015-09-21 23:57:42 +03:00
}
2017-07-06 00:11:49 +03:00
void ApiWrap : : kickParticipant ( PeerData * peer , UserData * user , const MTPChannelBannedRights & currentRights ) {
2017-04-06 22:02:40 +03:00
auto kick = KickRequest ( peer , user ) ;
if ( _kickRequests . contains ( kick ) ) return ;
2015-11-20 22:03:31 +03:00
2017-04-07 18:07:26 +03:00
if ( auto channel = peer - > asChannel ( ) ) {
2017-06-09 18:12:02 +02:00
auto rights = ChannelData : : KickedRestrictedRights ( ) ;
2017-07-06 00:11:49 +03:00
auto requestId = request ( MTPchannels_EditBanned ( channel - > inputChannel , user - > inputUser , rights ) ) . done ( [ this , channel , user , currentRights , rights ] ( const MTPUpdates & result ) {
2017-06-09 18:12:02 +02:00
applyUpdates ( result ) ;
_kickRequests . remove ( KickRequest ( channel , user ) ) ;
2017-07-06 00:11:49 +03:00
channel - > applyEditBanned ( user , currentRights , rights ) ;
2017-06-09 18:12:02 +02:00
} ) . fail ( [ this , kick ] ( const RPCError & error ) {
_kickRequests . remove ( kick ) ;
} ) . send ( ) ;
_kickRequests . insert ( kick , requestId ) ;
2017-04-06 22:02:40 +03:00
}
2015-11-09 12:51:22 +03:00
}
2017-04-07 18:07:26 +03:00
void ApiWrap : : unblockParticipant ( PeerData * peer , UserData * user ) {
auto kick = KickRequest ( peer , user ) ;
if ( _kickRequests . contains ( kick ) ) return ;
if ( auto channel = peer - > asChannel ( ) ) {
2017-06-09 18:12:02 +02:00
auto requestId = request ( MTPchannels_EditBanned ( channel - > inputChannel , user - > inputUser , MTP_channelBannedRights ( MTP_flags ( 0 ) , MTP_int ( 0 ) ) ) ) . done ( [ this , peer , user ] ( const MTPUpdates & result ) {
applyUpdates ( result ) ;
_kickRequests . remove ( KickRequest ( peer , user ) ) ;
if ( auto channel = peer - > asMegagroup ( ) ) {
if ( channel - > kickedCount ( ) > 0 ) {
channel - > setKickedCount ( channel - > kickedCount ( ) - 1 ) ;
} else {
channel - > updateFull ( true ) ;
}
}
} ) . fail ( [ this , kick ] ( const RPCError & error ) {
_kickRequests . remove ( kick ) ;
} ) . send ( ) ;
_kickRequests . insert ( kick , requestId ) ;
2017-04-07 18:07:26 +03:00
}
}
2015-06-28 15:37:10 +03:00
void ApiWrap : : scheduleStickerSetRequest ( uint64 setId , uint64 access ) {
if ( ! _stickerSetRequests . contains ( setId ) ) {
_stickerSetRequests . insert ( setId , qMakePair ( access , 0 ) ) ;
}
}
2015-03-19 12:18:19 +03:00
2015-06-28 15:37:10 +03:00
void ApiWrap : : requestStickerSets ( ) {
2017-04-06 22:02:40 +03:00
for ( auto i = _stickerSetRequests . begin ( ) , j = i , e = _stickerSetRequests . end ( ) ; i ! = e ; i = j ) {
2016-01-09 20:51:42 +08:00
+ + j ;
2015-06-28 15:37:10 +03:00
if ( i . value ( ) . second ) continue ;
2017-04-06 22:02:40 +03:00
auto waitMs = ( j = = e ) ? 0 : kSmallDelayMs ;
i . value ( ) . second = request ( MTPmessages_GetStickerSet ( MTP_inputStickerSetID ( MTP_long ( i . key ( ) ) , MTP_long ( i . value ( ) . first ) ) ) ) . done ( [ this , setId = i . key ( ) ] ( const MTPmessages_StickerSet & result ) {
gotStickerSet ( setId , result ) ;
} ) . fail ( [ this , setId = i . key ( ) ] ( const RPCError & error ) {
_stickerSetRequests . remove ( setId ) ;
} ) . after ( waitMs ) . send ( ) ;
2015-06-28 15:37:10 +03:00
}
}
2016-11-22 12:48:13 +03:00
void ApiWrap : : saveStickerSets ( const Stickers : : Order & localOrder , const Stickers : : Order & localRemoved ) {
for ( auto requestId : base : : take ( _stickerSetDisenableRequests ) ) {
2017-04-06 22:02:40 +03:00
request ( requestId ) . cancel ( ) ;
2016-11-22 12:48:13 +03:00
}
2017-04-06 22:02:40 +03:00
request ( base : : take ( _stickersReorderRequestId ) ) . cancel ( ) ;
request ( base : : take ( _stickersClearRecentRequestId ) ) . cancel ( ) ;
2016-11-22 12:48:13 +03:00
auto writeInstalled = true , writeRecent = false , writeCloudRecent = false , writeArchived = false ;
auto & recent = cGetRecentStickers ( ) ;
auto & sets = Global : : RefStickerSets ( ) ;
_stickersOrder = localOrder ;
for_const ( auto removedSetId , localRemoved ) {
if ( removedSetId = = Stickers : : CloudRecentSetId ) {
if ( sets . remove ( Stickers : : CloudRecentSetId ) ! = 0 ) {
writeCloudRecent = true ;
}
if ( sets . remove ( Stickers : : CustomSetId ) ) {
writeInstalled = true ;
}
if ( ! recent . isEmpty ( ) ) {
recent . clear ( ) ;
writeRecent = true ;
}
2017-04-06 22:02:40 +03:00
_stickersClearRecentRequestId = request ( MTPmessages_ClearRecentStickers ( MTP_flags ( 0 ) ) ) . done ( [ this ] ( const MTPBool & result ) {
_stickersClearRecentRequestId = 0 ;
} ) . fail ( [ this ] ( const RPCError & error ) {
_stickersClearRecentRequestId = 0 ;
} ) . send ( ) ;
2016-11-22 12:48:13 +03:00
continue ;
}
auto it = sets . find ( removedSetId ) ;
if ( it ! = sets . cend ( ) ) {
for ( auto i = recent . begin ( ) ; i ! = recent . cend ( ) ; ) {
if ( it - > stickers . indexOf ( i - > first ) > = 0 ) {
i = recent . erase ( i ) ;
writeRecent = true ;
} else {
+ + i ;
}
}
if ( ! ( it - > flags & MTPDstickerSet : : Flag : : f_archived ) ) {
MTPInputStickerSet setId = ( it - > id & & it - > access ) ? MTP_inputStickerSetID ( MTP_long ( it - > id ) , MTP_long ( it - > access ) ) : MTP_inputStickerSetShortName ( MTP_string ( it - > shortName ) ) ;
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPmessages_UninstallStickerSet ( setId ) ) . done ( [ this ] ( const MTPBool & result , mtpRequestId requestId ) {
stickerSetDisenabled ( requestId ) ;
} ) . fail ( [ this ] ( const RPCError & error , mtpRequestId requestId ) {
stickerSetDisenabled ( requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
_stickerSetDisenableRequests . insert ( requestId ) ;
2016-11-22 12:48:13 +03:00
int removeIndex = Global : : StickerSetsOrder ( ) . indexOf ( it - > id ) ;
if ( removeIndex > = 0 ) Global : : RefStickerSetsOrder ( ) . removeAt ( removeIndex ) ;
if ( ! ( it - > flags & MTPDstickerSet_ClientFlag : : f_featured ) & & ! ( it - > flags & MTPDstickerSet_ClientFlag : : f_special ) ) {
sets . erase ( it ) ;
} else {
if ( it - > flags & MTPDstickerSet : : Flag : : f_archived ) {
writeArchived = true ;
}
it - > flags & = ~ ( MTPDstickerSet : : Flag : : f_installed | MTPDstickerSet : : Flag : : f_archived ) ;
}
}
}
}
// Clear all installed flags, set only for sets from order.
for ( auto & set : sets ) {
if ( ! ( set . flags & MTPDstickerSet : : Flag : : f_archived ) ) {
set . flags & = ~ MTPDstickerSet : : Flag : : f_installed ;
}
}
auto & order ( Global : : RefStickerSetsOrder ( ) ) ;
order . clear ( ) ;
for_const ( auto setId , _stickersOrder ) {
auto it = sets . find ( setId ) ;
if ( it ! = sets . cend ( ) ) {
if ( ( it - > flags & MTPDstickerSet : : Flag : : f_archived ) & & ! localRemoved . contains ( it - > id ) ) {
MTPInputStickerSet mtpSetId = ( it - > id & & it - > access ) ? MTP_inputStickerSetID ( MTP_long ( it - > id ) , MTP_long ( it - > access ) ) : MTP_inputStickerSetShortName ( MTP_string ( it - > shortName ) ) ;
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPmessages_InstallStickerSet ( mtpSetId , MTP_boolFalse ( ) ) ) . done ( [ this ] ( const MTPmessages_StickerSetInstallResult & result , mtpRequestId requestId ) {
stickerSetDisenabled ( requestId ) ;
} ) . fail ( [ this ] ( const RPCError & error , mtpRequestId requestId ) {
stickerSetDisenabled ( requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
_stickerSetDisenableRequests . insert ( requestId ) ;
2016-11-22 12:48:13 +03:00
it - > flags & = ~ MTPDstickerSet : : Flag : : f_archived ;
writeArchived = true ;
}
order . push_back ( setId ) ;
it - > flags | = MTPDstickerSet : : Flag : : f_installed ;
}
}
for ( auto it = sets . begin ( ) ; it ! = sets . cend ( ) ; ) {
if ( ( it - > flags & MTPDstickerSet_ClientFlag : : f_featured )
| | ( it - > flags & MTPDstickerSet : : Flag : : f_installed )
| | ( it - > flags & MTPDstickerSet : : Flag : : f_archived )
| | ( it - > flags & MTPDstickerSet_ClientFlag : : f_special ) ) {
+ + it ;
} else {
it = sets . erase ( it ) ;
}
}
if ( writeInstalled ) Local : : writeInstalledStickers ( ) ;
if ( writeRecent ) Local : : writeUserSettings ( ) ;
if ( writeArchived ) Local : : writeArchivedStickers ( ) ;
if ( writeCloudRecent ) Local : : writeRecentStickers ( ) ;
emit App : : main ( ) - > stickersUpdated ( ) ;
if ( _stickerSetDisenableRequests . isEmpty ( ) ) {
stickersSaveOrder ( ) ;
} else {
2017-04-06 22:02:40 +03:00
requestSendDelayed ( ) ;
2016-11-22 12:48:13 +03:00
}
}
2017-04-06 22:02:40 +03:00
void ApiWrap : : stickerSetDisenabled ( mtpRequestId requestId ) {
_stickerSetDisenableRequests . remove ( requestId ) ;
if ( _stickerSetDisenableRequests . isEmpty ( ) ) {
stickersSaveOrder ( ) ;
}
} ;
2016-05-25 20:59:21 +03:00
void ApiWrap : : joinChannel ( ChannelData * channel ) {
if ( channel - > amIn ( ) ) {
2017-04-06 22:02:40 +03:00
Notify : : peerUpdatedDelayed ( channel , Notify : : PeerUpdate : : Flag : : ChannelAmIn ) ;
2016-05-25 20:59:21 +03:00
} else if ( ! _channelAmInRequests . contains ( channel ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_JoinChannel ( channel - > inputChannel ) ) . done ( [ this , channel ] ( const MTPUpdates & result ) {
_channelAmInRequests . remove ( channel ) ;
2017-04-13 20:59:05 +03:00
applyUpdates ( result ) ;
2017-04-06 22:02:40 +03:00
} ) . fail ( [ this , channel ] ( const RPCError & error ) {
if ( error . type ( ) = = qstr ( " CHANNELS_TOO_MUCH " ) ) {
Ui : : show ( Box < InformBox > ( lang ( lng_join_channel_error ) ) ) ;
}
_channelAmInRequests . remove ( channel ) ;
} ) . send ( ) ;
2016-05-25 20:59:21 +03:00
_channelAmInRequests . insert ( channel , requestId ) ;
}
}
void ApiWrap : : leaveChannel ( ChannelData * channel ) {
if ( ! channel - > amIn ( ) ) {
2017-04-06 22:02:40 +03:00
Notify : : peerUpdatedDelayed ( channel , Notify : : PeerUpdate : : Flag : : ChannelAmIn ) ;
2016-05-25 20:59:21 +03:00
} else if ( ! _channelAmInRequests . contains ( channel ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPchannels_LeaveChannel ( channel - > inputChannel ) ) . done ( [ this , channel ] ( const MTPUpdates & result ) {
_channelAmInRequests . remove ( channel ) ;
2017-04-13 20:59:05 +03:00
applyUpdates ( result ) ;
2017-04-06 22:02:40 +03:00
} ) . fail ( [ this , channel ] ( const RPCError & error ) {
_channelAmInRequests . remove ( channel ) ;
} ) . send ( ) ;
2016-05-25 20:59:21 +03:00
2017-04-06 22:02:40 +03:00
_channelAmInRequests . insert ( channel , requestId ) ;
2016-06-07 22:59:39 +03:00
}
2016-05-25 20:59:21 +03:00
}
2016-06-01 23:05:37 +03:00
void ApiWrap : : blockUser ( UserData * user ) {
if ( user - > isBlocked ( ) ) {
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserIsBlocked ) ;
} else if ( ! _blockRequests . contains ( user ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPcontacts_Block ( user - > inputUser ) ) . done ( [ this , user ] ( const MTPBool & result ) {
_blockRequests . remove ( user ) ;
user - > setBlockStatus ( UserData : : BlockStatus : : Blocked ) ;
emit App : : main ( ) - > peerUpdated ( user ) ;
} ) . fail ( [ this , user ] ( const RPCError & error ) {
_blockRequests . remove ( user ) ;
} ) . send ( ) ;
2016-06-01 23:05:37 +03:00
_blockRequests . insert ( user , requestId ) ;
}
}
void ApiWrap : : unblockUser ( UserData * user ) {
if ( ! user - > isBlocked ( ) ) {
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserIsBlocked ) ;
} else if ( ! _blockRequests . contains ( user ) ) {
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPcontacts_Unblock ( user - > inputUser ) ) . done ( [ this , user ] ( const MTPBool & result ) {
_blockRequests . remove ( user ) ;
user - > setBlockStatus ( UserData : : BlockStatus : : NotBlocked ) ;
emit App : : main ( ) - > peerUpdated ( user ) ;
} ) . fail ( [ this , user ] ( const RPCError & error ) {
_blockRequests . remove ( user ) ;
} ) . send ( ) ;
2016-06-01 23:05:37 +03:00
_blockRequests . insert ( user , requestId ) ;
}
}
2016-06-01 16:07:03 +03:00
void ApiWrap : : exportInviteLink ( PeerData * peer ) {
if ( _exportInviteRequests . contains ( peer ) ) {
return ;
}
2017-04-06 22:02:40 +03:00
auto sendRequest = [ this , peer ] {
auto exportFail = [ this , peer ] ( const RPCError & error ) {
_exportInviteRequests . remove ( peer ) ;
} ;
if ( auto chat = peer - > asChat ( ) ) {
return request ( MTPmessages_ExportChatInvite ( chat - > inputChat ) ) . done ( [ this , chat ] ( const MTPExportedChatInvite & result ) {
_exportInviteRequests . remove ( chat ) ;
chat - > setInviteLink ( ( result . type ( ) = = mtpc_chatInviteExported ) ? qs ( result . c_chatInviteExported ( ) . vlink ) : QString ( ) ) ;
} ) . fail ( exportFail ) . send ( ) ;
} else if ( auto channel = peer - > asChannel ( ) ) {
return request ( MTPchannels_ExportInvite ( channel - > inputChannel ) ) . done ( [ this , channel ] ( const MTPExportedChatInvite & result ) {
_exportInviteRequests . remove ( channel ) ;
channel - > setInviteLink ( ( result . type ( ) = = mtpc_chatInviteExported ) ? qs ( result . c_chatInviteExported ( ) . vlink ) : QString ( ) ) ;
} ) . fail ( exportFail ) . send ( ) ;
}
return 0 ;
} ;
if ( auto requestId = sendRequest ( ) ) {
_exportInviteRequests . insert ( peer , requestId ) ;
2016-06-01 16:07:03 +03:00
}
}
void ApiWrap : : requestNotifySetting ( PeerData * peer ) {
if ( _notifySettingRequests . contains ( peer ) ) return ;
2017-04-06 22:02:40 +03:00
auto notifyPeer = MTP_inputNotifyPeer ( peer - > input ) ;
auto requestId = request ( MTPaccount_GetNotifySettings ( notifyPeer ) ) . done ( [ this , notifyPeer , peer ] ( const MTPPeerNotifySettings & result ) {
notifySettingReceived ( notifyPeer , result ) ;
_notifySettingRequests . remove ( peer ) ;
} ) . fail ( [ this , notifyPeer , peer ] ( const RPCError & error ) {
notifySettingReceived ( notifyPeer , MTP_peerNotifySettingsEmpty ( ) ) ;
_notifySettingRequests . remove ( peer ) ;
} ) . send ( ) ;
2016-06-01 16:07:03 +03:00
_notifySettingRequests . insert ( peer , requestId ) ;
}
2016-06-07 22:59:39 +03:00
void ApiWrap : : saveDraftToCloudDelayed ( History * history ) {
_draftsSaveRequestIds . insert ( history , 0 ) ;
if ( ! _draftsSaveTimer . isActive ( ) ) {
2017-04-07 15:10:10 +03:00
_draftsSaveTimer . callOnce ( kSaveCloudDraftTimeout ) ;
2016-06-07 22:59:39 +03:00
}
}
2017-03-17 20:19:46 +03:00
void ApiWrap : : savePrivacy ( const MTPInputPrivacyKey & key , QVector < MTPInputPrivacyRule > & & rules ) {
auto keyTypeId = key . type ( ) ;
auto it = _privacySaveRequests . find ( keyTypeId ) ;
if ( it ! = _privacySaveRequests . cend ( ) ) {
2017-04-06 22:02:40 +03:00
request ( it . value ( ) ) . cancel ( ) ;
2017-03-17 20:19:46 +03:00
_privacySaveRequests . erase ( it ) ;
}
2017-04-06 22:02:40 +03:00
auto requestId = request ( MTPaccount_SetPrivacy ( key , MTP_vector < MTPInputPrivacyRule > ( std : : move ( rules ) ) ) ) . done ( [ this , keyTypeId ] ( const MTPaccount_PrivacyRules & result ) {
Expects ( result . type ( ) = = mtpc_account_privacyRules ) ;
auto & rules = result . c_account_privacyRules ( ) ;
App : : feedUsers ( rules . vusers ) ;
_privacySaveRequests . remove ( keyTypeId ) ;
handlePrivacyChange ( keyTypeId , rules . vrules ) ;
} ) . fail ( [ this , keyTypeId ] ( const RPCError & error ) {
_privacySaveRequests . remove ( keyTypeId ) ;
} ) . send ( ) ;
2017-03-17 20:19:46 +03:00
2017-04-06 22:02:40 +03:00
_privacySaveRequests . insert ( keyTypeId , requestId ) ;
2017-03-17 20:19:46 +03:00
}
void ApiWrap : : handlePrivacyChange ( mtpTypeId keyTypeId , const MTPVector < MTPPrivacyRule > & rules ) {
if ( keyTypeId = = mtpc_privacyKeyStatusTimestamp ) {
enum class Rule {
Unknown ,
Allow ,
Disallow ,
} ;
auto userRules = QMap < UserId , Rule > ( ) ;
auto contactsRule = Rule : : Unknown ;
auto everyoneRule = Rule : : Unknown ;
for ( auto & rule : rules . v ) {
auto type = rule . type ( ) ;
if ( type ! = mtpc_privacyValueAllowAll & & type ! = mtpc_privacyValueDisallowAll & & contactsRule ! = Rule : : Unknown ) {
// This is simplified: we ignore per-user rules that come after a contacts rule.
// But none of the official apps provide such complicated rule sets, so its fine.
continue ;
}
switch ( type ) {
case mtpc_privacyValueAllowAll : everyoneRule = Rule : : Allow ; break ;
case mtpc_privacyValueDisallowAll : everyoneRule = Rule : : Disallow ; break ;
case mtpc_privacyValueAllowContacts : contactsRule = Rule : : Allow ; break ;
case mtpc_privacyValueDisallowContacts : contactsRule = Rule : : Disallow ; break ;
case mtpc_privacyValueAllowUsers : {
for_const ( auto & userId , rule . c_privacyValueAllowUsers ( ) . vusers . v ) {
if ( ! userRules . contains ( userId . v ) ) {
userRules . insert ( userId . v , Rule : : Allow ) ;
}
}
} break ;
case mtpc_privacyValueDisallowUsers : {
for_const ( auto & userId , rule . c_privacyValueDisallowUsers ( ) . vusers . v ) {
if ( ! userRules . contains ( userId . v ) ) {
userRules . insert ( userId . v , Rule : : Disallow ) ;
}
}
} break ;
}
if ( everyoneRule ! = Rule : : Unknown ) {
break ;
}
}
auto now = unixtime ( ) ;
App : : enumerateUsers ( [ & userRules , contactsRule , everyoneRule , now ] ( UserData * user ) {
if ( user - > isSelf ( ) | | user - > loadedStatus ! = PeerData : : FullLoaded ) {
return ;
}
if ( user - > onlineTill < = 0 ) {
return ;
}
if ( user - > onlineTill + 3 * 86400 > = now ) {
user - > onlineTill = - 2 ; // recently
} else if ( user - > onlineTill + 7 * 86400 > = now ) {
user - > onlineTill = - 3 ; // last week
} else if ( user - > onlineTill + 30 * 86400 > = now ) {
user - > onlineTill = - 4 ; // last month
} else {
user - > onlineTill = 0 ;
}
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserOnlineChanged ) ;
} ) ;
if ( _contactsStatusesRequestId ) {
2017-04-06 22:02:40 +03:00
request ( _contactsStatusesRequestId ) . cancel ( ) ;
2017-03-17 20:19:46 +03:00
}
2017-04-06 22:02:40 +03:00
_contactsStatusesRequestId = request ( MTPcontacts_GetStatuses ( ) ) . done ( [ this ] ( const MTPVector < MTPContactStatus > & result ) {
_contactsStatusesRequestId = 0 ;
for_const ( auto & item , result . v ) {
t_assert ( item . type ( ) = = mtpc_contactStatus ) ;
auto & data = item . c_contactStatus ( ) ;
if ( auto user = App : : userLoaded ( data . vuser_id . v ) ) {
auto oldOnlineTill = user - > onlineTill ;
auto newOnlineTill = onlineTillFromStatus ( data . vstatus , oldOnlineTill ) ;
if ( oldOnlineTill ! = newOnlineTill ) {
user - > onlineTill = newOnlineTill ;
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserOnlineChanged ) ;
}
}
}
} ) . fail ( [ this ] ( const RPCError & error ) {
_contactsStatusesRequestId = 0 ;
} ) . send ( ) ;
2017-03-17 20:19:46 +03:00
}
}
int ApiWrap : : onlineTillFromStatus ( const MTPUserStatus & status , int currentOnlineTill ) {
switch ( status . type ( ) ) {
case mtpc_userStatusEmpty : return 0 ;
case mtpc_userStatusRecently : return ( currentOnlineTill > - 10 ) ? - 2 : currentOnlineTill ; // don't modify pseudo-online
case mtpc_userStatusLastWeek : return - 3 ;
case mtpc_userStatusLastMonth : return - 4 ;
case mtpc_userStatusOffline : return status . c_userStatusOffline ( ) . vwas_online . v ;
case mtpc_userStatusOnline : return status . c_userStatusOnline ( ) . vexpires . v ;
}
Unexpected ( " Bad UserStatus type. " ) ;
}
2016-06-07 22:59:39 +03:00
void ApiWrap : : saveDraftsToCloud ( ) {
for ( auto i = _draftsSaveRequestIds . begin ( ) , e = _draftsSaveRequestIds . end ( ) ; i ! = e ; + + i ) {
if ( i . value ( ) ) continue ; // sent already
auto history = i . key ( ) ;
auto cloudDraft = history - > cloudDraft ( ) ;
auto localDraft = history - > localDraft ( ) ;
if ( cloudDraft & & cloudDraft - > saveRequestId ) {
2017-04-06 22:02:40 +03:00
request ( base : : take ( cloudDraft - > saveRequestId ) ) . cancel ( ) ;
2016-06-07 22:59:39 +03:00
}
cloudDraft = history - > createCloudDraft ( localDraft ) ;
2017-03-25 18:42:01 +03:00
auto flags = MTPmessages_SaveDraft : : Flags ( 0 ) ;
2016-06-07 22:59:39 +03:00
auto & textWithTags = cloudDraft - > textWithTags ;
if ( cloudDraft - > previewCancelled ) {
flags | = MTPmessages_SaveDraft : : Flag : : f_no_webpage ;
}
if ( cloudDraft - > msgId ) {
flags | = MTPmessages_SaveDraft : : Flag : : f_reply_to_msg_id ;
}
if ( ! textWithTags . tags . isEmpty ( ) ) {
flags | = MTPmessages_SaveDraft : : Flag : : f_entities ;
}
2017-04-08 16:27:53 +03:00
auto entities = linksToMTP ( ConvertTextTagsToEntities ( textWithTags . tags ) , true ) ;
2017-04-06 22:02:40 +03:00
cloudDraft - > saveRequestId = request ( MTPmessages_SaveDraft ( MTP_flags ( flags ) , MTP_int ( cloudDraft - > msgId ) , history - > peer - > input , MTP_string ( textWithTags . text ) , entities ) ) . done ( [ this , history ] ( const MTPBool & result , mtpRequestId requestId ) {
if ( auto cloudDraft = history - > cloudDraft ( ) ) {
if ( cloudDraft - > saveRequestId = = requestId ) {
cloudDraft - > saveRequestId = 0 ;
history - > draftSavedToCloud ( ) ;
}
}
auto i = _draftsSaveRequestIds . find ( history ) ;
if ( i ! = _draftsSaveRequestIds . cend ( ) & & i . value ( ) = = requestId ) {
_draftsSaveRequestIds . remove ( history ) ;
2017-04-29 23:06:32 +03:00
checkQuitPreventFinished ( ) ;
2017-04-06 22:02:40 +03:00
}
} ) . fail ( [ this , history ] ( const RPCError & error , mtpRequestId requestId ) {
if ( auto cloudDraft = history - > cloudDraft ( ) ) {
if ( cloudDraft - > saveRequestId = = requestId ) {
history - > clearCloudDraft ( ) ;
}
}
auto i = _draftsSaveRequestIds . find ( history ) ;
if ( i ! = _draftsSaveRequestIds . cend ( ) & & i . value ( ) = = requestId ) {
_draftsSaveRequestIds . remove ( history ) ;
2017-04-29 23:06:32 +03:00
checkQuitPreventFinished ( ) ;
2017-04-06 22:02:40 +03:00
}
} ) . send ( ) ;
2016-06-07 22:59:39 +03:00
i . value ( ) = cloudDraft - > saveRequestId ;
}
2017-04-29 23:06:32 +03:00
}
bool ApiWrap : : isQuitPrevent ( ) {
2016-06-07 22:59:39 +03:00
if ( _draftsSaveRequestIds . isEmpty ( ) ) {
2017-04-29 23:06:32 +03:00
return false ;
}
LOG ( ( " ApiWrap prevents quit, saving drafts... " ) ) ;
saveDraftsToCloud ( ) ;
return true ;
}
void ApiWrap : : checkQuitPreventFinished ( ) {
if ( _draftsSaveRequestIds . isEmpty ( ) ) {
if ( App : : quitting ( ) ) {
LOG ( ( " ApiWrap doesn't prevent quit any more. " ) ) ;
}
Messenger : : Instance ( ) . quitPreventFinished ( ) ;
2016-06-07 22:59:39 +03:00
}
}
2016-06-01 16:07:03 +03:00
PeerData * ApiWrap : : notifySettingReceived ( MTPInputNotifyPeer notifyPeer , const MTPPeerNotifySettings & settings ) {
PeerData * requestedPeer = nullptr ;
switch ( notifyPeer . type ( ) ) {
case mtpc_inputNotifyAll : App : : main ( ) - > applyNotifySetting ( MTP_notifyAll ( ) , settings ) ; break ;
case mtpc_inputNotifyUsers : App : : main ( ) - > applyNotifySetting ( MTP_notifyUsers ( ) , settings ) ; break ;
case mtpc_inputNotifyChats : App : : main ( ) - > applyNotifySetting ( MTP_notifyChats ( ) , settings ) ; break ;
case mtpc_inputNotifyPeer : {
auto & peer = notifyPeer . c_inputNotifyPeer ( ) . vpeer ;
switch ( peer . type ( ) ) {
case mtpc_inputPeerEmpty : App : : main ( ) - > applyNotifySetting ( MTP_notifyPeer ( MTP_peerUser ( MTP_int ( 0 ) ) ) , settings ) ; break ;
case mtpc_inputPeerSelf : requestedPeer = App : : self ( ) ; break ;
case mtpc_inputPeerUser : requestedPeer = App : : user ( peerFromUser ( peer . c_inputPeerUser ( ) . vuser_id ) ) ; break ;
case mtpc_inputPeerChat : requestedPeer = App : : chat ( peerFromChat ( peer . c_inputPeerChat ( ) . vchat_id ) ) ; break ;
case mtpc_inputPeerChannel : requestedPeer = App : : channel ( peerFromChannel ( peer . c_inputPeerChannel ( ) . vchannel_id ) ) ; break ;
}
if ( requestedPeer ) {
App : : main ( ) - > applyNotifySetting ( MTP_notifyPeer ( peerToMTP ( requestedPeer - > id ) ) , settings ) ;
}
} break ;
}
2017-06-05 16:33:45 +03:00
_session - > notifications ( ) . checkDelayed ( ) ;
2016-06-01 16:07:03 +03:00
return requestedPeer ;
}
2015-06-28 15:37:10 +03:00
void ApiWrap : : gotStickerSet ( uint64 setId , const MTPmessages_StickerSet & result ) {
_stickerSetRequests . remove ( setId ) ;
2016-01-09 19:24:16 +08:00
2015-06-28 15:37:10 +03:00
if ( result . type ( ) ! = mtpc_messages_stickerSet ) return ;
2016-06-28 21:05:38 +03:00
auto & d ( result . c_messages_stickerSet ( ) ) ;
2016-01-09 19:24:16 +08:00
2015-06-28 15:37:10 +03:00
if ( d . vset . type ( ) ! = mtpc_stickerSet ) return ;
2016-06-28 21:05:38 +03:00
auto & s ( d . vset . c_stickerSet ( ) ) ;
2015-06-28 15:37:10 +03:00
2016-06-27 19:25:21 +03:00
auto & sets = Global : : RefStickerSets ( ) ;
2016-03-19 19:55:15 +03:00
auto it = sets . find ( setId ) ;
2015-06-28 15:37:10 +03:00
if ( it = = sets . cend ( ) ) return ;
it - > access = s . vaccess_hash . v ;
it - > hash = s . vhash . v ;
it - > shortName = qs ( s . vshort_name ) ;
2015-12-02 20:17:53 +03:00
it - > title = stickerSetTitle ( s ) ;
2016-07-15 18:58:52 +03:00
auto clientFlags = it - > flags & ( MTPDstickerSet_ClientFlag : : f_featured | MTPDstickerSet_ClientFlag : : f_unread | MTPDstickerSet_ClientFlag : : f_not_loaded | MTPDstickerSet_ClientFlag : : f_special ) ;
2016-06-27 19:25:21 +03:00
it - > flags = s . vflags . v | clientFlags ;
it - > flags & = ~ MTPDstickerSet_ClientFlag : : f_not_loaded ;
2015-06-28 15:37:10 +03:00
2017-03-10 22:46:28 +03:00
auto & d_docs = d . vdocuments . v ;
2016-03-19 19:55:15 +03:00
auto custom = sets . find ( Stickers : : CustomSetId ) ;
2015-06-28 15:37:10 +03:00
2015-12-02 20:17:53 +03:00
StickerPack pack ;
pack . reserve ( d_docs . size ( ) ) ;
2015-06-28 15:37:10 +03:00
for ( int32 i = 0 , l = d_docs . size ( ) ; i ! = l ; + + i ) {
DocumentData * doc = App : : feedDocument ( d_docs . at ( i ) ) ;
2015-07-01 00:07:05 +03:00
if ( ! doc | | ! doc - > sticker ( ) ) continue ;
2015-06-28 15:37:10 +03:00
2015-12-02 20:17:53 +03:00
pack . push_back ( doc ) ;
2015-06-28 15:37:10 +03:00
if ( custom ! = sets . cend ( ) ) {
int32 index = custom - > stickers . indexOf ( doc ) ;
if ( index > = 0 ) {
custom - > stickers . removeAt ( index ) ;
}
2015-03-19 12:18:19 +03:00
}
}
2015-06-28 15:37:10 +03:00
if ( custom ! = sets . cend ( ) & & custom - > stickers . isEmpty ( ) ) {
sets . erase ( custom ) ;
custom = sets . end ( ) ;
}
bool writeRecent = false ;
RecentStickerPack & recent ( cGetRecentStickers ( ) ) ;
2015-12-02 20:17:53 +03:00
for ( RecentStickerPack : : iterator i = recent . begin ( ) ; i ! = recent . cend ( ) ; ) {
if ( it - > stickers . indexOf ( i - > first ) > = 0 & & pack . indexOf ( i - > first ) < 0 ) {
i = recent . erase ( i ) ;
writeRecent = true ;
} else {
+ + i ;
2015-03-19 12:18:19 +03:00
}
2015-12-02 20:17:53 +03:00
}
2016-01-09 19:24:16 +08:00
2015-12-02 20:17:53 +03:00
if ( pack . isEmpty ( ) ) {
2016-03-19 19:55:15 +03:00
int removeIndex = Global : : StickerSetsOrder ( ) . indexOf ( setId ) ;
if ( removeIndex > = 0 ) Global : : RefStickerSetsOrder ( ) . removeAt ( removeIndex ) ;
2015-06-28 15:37:10 +03:00
sets . erase ( it ) ;
} else {
2015-12-02 20:17:53 +03:00
it - > stickers = pack ;
2016-01-09 20:51:42 +08:00
it - > emoji . clear ( ) ;
2017-03-10 22:46:28 +03:00
auto & v = d . vpacks . v ;
2017-02-15 11:50:11 +03:00
for ( auto i = 0 , l = v . size ( ) ; i ! = l ; + + i ) {
if ( v [ i ] . type ( ) ! = mtpc_stickerPack ) continue ;
auto & pack = v [ i ] . c_stickerPack ( ) ;
if ( auto emoji = Ui : : Emoji : : Find ( qs ( pack . vemoticon ) ) ) {
emoji = emoji - > original ( ) ;
2017-03-10 22:46:28 +03:00
auto & stickers = pack . vdocuments . v ;
2017-02-23 12:32:28 +03:00
2016-01-09 20:51:42 +08:00
StickerPack p ;
p . reserve ( stickers . size ( ) ) ;
2017-02-15 11:50:11 +03:00
for ( auto j = 0 , c = stickers . size ( ) ; j ! = c ; + + j ) {
auto doc = App : : document ( stickers [ j ] . v ) ;
2016-01-09 20:51:42 +08:00
if ( ! doc | | ! doc - > sticker ( ) ) continue ;
p . push_back ( doc ) ;
}
2017-02-15 11:50:11 +03:00
it - > emoji . insert ( emoji , p ) ;
2016-01-09 20:51:42 +08:00
}
}
2015-06-28 15:37:10 +03:00
}
if ( writeRecent ) {
Local : : writeUserSettings ( ) ;
}
2016-07-21 13:09:47 +03:00
if ( it - > flags & MTPDstickerSet : : Flag : : f_installed ) {
if ( ! ( it - > flags & MTPDstickerSet : : Flag : : f_archived ) ) {
Local : : writeInstalledStickers ( ) ;
}
}
if ( it - > flags & MTPDstickerSet_ClientFlag : : f_featured ) {
Local : : writeFeaturedStickers ( ) ;
}
2015-06-28 15:37:10 +03:00
if ( App : : main ( ) ) emit App : : main ( ) - > stickersUpdated ( ) ;
}
void ApiWrap : : requestWebPageDelayed ( WebPageData * page ) {
if ( page - > pendingTill < = 0 ) return ;
_webPagesPending . insert ( page , 0 ) ;
2017-04-07 15:10:10 +03:00
auto left = ( page - > pendingTill - unixtime ( ) ) * 1000 ;
2015-06-28 15:37:10 +03:00
if ( ! _webPagesTimer . isActive ( ) | | left < = _webPagesTimer . remainingTime ( ) ) {
2017-04-07 15:10:10 +03:00
_webPagesTimer . callOnce ( ( left < 0 ? 0 : left ) + 1 ) ;
2015-03-19 12:18:19 +03:00
}
}
2015-06-28 15:37:10 +03:00
void ApiWrap : : clearWebPageRequest ( WebPageData * page ) {
_webPagesPending . remove ( page ) ;
2017-04-07 15:10:10 +03:00
if ( _webPagesPending . isEmpty ( ) & & _webPagesTimer . isActive ( ) ) {
_webPagesTimer . cancel ( ) ;
}
2015-06-28 15:37:10 +03:00
}
void ApiWrap : : clearWebPageRequests ( ) {
_webPagesPending . clear ( ) ;
2017-04-07 15:10:10 +03:00
_webPagesTimer . cancel ( ) ;
2015-06-28 15:37:10 +03:00
}
2015-04-04 23:01:34 +03:00
void ApiWrap : : resolveWebPages ( ) {
2017-04-06 22:02:40 +03:00
auto ids = QVector < MTPint > ( ) ; // temp_req_id = -1
using IndexAndMessageIds = QPair < int32 , QVector < MTPint > > ;
2016-09-27 16:37:18 +03:00
using MessageIdsByChannel = QMap < ChannelData * , IndexAndMessageIds > ;
2015-09-12 14:59:50 +03:00
MessageIdsByChannel idsByChannel ; // temp_req_id = -index - 2
2016-09-27 16:37:18 +03:00
auto & items = App : : webPageItems ( ) ;
2015-04-04 23:01:34 +03:00
ids . reserve ( _webPagesPending . size ( ) ) ;
int32 t = unixtime ( ) , m = INT_MAX ;
2016-09-27 16:37:18 +03:00
for ( auto i = _webPagesPending . begin ( ) ; i ! = _webPagesPending . cend ( ) ; + + i ) {
2015-09-12 14:59:50 +03:00
if ( i . value ( ) > 0 ) continue ;
2015-04-04 23:01:34 +03:00
if ( i . key ( ) - > pendingTill < = t ) {
2016-09-27 16:37:18 +03:00
auto j = items . constFind ( i . key ( ) ) ;
2015-04-04 23:01:34 +03:00
if ( j ! = items . cend ( ) & & ! j . value ( ) . isEmpty ( ) ) {
2016-09-27 16:37:18 +03:00
for_const ( auto item , j . value ( ) ) {
2015-09-12 14:59:50 +03:00
if ( item - > id > 0 ) {
if ( item - > channelId ( ) = = NoChannel ) {
ids . push_back ( MTP_int ( item - > id ) ) ;
i . value ( ) = - 1 ;
} else {
2016-09-27 16:37:18 +03:00
auto channel = item - > history ( ) - > peer - > asChannel ( ) ;
2017-04-06 22:02:40 +03:00
auto channelMap = idsByChannel . find ( channel ) ;
2015-09-12 14:59:50 +03:00
if ( channelMap = = idsByChannel . cend ( ) ) {
2017-04-06 22:02:40 +03:00
channelMap = idsByChannel . insert ( channel , IndexAndMessageIds ( idsByChannel . size ( ) , QVector < MTPint > ( 1 , MTP_int ( item - > id ) ) ) ) ;
2015-09-12 14:59:50 +03:00
} else {
channelMap . value ( ) . second . push_back ( MTP_int ( item - > id ) ) ;
}
i . value ( ) = - channelMap . value ( ) . first - 2 ;
}
break ;
}
}
2015-04-04 23:01:34 +03:00
}
} else {
m = qMin ( m , i . key ( ) - > pendingTill - t ) ;
}
}
2015-09-12 14:59:50 +03:00
2017-04-06 22:02:40 +03:00
auto requestId = mtpRequestId ( 0 ) ;
if ( ! ids . isEmpty ( ) ) {
requestId = request ( MTPmessages_GetMessages ( MTP_vector < MTPint > ( ids ) ) ) . done ( [ this ] ( const MTPmessages_Messages & result , mtpRequestId requestId ) {
gotWebPages ( nullptr , result , requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
}
QVector < mtpRequestId > reqsByIndex ( idsByChannel . size ( ) , 0 ) ;
2016-09-27 16:37:18 +03:00
for ( auto i = idsByChannel . cbegin ( ) , e = idsByChannel . cend ( ) ; i ! = e ; + + i ) {
2017-04-06 22:02:40 +03:00
reqsByIndex [ i . value ( ) . first ] = request ( MTPchannels_GetMessages ( i . key ( ) - > inputChannel , MTP_vector < MTPint > ( i . value ( ) . second ) ) ) . done ( [ this , channel = i . key ( ) ] ( const MTPmessages_Messages & result , mtpRequestId requestId ) {
gotWebPages ( channel , result , requestId ) ;
} ) . after ( kSmallDelayMs ) . send ( ) ;
}
if ( requestId | | ! reqsByIndex . isEmpty ( ) ) {
for ( auto & pendingRequestId : _webPagesPending ) {
if ( pendingRequestId > 0 ) continue ;
if ( pendingRequestId < 0 ) {
if ( pendingRequestId = = - 1 ) {
pendingRequestId = requestId ;
2015-09-12 14:59:50 +03:00
} else {
2017-04-06 22:02:40 +03:00
pendingRequestId = reqsByIndex [ - pendingRequestId - 2 ] ;
2015-09-12 14:59:50 +03:00
}
2015-04-04 23:01:34 +03:00
}
}
}
2015-09-12 14:59:50 +03:00
2017-04-07 15:10:10 +03:00
if ( m < INT_MAX ) {
_webPagesTimer . callOnce ( m * 1000 ) ;
}
2015-04-04 23:01:34 +03:00
}
2017-04-06 19:49:42 +03:00
void ApiWrap : : requestParticipantsCountDelayed ( ChannelData * channel ) {
2017-04-07 15:10:10 +03:00
_participantsCountRequestTimer . call ( kReloadChannelMembersTimeout , [ this , channel ] {
2017-04-06 19:49:42 +03:00
channel - > updateFull ( true ) ;
} ) ;
2015-11-13 18:14:33 +03:00
}
2015-09-13 11:41:27 +03:00
void ApiWrap : : gotWebPages ( ChannelData * channel , const MTPmessages_Messages & msgs , mtpRequestId req ) {
2015-04-04 23:01:34 +03:00
const QVector < MTPMessage > * v = 0 ;
switch ( msgs . type ( ) ) {
2015-09-04 16:01:31 +03:00
case mtpc_messages_messages : {
2016-09-27 16:37:18 +03:00
auto & d = msgs . c_messages_messages ( ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2017-03-10 22:46:28 +03:00
v = & d . vmessages . v ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_messagesSlice : {
2016-09-27 16:37:18 +03:00
auto & d = msgs . c_messages_messagesSlice ( ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2017-03-10 22:46:28 +03:00
v = & d . vmessages . v ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_channelMessages : {
2016-09-27 16:37:18 +03:00
auto & d = msgs . c_messages_channelMessages ( ) ;
2015-09-13 11:41:27 +03:00
if ( channel ) {
channel - > ptsReceived ( d . vpts . v ) ;
} else {
2015-09-19 12:13:21 +03:00
LOG ( ( " API Error: received messages.channelMessages when no channel was passed! (ApiWrap::gotWebPages) " ) ) ;
}
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2017-03-10 22:46:28 +03:00
v = & d . vmessages . v ;
2015-09-04 16:01:31 +03:00
} break ;
2015-04-04 23:01:34 +03:00
}
2015-09-04 16:01:31 +03:00
if ( ! v ) return ;
QMap < uint64 , int32 > msgsIds ; // copied from feedMsgs
2015-04-04 23:01:34 +03:00
for ( int32 i = 0 , l = v - > size ( ) ; i < l ; + + i ) {
2016-04-08 14:44:35 +04:00
const auto & msg ( v - > at ( i ) ) ;
2015-04-04 23:01:34 +03:00
switch ( msg . type ( ) ) {
2015-09-04 16:01:31 +03:00
case mtpc_message : msgsIds . insert ( ( uint64 ( uint32 ( msg . c_message ( ) . vid . v ) ) < < 32 ) | uint64 ( i ) , i ) ; break ;
case mtpc_messageEmpty : msgsIds . insert ( ( uint64 ( uint32 ( msg . c_messageEmpty ( ) . vid . v ) ) < < 32 ) | uint64 ( i ) , i ) ; break ;
case mtpc_messageService : msgsIds . insert ( ( uint64 ( uint32 ( msg . c_messageService ( ) . vid . v ) ) < < 32 ) | uint64 ( i ) , i ) ; break ;
2015-04-04 23:01:34 +03:00
}
}
2016-09-27 16:37:18 +03:00
for_const ( auto msgId , msgsIds ) {
if ( auto item = App : : histories ( ) . addNewMessage ( v - > at ( msgId ) , NewMessageExisting ) ) {
2016-03-19 19:55:15 +03:00
item - > setPendingInitDimensions ( ) ;
2015-04-04 23:01:34 +03:00
}
}
2016-09-27 16:37:18 +03:00
auto & items = App : : webPageItems ( ) ;
for ( auto i = _webPagesPending . begin ( ) ; i ! = _webPagesPending . cend ( ) ; ) {
2015-04-04 23:01:34 +03:00
if ( i . value ( ) = = req ) {
if ( i . key ( ) - > pendingTill > 0 ) {
i . key ( ) - > pendingTill = - 1 ;
2016-09-27 16:37:18 +03:00
auto j = items . constFind ( i . key ( ) ) ;
2015-04-04 23:01:34 +03:00
if ( j ! = items . cend ( ) ) {
2016-09-27 16:37:18 +03:00
for_const ( auto item , j . value ( ) ) {
item - > setPendingInitDimensions ( ) ;
2015-04-04 23:01:34 +03:00
}
}
}
i = _webPagesPending . erase ( i ) ;
} else {
+ + i ;
}
}
}
2016-11-22 12:48:13 +03:00
void ApiWrap : : stickersSaveOrder ( ) {
if ( _stickersOrder . size ( ) > 1 ) {
QVector < MTPlong > mtpOrder ;
mtpOrder . reserve ( _stickersOrder . size ( ) ) ;
for_const ( auto setId , _stickersOrder ) {
mtpOrder . push_back ( MTP_long ( setId ) ) ;
}
2017-04-06 22:02:40 +03:00
_stickersReorderRequestId = request ( MTPmessages_ReorderStickerSets ( MTP_flags ( 0 ) , MTP_vector < MTPlong > ( mtpOrder ) ) ) . done ( [ this ] ( const MTPBool & result ) {
_stickersReorderRequestId = 0 ;
} ) . fail ( [ this ] ( const RPCError & error ) {
_stickersReorderRequestId = 0 ;
Global : : SetLastStickersUpdate ( 0 ) ;
App : : main ( ) - > updateStickers ( ) ;
} ) . send ( ) ;
2016-11-22 12:48:13 +03:00
}
}
2017-04-06 22:02:40 +03:00
ApiWrap : : ~ ApiWrap ( ) = default ;