mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 00:08:02 +00:00
Update API scheme to layer 100.
This commit is contained in:
parent
68fb9b8b67
commit
c4aac5fa0e
@ -153,10 +153,13 @@ inputPeerSelf#7da07ec9 = InputPeer;
|
||||
inputPeerChat#179be863 chat_id:int = InputPeer;
|
||||
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
|
||||
inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer;
|
||||
inputPeerUserFromMessage#17bae2e6 peer:InputPeer msg_id:int user_id:int = InputPeer;
|
||||
inputPeerChannelFromMessage#9c95f7bb peer:InputPeer msg_id:int channel_id:int = InputPeer;
|
||||
|
||||
inputUserEmpty#b98886cf = InputUser;
|
||||
inputUserSelf#f7c1b13f = InputUser;
|
||||
inputUser#d8292816 user_id:int access_hash:long = InputUser;
|
||||
inputUserFromMessage#2d117597 peer:InputPeer msg_id:int user_id:int = InputUser;
|
||||
|
||||
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
|
||||
|
||||
@ -229,11 +232,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
chatEmpty#9ba2d800 id:int = Chat;
|
||||
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||
chatForbidden#7328bdb id:int title:string = Chat;
|
||||
channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||
channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
|
||||
channelFull#3648977 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int pts:int = ChatFull;
|
||||
channelFull#9882e516 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.13?int pts:int = ChatFull;
|
||||
|
||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||
@ -246,8 +249,8 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#475cdbd5 photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
||||
|
||||
messageEmpty#83e5de54 id:int = Message;
|
||||
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
|
||||
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
|
||||
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
|
||||
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
|
||||
@ -353,7 +356,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
|
||||
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||
|
||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#a6c47aaa flags:# inexact:flags.1?true count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
||||
|
||||
@ -546,6 +549,7 @@ inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
||||
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
|
||||
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey;
|
||||
|
||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||
@ -553,6 +557,7 @@ privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
||||
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
||||
privacyKeyForwards#69ec56a3 = PrivacyKey;
|
||||
privacyKeyProfilePhoto#96151fed = PrivacyKey;
|
||||
privacyKeyPhoneNumber#d19ae46d = PrivacyKey;
|
||||
|
||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||
@ -560,6 +565,8 @@ inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
|
||||
inputPrivacyValueAllowChatParticipants#4c81c1ba chats:Vector<int> = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowChatParticipants#d82363af chats:Vector<int> = InputPrivacyRule;
|
||||
|
||||
privacyValueAllowContacts#fffe1bac = PrivacyRule;
|
||||
privacyValueAllowAll#65427b82 = PrivacyRule;
|
||||
@ -567,8 +574,10 @@ privacyValueAllowUsers#4d5bbe0c users:Vector<int> = PrivacyRule;
|
||||
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
|
||||
privacyValueDisallowAll#8b73e763 = PrivacyRule;
|
||||
privacyValueDisallowUsers#c7f49b7 users:Vector<int> = PrivacyRule;
|
||||
privacyValueAllowChatParticipants#18be796b chats:Vector<int> = PrivacyRule;
|
||||
privacyValueDisallowChatParticipants#acae0690 chats:Vector<int> = PrivacyRule;
|
||||
|
||||
account.privacyRules#554abb6f rules:Vector<PrivacyRule> users:Vector<User> = account.PrivacyRules;
|
||||
account.privacyRules#50a04e45 rules:Vector<PrivacyRule> chats:Vector<Chat> users:Vector<User> = account.PrivacyRules;
|
||||
|
||||
accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
|
||||
|
||||
@ -592,7 +601,6 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
|
||||
|
||||
contactLinkUnknown#5f4f9247 = ContactLink;
|
||||
contactLinkNone#feedd3ad = ContactLink;
|
||||
contactLinkHasPhone#268f3f59 = ContactLink;
|
||||
contactLinkContact#d502c2d0 = ContactLink;
|
||||
|
||||
webPageEmpty#eb1477e8 id:long = WebPage;
|
||||
@ -640,6 +648,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
|
||||
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
|
||||
keyboardButtonGame#50f41ccf text:string = KeyboardButton;
|
||||
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
|
||||
keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
|
||||
inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
|
||||
|
||||
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
|
||||
|
||||
@ -666,6 +676,7 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
|
||||
|
||||
inputChannelEmpty#ee8c1e86 = InputChannel;
|
||||
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
|
||||
inputChannelFromMessage#2a286531 peer:InputPeer msg_id:int channel_id:int = InputChannel;
|
||||
|
||||
contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;
|
||||
|
||||
@ -761,6 +772,8 @@ topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
|
||||
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
|
||||
topPeerCategoryChannels#161d9628 = TopPeerCategory;
|
||||
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
|
||||
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
|
||||
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
|
||||
|
||||
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
|
||||
|
||||
@ -945,6 +958,7 @@ channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputSticker
|
||||
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction;
|
||||
|
||||
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
||||
|
||||
@ -1145,6 +1159,12 @@ inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer;
|
||||
|
||||
folderPeer#e9baa668 peer:Peer folder_id:int = FolderPeer;
|
||||
|
||||
messages.searchCounter#e844ebff flags:# inexact:flags.1?true filter:MessagesFilter count:int = messages.SearchCounter;
|
||||
|
||||
urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User domain:string = UrlAuthResult;
|
||||
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
|
||||
urlAuthResultDefault#a9d6db1f = UrlAuthResult;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -1243,7 +1263,7 @@ contacts.unblock#e54100bd id:InputUser = Bool;
|
||||
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
|
||||
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
||||
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
|
||||
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
||||
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
||||
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
|
||||
contacts.resetSaved#879537f1 = Bool;
|
||||
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
||||
@ -1297,7 +1317,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par
|
||||
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
||||
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||
messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.searchGlobal#f79c611 q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
||||
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
||||
@ -1359,6 +1379,9 @@ messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
|
||||
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
|
||||
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
|
||||
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
||||
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||
@ -1427,6 +1450,9 @@ channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool
|
||||
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
||||
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
|
||||
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
|
||||
channels.getBroadcastsForDiscussion#1a87f304 = messages.Chats;
|
||||
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
@ -1461,4 +1487,4 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
|
||||
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
||||
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||
|
||||
// LAYER 99
|
||||
// LAYER 100
|
||||
|
@ -185,6 +185,26 @@ MTPInputPrivacyKey ApiWrap::Privacy::Input(Key key) {
|
||||
Unexpected("Key in ApiWrap::Privacy::Input.");
|
||||
}
|
||||
|
||||
std::optional<ApiWrap::Privacy::Key> ApiWrap::Privacy::KeyFromMTP(
|
||||
mtpTypeId type) {
|
||||
using Key = Privacy::Key;
|
||||
switch (type) {
|
||||
case mtpc_privacyKeyStatusTimestamp:
|
||||
case mtpc_inputPrivacyKeyStatusTimestamp: return Key::LastSeen;
|
||||
case mtpc_privacyKeyChatInvite:
|
||||
case mtpc_inputPrivacyKeyChatInvite: return Key::Invites;
|
||||
case mtpc_privacyKeyPhoneCall:
|
||||
case mtpc_inputPrivacyKeyPhoneCall: return Key::Calls;
|
||||
case mtpc_privacyKeyPhoneP2P:
|
||||
case mtpc_inputPrivacyKeyPhoneP2P: return Key::CallsPeer2Peer;
|
||||
case mtpc_privacyKeyForwards:
|
||||
case mtpc_inputPrivacyKeyForwards: return Key::Forwards;
|
||||
case mtpc_privacyKeyProfilePhoto:
|
||||
case mtpc_inputPrivacyKeyProfilePhoto: return Key::ProfilePhoto;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ApiWrap::ApiWrap(not_null<AuthSession*> session)
|
||||
: _session(session)
|
||||
, _messageDataResolveDelayed([=] { resolveMessageDatas(); })
|
||||
@ -2276,7 +2296,9 @@ void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) {
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules) {
|
||||
void ApiWrap::savePrivacy(
|
||||
const MTPInputPrivacyKey &key,
|
||||
QVector<MTPInputPrivacyRule> &&rules) {
|
||||
const auto keyTypeId = key.type();
|
||||
const auto it = _privacySaveRequests.find(keyTypeId);
|
||||
if (it != _privacySaveRequests.cend()) {
|
||||
@ -2288,12 +2310,14 @@ void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacy
|
||||
key,
|
||||
MTP_vector<MTPInputPrivacyRule>(std::move(rules))
|
||||
)).done([=](const MTPaccount_PrivacyRules &result) {
|
||||
Expects(result.type() == mtpc_account_privacyRules);
|
||||
|
||||
auto &rules = result.c_account_privacyRules();
|
||||
_session->data().processUsers(rules.vusers);
|
||||
_privacySaveRequests.remove(keyTypeId);
|
||||
handlePrivacyChange(keyTypeId, rules.vrules);
|
||||
result.match([&](const MTPDaccount_privacyRules &data) {
|
||||
_session->data().processUsers(data.vusers);
|
||||
_session->data().processChats(data.vchats);
|
||||
_privacySaveRequests.remove(keyTypeId);
|
||||
if (const auto key = Privacy::KeyFromMTP(keyTypeId)) {
|
||||
handlePrivacyChange(*key, data.vrules);
|
||||
}
|
||||
});
|
||||
}).fail([=](const RPCError &error) {
|
||||
_privacySaveRequests.remove(keyTypeId);
|
||||
}).send();
|
||||
@ -2302,80 +2326,16 @@ void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacy
|
||||
}
|
||||
|
||||
void ApiWrap::handlePrivacyChange(
|
||||
mtpTypeId keyTypeId,
|
||||
Privacy::Key key,
|
||||
const MTPVector<MTPPrivacyRule> &rules) {
|
||||
using Key = Privacy::Key;
|
||||
const auto key = [&]() -> std::optional<Key> {
|
||||
switch (keyTypeId) {
|
||||
case mtpc_privacyKeyStatusTimestamp:
|
||||
case mtpc_inputPrivacyKeyStatusTimestamp: return Key::LastSeen;
|
||||
case mtpc_privacyKeyChatInvite:
|
||||
case mtpc_inputPrivacyKeyChatInvite: return Key::Invites;
|
||||
case mtpc_privacyKeyPhoneCall:
|
||||
case mtpc_inputPrivacyKeyPhoneCall: return Key::Calls;
|
||||
case mtpc_privacyKeyPhoneP2P:
|
||||
case mtpc_inputPrivacyKeyPhoneP2P: return Key::CallsPeer2Peer;
|
||||
case mtpc_privacyKeyForwards:
|
||||
case mtpc_inputPrivacyKeyForwards: return Key::Forwards;
|
||||
case mtpc_privacyKeyProfilePhoto:
|
||||
case mtpc_inputPrivacyKeyProfilePhoto: return Key::ProfilePhoto;
|
||||
}
|
||||
return std::nullopt;
|
||||
}();
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
pushPrivacy(*key, rules.v);
|
||||
if (*key == Key::LastSeen) {
|
||||
pushPrivacy(key, rules.v);
|
||||
if (key == Privacy::Key::LastSeen) {
|
||||
updatePrivacyLastSeens(rules.v);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::updatePrivacyLastSeens(const QVector<MTPPrivacyRule> &rules) {
|
||||
enum class Rule {
|
||||
Unknown,
|
||||
Allow,
|
||||
Disallow,
|
||||
};
|
||||
auto userRules = QMap<UserId, Rule>();
|
||||
auto contactsRule = Rule::Unknown;
|
||||
auto everyoneRule = Rule::Unknown;
|
||||
for (auto &rule : rules) {
|
||||
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();
|
||||
const auto now = unixtime();
|
||||
_session->data().enumerateUsers([&](UserData *user) {
|
||||
if (user->isSelf() || user->loadedStatus != PeerData::FullLoaded) {
|
||||
return;
|
||||
@ -5642,6 +5602,7 @@ void ApiWrap::reloadPrivacy(Privacy::Key key) {
|
||||
_privacyRequestIds.erase(key);
|
||||
result.match([&](const MTPDaccount_privacyRules &data) {
|
||||
_session->data().processUsers(data.vusers);
|
||||
_session->data().processChats(data.vchats);
|
||||
pushPrivacy(key, data.vrules.v);
|
||||
});
|
||||
}).fail([=](const RPCError &error) {
|
||||
@ -5664,8 +5625,10 @@ auto ApiWrap::parsePrivacy(const QVector<MTPPrivacyRule> &rules)
|
||||
optionSet = true;
|
||||
result.option = option;
|
||||
};
|
||||
auto &always = result.always;
|
||||
auto &never = result.never;
|
||||
auto &alwaysUsers = result.alwaysUsers;
|
||||
auto &neverUsers = result.neverUsers;
|
||||
auto &alwaysChats = result.alwaysChats;
|
||||
auto &neverChats = result.neverChats;
|
||||
const auto Feed = [&](const MTPPrivacyRule &rule) {
|
||||
rule.match([&](const MTPDprivacyValueAllowAll &) {
|
||||
SetOption(Option::Everyone);
|
||||
@ -5673,12 +5636,25 @@ auto ApiWrap::parsePrivacy(const QVector<MTPPrivacyRule> &rules)
|
||||
SetOption(Option::Contacts);
|
||||
}, [&](const MTPDprivacyValueAllowUsers &data) {
|
||||
const auto &users = data.vusers.v;
|
||||
always.reserve(always.size() + users.size());
|
||||
alwaysUsers.reserve(alwaysUsers.size() + users.size());
|
||||
for (const auto userId : users) {
|
||||
const auto user = _session->data().user(UserId(userId.v));
|
||||
if (!base::contains(never, user)
|
||||
&& !base::contains(always, user)) {
|
||||
always.push_back(user);
|
||||
if (!base::contains(neverUsers, user)
|
||||
&& !base::contains(alwaysUsers, user)) {
|
||||
alwaysUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
}, [&](const MTPDprivacyValueAllowChatParticipants &data) {
|
||||
const auto &chats = data.vchats.v;
|
||||
alwaysChats.reserve(alwaysChats.size() + chats.size());
|
||||
for (const auto chatId : chats) {
|
||||
const auto chat = _session->data().chatLoaded(chatId.v);
|
||||
const auto peer = chat
|
||||
? static_cast<PeerData*>(chat)
|
||||
: _session->data().channel(chatId.v);
|
||||
if (!base::contains(neverChats, peer)
|
||||
&& !base::contains(alwaysChats, peer)) {
|
||||
alwaysChats.emplace_back(peer);
|
||||
}
|
||||
}
|
||||
}, [&](const MTPDprivacyValueDisallowContacts &) {
|
||||
@ -5687,12 +5663,25 @@ auto ApiWrap::parsePrivacy(const QVector<MTPPrivacyRule> &rules)
|
||||
SetOption(Option::Nobody);
|
||||
}, [&](const MTPDprivacyValueDisallowUsers &data) {
|
||||
const auto &users = data.vusers.v;
|
||||
never.reserve(never.size() + users.size());
|
||||
neverUsers.reserve(neverUsers.size() + users.size());
|
||||
for (const auto userId : users) {
|
||||
const auto user = _session->data().user(UserId(userId.v));
|
||||
if (!base::contains(always, user)
|
||||
&& !base::contains(never, user)) {
|
||||
never.push_back(user);
|
||||
if (!base::contains(alwaysUsers, user)
|
||||
&& !base::contains(neverUsers, user)) {
|
||||
neverUsers.push_back(user);
|
||||
}
|
||||
}
|
||||
}, [&](const MTPDprivacyValueDisallowChatParticipants &data) {
|
||||
const auto &chats = data.vchats.v;
|
||||
neverChats.reserve(neverChats.size() + chats.size());
|
||||
for (const auto chatId : chats) {
|
||||
const auto chat = _session->data().chatLoaded(chatId.v);
|
||||
const auto peer = chat
|
||||
? static_cast<PeerData*>(chat)
|
||||
: _session->data().channel(chatId.v);
|
||||
if (!base::contains(alwaysChats, peer)
|
||||
&& !base::contains(neverChats, peer)) {
|
||||
neverChats.emplace_back(peer);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -60,6 +60,30 @@ inline int32 CountHash(IntRange &&range) {
|
||||
|
||||
class ApiWrap : public MTP::Sender, private base::Subscriber {
|
||||
public:
|
||||
struct Privacy {
|
||||
enum class Key {
|
||||
LastSeen,
|
||||
Calls,
|
||||
Invites,
|
||||
CallsPeer2Peer,
|
||||
Forwards,
|
||||
ProfilePhoto,
|
||||
};
|
||||
enum class Option {
|
||||
Everyone,
|
||||
Contacts,
|
||||
Nobody,
|
||||
};
|
||||
Option option = Option::Everyone;
|
||||
std::vector<not_null<UserData*>> alwaysUsers;
|
||||
std::vector<not_null<UserData*>> neverUsers;
|
||||
std::vector<not_null<PeerData*>> alwaysChats;
|
||||
std::vector<not_null<PeerData*>> neverChats;
|
||||
|
||||
static MTPInputPrivacyKey Input(Key key);
|
||||
static std::optional<Key> KeyFromMTP(mtpTypeId type);
|
||||
};
|
||||
|
||||
ApiWrap(not_null<AuthSession*> session);
|
||||
|
||||
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
|
||||
@ -214,8 +238,12 @@ public:
|
||||
void updateNotifySettingsDelayed(not_null<const PeerData*> peer);
|
||||
void saveDraftToCloudDelayed(not_null<History*> history);
|
||||
|
||||
void savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules);
|
||||
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
|
||||
void savePrivacy(
|
||||
const MTPInputPrivacyKey &key,
|
||||
QVector<MTPInputPrivacyRule> &&rules);
|
||||
void handlePrivacyChange(
|
||||
Privacy::Key key,
|
||||
const MTPVector<MTPPrivacyRule> &rules);
|
||||
static int OnlineTillFromStatus(
|
||||
const MTPUserStatus &status,
|
||||
int currentOnlineTill);
|
||||
@ -401,26 +429,6 @@ public:
|
||||
|
||||
void saveSelfBio(const QString &text, FnMut<void()> done);
|
||||
|
||||
struct Privacy {
|
||||
enum class Key {
|
||||
LastSeen,
|
||||
Calls,
|
||||
Invites,
|
||||
CallsPeer2Peer,
|
||||
Forwards,
|
||||
ProfilePhoto,
|
||||
};
|
||||
enum class Option {
|
||||
Everyone,
|
||||
Contacts,
|
||||
Nobody,
|
||||
};
|
||||
Option option = Option::Everyone;
|
||||
std::vector<not_null<UserData*>> always;
|
||||
std::vector<not_null<UserData*>> never;
|
||||
|
||||
static MTPInputPrivacyKey Input(Key key);
|
||||
};
|
||||
void reloadPrivacy(Privacy::Key key);
|
||||
rpl::producer<Privacy> privacyValue(Privacy::Key key);
|
||||
|
||||
|
@ -148,9 +148,6 @@ namespace App {
|
||||
case mtpc_contactLinkContact:
|
||||
user->setContactStatus(UserData::ContactStatus::Contact);
|
||||
break;
|
||||
case mtpc_contactLinkHasPhone:
|
||||
user->setContactStatus(UserData::ContactStatus::CanAdd);
|
||||
break;
|
||||
case mtpc_contactLinkNone:
|
||||
case mtpc_contactLinkUnknown:
|
||||
user->setContactStatus(UserData::ContactStatus::PhoneUnknown);
|
||||
|
@ -142,23 +142,41 @@ void EditPrivacyBox::editExceptionUsers(
|
||||
}
|
||||
|
||||
QVector<MTPInputPrivacyRule> EditPrivacyBox::collectResult() {
|
||||
auto collectInputUsers = [](auto &users) {
|
||||
const auto collectInputUsers = [](const auto &users) {
|
||||
auto result = QVector<MTPInputUser>();
|
||||
result.reserve(users.size());
|
||||
for (auto user : users) {
|
||||
for (const auto user : users) {
|
||||
result.push_back(user->inputUser);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto collectInputChats = [](const auto & chats) {
|
||||
auto result = QVector<MTPint>();
|
||||
result.reserve(chats.size());
|
||||
for (const auto peer : chats) {
|
||||
result.push_back(MTP_int(peer->bareId()));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
constexpr auto kMaxRules = 3; // allow users, disallow users, option
|
||||
auto result = QVector<MTPInputPrivacyRule>();
|
||||
result.reserve(kMaxRules);
|
||||
if (showExceptionLink(Exception::Always) && !_value.always.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.always))));
|
||||
if (showExceptionLink(Exception::Always)) {
|
||||
if (!_value.alwaysUsers.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.alwaysUsers))));
|
||||
}
|
||||
if (!_value.alwaysChats.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueAllowChatParticipants(MTP_vector<MTPint>(collectInputChats(_value.alwaysChats))));
|
||||
}
|
||||
}
|
||||
if (showExceptionLink(Exception::Never) && !_value.never.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.never))));
|
||||
if (showExceptionLink(Exception::Never)) {
|
||||
if (!_value.neverUsers.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.neverUsers))));
|
||||
}
|
||||
if (!_value.neverChats.empty()) {
|
||||
result.push_back(MTP_inputPrivacyValueDisallowChatParticipants(MTP_vector<MTPint>(collectInputChats(_value.neverChats))));
|
||||
}
|
||||
}
|
||||
result.push_back([&] {
|
||||
switch (_value.option) {
|
||||
@ -172,10 +190,11 @@ QVector<MTPInputPrivacyRule> EditPrivacyBox::collectResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// #TODO privacy
|
||||
std::vector<not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception exception) {
|
||||
switch (exception) {
|
||||
case Exception::Always: return _value.always;
|
||||
case Exception::Never: return _value.never;
|
||||
case Exception::Always: return _value.alwaysUsers;
|
||||
case Exception::Never: return _value.neverUsers;
|
||||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
}
|
||||
@ -309,7 +328,8 @@ void EditPrivacyBox::setupContent() {
|
||||
|
||||
addButton(langFactory(lng_settings_save), [=] {
|
||||
const auto someAreDisallowed = (_value.option != Option::Everyone)
|
||||
|| !_value.never.empty();
|
||||
|| !_value.neverUsers.empty()
|
||||
|| !_value.neverChats.empty();
|
||||
_controller->confirmSave(someAreDisallowed, crl::guard(this, [=] {
|
||||
Auth().api().savePrivacy(
|
||||
_controller->apiKey(),
|
||||
|
@ -212,7 +212,7 @@ EntitiesInText ConvertTextTagsToEntities(const TextWithTags::Tags &tags) {
|
||||
push(EntityType::Italic);
|
||||
} else if (tag.id == Ui::InputField::kTagCode) {
|
||||
push(EntityType::Code);
|
||||
} else if (tag.id == Ui::InputField::kTagPre) {
|
||||
} else if (tag.id == Ui::InputField::kTagPre) { // #TODO entities
|
||||
push(EntityType::Pre);
|
||||
} else /*if (ValidateUrl(tag.id)) */{ // We validate when we insert.
|
||||
push(EntityType::CustomUrl, tag.id);
|
||||
@ -247,7 +247,7 @@ TextWithTags::Tags ConvertEntitiesToTextTags(const EntitiesInText &entities) {
|
||||
}
|
||||
} break;
|
||||
case EntityType::Bold: push(Ui::InputField::kTagBold); break;
|
||||
case EntityType::Italic: push(Ui::InputField::kTagItalic); break;
|
||||
case EntityType::Italic: push(Ui::InputField::kTagItalic); break; // #TODO entities
|
||||
case EntityType::Code: push(Ui::InputField::kTagCode); break;
|
||||
case EntityType::Pre: push(Ui::InputField::kTagPre); break;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ for line in lines:
|
||||
templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', restype);
|
||||
if (templ):
|
||||
vectemplate = templ.group(2);
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+_[A-Z]', vectemplate)):
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)):
|
||||
restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'):
|
||||
restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
@ -254,7 +254,7 @@ for line in lines:
|
||||
templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype);
|
||||
if (templ):
|
||||
vectemplate = templ.group(2);
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+_[A-Z]', vectemplate)):
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)):
|
||||
ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'):
|
||||
ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
@ -284,7 +284,7 @@ for line in lines:
|
||||
templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype);
|
||||
if (templ):
|
||||
vectemplate = templ.group(2);
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+_[A-Z]', vectemplate)):
|
||||
if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)):
|
||||
ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'):
|
||||
ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>';
|
||||
|
@ -479,7 +479,7 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
||||
const auto &migratedTo = data.has_migrated_to()
|
||||
? data.vmigrated_to
|
||||
: MTPInputChannel(MTP_inputChannelEmpty());
|
||||
migratedTo.match([&](const MTPDinputChannel &input) {
|
||||
migratedTo.match([&](const MTPDinputChannel & input) {
|
||||
const auto channel = this->channel(input.vchannel_id.v);
|
||||
channel->addFlags(MTPDchannel::Flag::f_megagroup);
|
||||
if (!channel->access) {
|
||||
@ -490,6 +490,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
|
||||
channel->access = input.vaccess_hash.v;
|
||||
}
|
||||
ApplyMigration(chat, channel);
|
||||
}, [](const MTPDinputChannelFromMessage &) {
|
||||
LOG(("API Error: migrated_to contains channel from message."));
|
||||
}, [](const MTPDinputChannelEmpty &) {
|
||||
});
|
||||
|
||||
|
@ -441,6 +441,9 @@ struct ActionSecureValuesSent {
|
||||
struct ActionContactSignUp {
|
||||
};
|
||||
|
||||
struct ActionPhoneNumberRequest {
|
||||
};
|
||||
|
||||
struct ServiceAction {
|
||||
base::optional_variant<
|
||||
ActionChatCreate,
|
||||
@ -462,7 +465,8 @@ struct ServiceAction {
|
||||
ActionCustomAction,
|
||||
ActionBotAllowed,
|
||||
ActionSecureValuesSent,
|
||||
ActionContactSignUp> content;
|
||||
ActionContactSignUp,
|
||||
ActionPhoneNumberRequest> content;
|
||||
};
|
||||
|
||||
ServiceAction ParseServiceAction(
|
||||
@ -487,6 +491,9 @@ struct TextPart {
|
||||
MentionName,
|
||||
Phone,
|
||||
Cashtag,
|
||||
Underline,
|
||||
Strike,
|
||||
Blockquote
|
||||
};
|
||||
Type type = Type::Text;
|
||||
Utf8String text;
|
||||
|
@ -1081,6 +1081,10 @@ void ApiWrap::requestSinglePeerDialog() {
|
||||
)).done(std::move(doneSinglePeer)).send();
|
||||
}, [&](const MTPDinputPeerSelf &data) {
|
||||
requestUser(MTP_inputUserSelf());
|
||||
}, [&](const MTPDinputPeerUserFromMessage &data) {
|
||||
Unexpected("From message peer in ApiWrap::requestSinglePeerDialog.");
|
||||
}, [&](const MTPDinputPeerChannelFromMessage &data) {
|
||||
Unexpected("From message peer in ApiWrap::requestSinglePeerDialog.");
|
||||
}, [](const MTPDinputPeerEmpty &data) {
|
||||
Unexpected("Empty peer in ApiWrap::requestSinglePeerDialog.");
|
||||
});
|
||||
|
@ -283,6 +283,10 @@ QByteArray FormatText(
|
||||
"onclick=\"return ShowCashtag("
|
||||
+ SerializeString('"' + text.mid(1) + '"')
|
||||
+ ")\">" + text + "</a>";
|
||||
case Type::Underline: return "<u>" + text + "</u>";
|
||||
case Type::Strike: return "<s>" + text + "</s>";
|
||||
case Type::Blockquote:
|
||||
return "<blockquote>" + text + "</blockquote>";
|
||||
}
|
||||
Unexpected("Type in text entities serialization.");
|
||||
}) | ranges::to_vector);
|
||||
@ -1082,6 +1086,8 @@ auto HtmlWriter::Wrap::pushMessage(
|
||||
+ SerializeList(list);
|
||||
}, [&](const ActionContactSignUp &data) {
|
||||
return serviceFrom + " joined Telegram";
|
||||
}, [&](const ActionPhoneNumberRequest &data) {
|
||||
return serviceFrom + " requested your phone number";
|
||||
}, [](std::nullopt_t) { return QByteArray(); });
|
||||
|
||||
if (!serviceText.isEmpty()) {
|
||||
|
@ -172,6 +172,9 @@ QByteArray SerializeText(
|
||||
case Type::MentionName: return "mention_name";
|
||||
case Type::Phone: return "phone";
|
||||
case Type::Cashtag: return "cashtag";
|
||||
case Type::Underline: return "underline";
|
||||
case Type::Strike: return "strikethrough";
|
||||
case Type::Blockquote: return "blockquote";
|
||||
}
|
||||
Unexpected("Type in SerializeText.");
|
||||
}();
|
||||
@ -462,6 +465,9 @@ QByteArray SerializeMessage(
|
||||
}, [&](const ActionContactSignUp &data) {
|
||||
pushActor();
|
||||
pushAction("joined_telegram");
|
||||
}, [&](const ActionPhoneNumberRequest &data) {
|
||||
pushActor();
|
||||
pushAction("requested_phone_number");
|
||||
}, [](std::nullopt_t) {});
|
||||
|
||||
if (!message.action.content) {
|
||||
|
@ -335,6 +335,9 @@ QByteArray SerializeMessage(
|
||||
}, [&](const ActionContactSignUp &data) {
|
||||
pushActor();
|
||||
pushAction("Join Telegram");
|
||||
}, [&](const ActionPhoneNumberRequest &data) {
|
||||
pushActor();
|
||||
pushAction("Request Phone Number");
|
||||
}, [](std::nullopt_t) {});
|
||||
|
||||
if (!message.action.content) {
|
||||
|
@ -36,10 +36,14 @@ constexpr auto kMegabyte = 1024 * 1024;
|
||||
PeerId ReadPeerId(const MTPInputPeer &data) {
|
||||
return data.match([](const MTPDinputPeerUser &data) {
|
||||
return peerFromUser(data.vuser_id.v);
|
||||
}, [](const MTPDinputPeerUserFromMessage &data) {
|
||||
return peerFromUser(data.vuser_id.v);
|
||||
}, [](const MTPDinputPeerChat &data) {
|
||||
return peerFromChat(data.vchat_id.v);
|
||||
}, [](const MTPDinputPeerChannel &data) {
|
||||
return peerFromChannel(data.vchannel_id.v);
|
||||
}, [](const MTPDinputPeerChannelFromMessage &data) {
|
||||
return peerFromChannel(data.vchannel_id.v);
|
||||
}, [](const MTPDinputPeerSelf &data) {
|
||||
return Auth().userPeerId();
|
||||
}, [](const MTPDinputPeerEmpty &data) {
|
||||
|
@ -616,6 +616,8 @@ void GenerateItems(
|
||||
createDefaultBannedRights(data);
|
||||
}, [&](const MTPDchannelAdminLogEventActionStopPoll &data) {
|
||||
createStopPoll(data);
|
||||
}, [&](const MTPDchannelAdminLogEventActionChangeLinkedChat &data) {
|
||||
// #TODO discussion
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ not_null<HistoryItem*> CreateUnsupportedMessage(
|
||||
text.entities.push_front(
|
||||
EntityInText(EntityType::Italic, 0, text.text.size()));
|
||||
flags &= ~MTPDmessage::Flag::f_post_author;
|
||||
flags |= MTPDmessage_ClientFlag::f_is_unsupported;
|
||||
flags |= MTPDmessage::Flag::f_legacy;
|
||||
return history->owner().makeMessage(
|
||||
history,
|
||||
msgId,
|
||||
|
@ -618,7 +618,7 @@ bool HistoryMessage::allowsEdit(TimeId now) const {
|
||||
return canStopPoll()
|
||||
&& !isTooOldForEdit(now)
|
||||
&& (!_media || _media->allowsEdit())
|
||||
&& !isUnsupportedMessage()
|
||||
&& !isLegacyMessage()
|
||||
&& !isEditingMedia();
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,8 @@ private:
|
||||
return _flags & MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
}
|
||||
bool isTooOldForEdit(TimeId now) const;
|
||||
bool isUnsupportedMessage() const {
|
||||
return _flags & MTPDmessage_ClientFlag::f_is_unsupported;
|
||||
bool isLegacyMessage() const {
|
||||
return _flags & MTPDmessage::Flag::f_legacy;
|
||||
}
|
||||
|
||||
// For an invoice button we replace the button text with a "Receipt" key.
|
||||
|
@ -4292,7 +4292,36 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
|
||||
case mtpc_updatePrivacy: {
|
||||
auto &d = update.c_updatePrivacy();
|
||||
session().api().handlePrivacyChange(d.vkey.type(), d.vrules);
|
||||
const auto allChatsLoaded = [&](const MTPVector<MTPint> &ids) {
|
||||
for (const auto &chatId : ids.v) {
|
||||
if (!session().data().chatLoaded(chatId.v)
|
||||
&& !session().data().channelLoaded(chatId.v)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const auto allLoaded = [&] {
|
||||
for (const auto &rule : d.vrules.v) {
|
||||
const auto loaded = rule.match([&](
|
||||
const MTPDprivacyValueAllowChatParticipants & data) {
|
||||
return allChatsLoaded(data.vchats);
|
||||
}, [&](const MTPDprivacyValueDisallowChatParticipants & data) {
|
||||
return allChatsLoaded(data.vchats);
|
||||
}, [](auto &&) { return true; });
|
||||
if (!loaded) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (const auto key = ApiWrap::Privacy::KeyFromMTP(d.vkey.type())) {
|
||||
if (allLoaded()) {
|
||||
session().api().handlePrivacyChange(*key, d.vrules);
|
||||
} else {
|
||||
session().api().reloadPrivacy(*key);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updatePinnedDialogs: {
|
||||
|
@ -69,11 +69,8 @@ enum class MTPDmessage_ClientFlag : uint32 {
|
||||
// message has an admin badge in supergroup
|
||||
f_has_admin_badge = (1U << 20),
|
||||
|
||||
// message is unsupported by a current version of client
|
||||
f_is_unsupported = (1U << 19),
|
||||
|
||||
// update this when adding new client side flags
|
||||
MIN_FIELD = (1U << 19),
|
||||
MIN_FIELD = (1U << 20),
|
||||
};
|
||||
DEFINE_MTP_CLIENT_FLAGS(MTPDmessage)
|
||||
|
||||
|
@ -102,10 +102,10 @@ void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
|
||||
key
|
||||
) | rpl::map([=](const Privacy &value) {
|
||||
auto add = QStringList();
|
||||
if (const auto never = value.never.size()) {
|
||||
if (const auto never = value.neverUsers.size()) { // #TODO privacy
|
||||
add.push_back("-" + QString::number(never));
|
||||
}
|
||||
if (const auto always = value.always.size()) {
|
||||
if (const auto always = value.alwaysUsers.size()) {
|
||||
add.push_back("+" + QString::number(always));
|
||||
}
|
||||
if (!add.isEmpty()) {
|
||||
|
@ -4715,14 +4715,14 @@ void WriteExportSettings(const Export::Settings &settings) {
|
||||
<< quint32(settings.format)
|
||||
<< settings.path
|
||||
<< quint32(settings.availableAt);
|
||||
settings.singlePeer.match([&](const MTPDinputPeerUser &user) {
|
||||
settings.singlePeer.match([&](const MTPDinputPeerUser & user) {
|
||||
data.stream
|
||||
<< kSinglePeerTypeUser
|
||||
<< qint32(user.vuser_id.v)
|
||||
<< quint64(user.vaccess_hash.v);
|
||||
}, [&](const MTPDinputPeerChat &chat) {
|
||||
}, [&](const MTPDinputPeerChat & chat) {
|
||||
data.stream << kSinglePeerTypeChat << qint32(chat.vchat_id.v);
|
||||
}, [&](const MTPDinputPeerChannel &channel) {
|
||||
}, [&](const MTPDinputPeerChannel & channel) {
|
||||
data.stream
|
||||
<< kSinglePeerTypeChannel
|
||||
<< qint32(channel.vchannel_id.v)
|
||||
@ -4731,6 +4731,10 @@ void WriteExportSettings(const Export::Settings &settings) {
|
||||
data.stream << kSinglePeerTypeSelf;
|
||||
}, [&](const MTPDinputPeerEmpty &) {
|
||||
data.stream << kSinglePeerTypeEmpty;
|
||||
}, [&](const MTPDinputPeerUserFromMessage &) {
|
||||
Unexpected("From message peer in single peer export settings.");
|
||||
}, [&](const MTPDinputPeerChannelFromMessage &) {
|
||||
Unexpected("From message peer in single peer export settings.");
|
||||
});
|
||||
data.stream << qint32(settings.singlePeerFrom);
|
||||
data.stream << qint32(settings.singlePeerTill);
|
||||
|
@ -12,18 +12,35 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/cache/storage_cache_types.h"
|
||||
#include "storage/serialize_common.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "base/overload.h"
|
||||
#include "auth_session.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kDocumentBaseCacheTag = 0x0000000000010000ULL;
|
||||
constexpr auto kDocumentBaseCacheMask = 0x000000000000FF00ULL;
|
||||
constexpr auto kSerializeTypeShift = quint8(0x08);
|
||||
|
||||
MTPInputPeer GenerateInputPeer(uint64 id, uint64 accessHash, int32 self) {
|
||||
MTPInputPeer GenerateInputPeer(
|
||||
uint64 id,
|
||||
uint64 accessHash,
|
||||
int32 inMessagePeerId,
|
||||
int32 inMessageId,
|
||||
int32 self) {
|
||||
const auto bareId = [&] {
|
||||
return peerToBareMTPInt(id);
|
||||
};
|
||||
if (!id) {
|
||||
if (inMessagePeerId > 0 && inMessageId) {
|
||||
return MTP_inputPeerUserFromMessage(
|
||||
GenerateInputPeer(id, accessHash, 0, 0, self),
|
||||
MTP_int(inMessageId),
|
||||
MTP_int(inMessagePeerId));
|
||||
} else if (inMessagePeerId < 0 && inMessageId) {
|
||||
return MTP_inputPeerChannelFromMessage(
|
||||
GenerateInputPeer(id, accessHash, 0, 0, self),
|
||||
MTP_int(inMessageId),
|
||||
MTP_int(-inMessagePeerId));
|
||||
} else if (!id) {
|
||||
return MTP_inputPeerEmpty();
|
||||
} else if (id == peerFromUser(self)) {
|
||||
return MTP_inputPeerSelf();
|
||||
@ -98,19 +115,36 @@ StorageFileLocation::StorageFileLocation(
|
||||
: data.vthumb_size.v[0];
|
||||
}, [&](const MTPDinputPeerPhotoFileLocation &data) {
|
||||
_type = Type::PeerPhoto;
|
||||
data.vpeer.match([&](const MTPDinputPeerEmpty &data) {
|
||||
const auto fillPeer = base::overload([&](
|
||||
const MTPDinputPeerEmpty &data) {
|
||||
_id = 0;
|
||||
}, [&](const MTPDinputPeerSelf &data) {
|
||||
}, [&](const MTPDinputPeerSelf & data) {
|
||||
_id = peerFromUser(self);
|
||||
}, [&](const MTPDinputPeerChat &data) {
|
||||
}, [&](const MTPDinputPeerChat & data) {
|
||||
_id = peerFromChat(data.vchat_id);
|
||||
}, [&](const MTPDinputPeerUser &data) {
|
||||
}, [&](const MTPDinputPeerUser & data) {
|
||||
_id = peerFromUser(data.vuser_id);
|
||||
_accessHash = data.vaccess_hash.v;
|
||||
}, [&](const MTPDinputPeerChannel &data) {
|
||||
}, [&](const MTPDinputPeerChannel & data) {
|
||||
_id = peerFromChannel(data.vchannel_id);
|
||||
_accessHash = data.vaccess_hash.v;
|
||||
});
|
||||
data.vpeer.match(fillPeer, [&](
|
||||
const MTPDinputPeerUserFromMessage &data) {
|
||||
data.vpeer.match(fillPeer, [&](auto &&) {
|
||||
// Bad data provided.
|
||||
_id = _accessHash = 0;
|
||||
});
|
||||
_inMessagePeerId = data.vuser_id.v;
|
||||
_inMessageId = data.vmsg_id.v;
|
||||
}, [&](const MTPDinputPeerChannelFromMessage &data) {
|
||||
data.vpeer.match(fillPeer, [&](auto &&) {
|
||||
// Bad data provided.
|
||||
_id = _accessHash = 0;
|
||||
});
|
||||
_inMessagePeerId = -data.vchannel_id.v;
|
||||
_inMessageId = data.vmsg_id.v;
|
||||
});
|
||||
_volumeId = data.vvolume_id.v;
|
||||
_localId = data.vlocal_id.v;
|
||||
_sizeLetter = data.is_big() ? 'c' : 'a';
|
||||
@ -195,7 +229,12 @@ MTPInputFileLocation StorageFileLocation::tl(int32 self) const {
|
||||
MTP_flags((_sizeLetter == 'c')
|
||||
? MTPDinputPeerPhotoFileLocation::Flag::f_big
|
||||
: MTPDinputPeerPhotoFileLocation::Flag(0)),
|
||||
GenerateInputPeer(_id, _accessHash, self),
|
||||
GenerateInputPeer(
|
||||
_id,
|
||||
_accessHash,
|
||||
_inMessagePeerId,
|
||||
_inMessageId,
|
||||
self),
|
||||
MTP_long(_volumeId),
|
||||
MTP_int(_localId));
|
||||
|
||||
@ -219,12 +258,14 @@ QByteArray StorageFileLocation::serialize() const {
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
stream
|
||||
<< quint16(_dcId)
|
||||
<< quint8(_type)
|
||||
<< (kSerializeTypeShift | quint8(_type))
|
||||
<< quint8(_sizeLetter)
|
||||
<< qint32(_localId)
|
||||
<< quint64(_id)
|
||||
<< quint64(_accessHash)
|
||||
<< quint64(_volumeId)
|
||||
<< qint32(_inMessagePeerId)
|
||||
<< qint32(_inMessageId)
|
||||
<< _fileReference;
|
||||
}
|
||||
return result;
|
||||
@ -232,12 +273,12 @@ QByteArray StorageFileLocation::serialize() const {
|
||||
|
||||
int StorageFileLocation::serializeSize() const {
|
||||
return valid()
|
||||
? int(sizeof(uint64) * 4 + Serialize::bytearraySize(_fileReference))
|
||||
? int(sizeof(uint64) * 5 + Serialize::bytearraySize(_fileReference))
|
||||
: 0;
|
||||
}
|
||||
|
||||
std::optional<StorageFileLocation> StorageFileLocation::FromSerialized(
|
||||
const QByteArray &serialized) {
|
||||
const QByteArray &serialized) {
|
||||
if (serialized.isEmpty()) {
|
||||
return StorageFileLocation();
|
||||
}
|
||||
@ -249,6 +290,8 @@ std::optional<StorageFileLocation> StorageFileLocation::FromSerialized(
|
||||
quint64 id = 0;
|
||||
quint64 accessHash = 0;
|
||||
quint64 volumeId = 0;
|
||||
qint32 inMessagePeerId = 0;
|
||||
qint32 inMessageId = 0;
|
||||
QByteArray fileReference;
|
||||
auto stream = QDataStream(serialized);
|
||||
stream.setVersion(QDataStream::Qt_5_1);
|
||||
@ -259,8 +302,12 @@ std::optional<StorageFileLocation> StorageFileLocation::FromSerialized(
|
||||
>> localId
|
||||
>> id
|
||||
>> accessHash
|
||||
>> volumeId
|
||||
>> fileReference;
|
||||
>> volumeId;
|
||||
if (type & kSerializeTypeShift) {
|
||||
type &= ~kSerializeTypeShift;
|
||||
stream >> inMessagePeerId >> inMessageId;
|
||||
}
|
||||
stream >> fileReference;
|
||||
|
||||
auto result = StorageFileLocation();
|
||||
result._dcId = dcId;
|
||||
@ -270,6 +317,8 @@ std::optional<StorageFileLocation> StorageFileLocation::FromSerialized(
|
||||
result._id = id;
|
||||
result._accessHash = accessHash;
|
||||
result._volumeId = volumeId;
|
||||
result._inMessagePeerId = inMessagePeerId;
|
||||
result._inMessageId = inMessageId;
|
||||
result._fileReference = fileReference;
|
||||
return (stream.status() == QDataStream::Ok && result.valid())
|
||||
? std::make_optional(result)
|
||||
|
@ -107,6 +107,8 @@ private:
|
||||
uint64 _id = 0;
|
||||
uint64 _accessHash = 0;
|
||||
uint64 _volumeId = 0;
|
||||
uint32 _inMessagePeerId = 0; // > 0 'userId', < 0 '-channelId'.
|
||||
uint32 _inMessageId = 0;
|
||||
QByteArray _fileReference;
|
||||
|
||||
};
|
||||
|
@ -259,7 +259,7 @@ public:
|
||||
startFlags = TextBlockFSemibold;
|
||||
} else if (type == EntityType::Italic) {
|
||||
startFlags = TextBlockFItalic;
|
||||
} else if (type == EntityType::Code) {
|
||||
} else if (type == EntityType::Code) { // #TODO entities
|
||||
startFlags = TextBlockFCode;
|
||||
} else if (type == EntityType::Pre) {
|
||||
startFlags = TextBlockFPre;
|
||||
@ -538,7 +538,7 @@ public:
|
||||
if (((type == EntityType::Mention || type == EntityType::MentionName) && !parseMentions) ||
|
||||
(type == EntityType::Hashtag && !parseHashtags) ||
|
||||
(type == EntityType::Cashtag && !parseHashtags) ||
|
||||
(type == EntityType::BotCommand && !parseBotCommands) ||
|
||||
(type == EntityType::BotCommand && !parseBotCommands) || // #TODO entities
|
||||
((type == EntityType::Bold || type == EntityType::Italic || type == EntityType::Code || type == EntityType::Pre) && !parseMarkdown)) {
|
||||
continue;
|
||||
}
|
||||
@ -3077,7 +3077,7 @@ TextForMimeData Text::toText(
|
||||
? std::vector<MarkdownTagTracker>{
|
||||
{ TextBlockFItalic, EntityType::Italic },
|
||||
{ TextBlockFSemibold, EntityType::Bold },
|
||||
{ TextBlockFCode, EntityType::Code },
|
||||
{ TextBlockFCode, EntityType::Code }, // #TODO entities
|
||||
{ TextBlockFPre, EntityType::Pre }
|
||||
} : std::vector<MarkdownTagTracker>();
|
||||
const auto flagsChangeCallback = [&](int32 oldFlags, int32 newFlags) {
|
||||
|
@ -1322,7 +1322,7 @@ bool CutPart(TextWithEntities &sending, TextWithEntities &left, int32 limit) {
|
||||
if (s > half) {
|
||||
bool inEntity = (currentEntity < entityCount) && (ch > start + left.entities[currentEntity].offset()) && (ch < start + left.entities[currentEntity].offset() + left.entities[currentEntity].length());
|
||||
EntityType entityType = (currentEntity < entityCount) ? left.entities[currentEntity].type() : EntityType::Invalid;
|
||||
bool canBreakEntity = (entityType == EntityType::Pre || entityType == EntityType::Code);
|
||||
bool canBreakEntity = (entityType == EntityType::Pre || entityType == EntityType::Code); // #TODO entities
|
||||
int32 noEntityLevel = inEntity ? 0 : 1;
|
||||
|
||||
auto markGoodAsLevel = [&](int newLevel) {
|
||||
@ -1502,6 +1502,7 @@ EntitiesInText EntitiesFromMTP(const QVector<MTPMessageEntity> &entities) {
|
||||
case mtpc_messageEntityItalic: { auto &d = entity.c_messageEntityItalic(); result.push_back({ EntityType::Italic, d.voffset.v, d.vlength.v }); } break;
|
||||
case mtpc_messageEntityCode: { auto &d = entity.c_messageEntityCode(); result.push_back({ EntityType::Code, d.voffset.v, d.vlength.v }); } break;
|
||||
case mtpc_messageEntityPre: { auto &d = entity.c_messageEntityPre(); result.push_back({ EntityType::Pre, d.voffset.v, d.vlength.v, Clean(qs(d.vlanguage)) }); } break;
|
||||
// #TODO entities
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1516,7 +1517,7 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(const EntitiesInText &entities, Conver
|
||||
if (option == ConvertOption::SkipLocal
|
||||
&& entity.type() != EntityType::Bold
|
||||
&& entity.type() != EntityType::Italic
|
||||
&& entity.type() != EntityType::Code
|
||||
&& entity.type() != EntityType::Code // #TODO entities
|
||||
&& entity.type() != EntityType::Pre
|
||||
&& entity.type() != EntityType::MentionName
|
||||
&& entity.type() != EntityType::CustomUrl) {
|
||||
@ -1549,7 +1550,7 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(const EntitiesInText &entities, Conver
|
||||
case EntityType::BotCommand: v.push_back(MTP_messageEntityBotCommand(offset, length)); break;
|
||||
case EntityType::Bold: v.push_back(MTP_messageEntityBold(offset, length)); break;
|
||||
case EntityType::Italic: v.push_back(MTP_messageEntityItalic(offset, length)); break;
|
||||
case EntityType::Code: v.push_back(MTP_messageEntityCode(offset, length)); break;
|
||||
case EntityType::Code: v.push_back(MTP_messageEntityCode(offset, length)); break; // #TODO entities
|
||||
case EntityType::Pre: v.push_back(MTP_messageEntityPre(offset, length, MTP_string(entity.data()))); break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user