Update API scheme to layer 100.

This commit is contained in:
John Preston 2019-05-20 16:57:25 +02:00
parent 68fb9b8b67
commit c4aac5fa0e
26 changed files with 325 additions and 169 deletions

View File

@ -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

View File

@ -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);
}
}
});

View File

@ -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);

View File

@ -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);

View File

@ -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(),

View File

@ -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;
}

View File

@ -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('.', '_') + '>';

View File

@ -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 &) {
});

View File

@ -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;

View File

@ -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.");
});

View File

@ -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()) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -616,6 +616,8 @@ void GenerateItems(
createDefaultBannedRights(data);
}, [&](const MTPDchannelAdminLogEventActionStopPoll &data) {
createStopPoll(data);
}, [&](const MTPDchannelAdminLogEventActionChangeLinkedChat &data) {
// #TODO discussion
});
}

View File

@ -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,

View File

@ -618,7 +618,7 @@ bool HistoryMessage::allowsEdit(TimeId now) const {
return canStopPoll()
&& !isTooOldForEdit(now)
&& (!_media || _media->allowsEdit())
&& !isUnsupportedMessage()
&& !isLegacyMessage()
&& !isEditingMedia();
}

View File

@ -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.

View File

@ -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: {

View File

@ -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)

View File

@ -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()) {

View File

@ -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);

View File

@ -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)

View File

@ -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;
};

View File

@ -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) {

View File

@ -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;
}
}