From 32241423ab2783930e1d1e5ba64a67709cf20b9b Mon Sep 17 00:00:00 2001 From: Green Sky Date: Mon, 19 Feb 2024 15:32:57 +0100 Subject: [PATCH] make new contacts merge with preexisting empty contacts (by ID) --- .../tox_contacts/tox_contact_model2.cpp | 208 ++++++++++++------ 1 file changed, 137 insertions(+), 71 deletions(-) diff --git a/solanaceae/tox_contacts/tox_contact_model2.cpp b/solanaceae/tox_contacts/tox_contact_model2.cpp index 248a47b..9d29c9a 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.cpp +++ b/solanaceae/tox_contacts/tox_contact_model2.cpp @@ -37,6 +37,7 @@ ToxContactModel2::ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProvid _cr.emplace(c, this); _cr.emplace(c); _cr.emplace(c, _t.toxSelfGetName()); + // TODO: can contact with id preexist here? _cr.emplace(c, _t.toxSelfGetPublicKey()); _friend_self = c; @@ -153,16 +154,26 @@ Contact3Handle ToxContactModel2::getContactFriend(uint32_t friend_number) { return {_cr, c}; } - // else, new ent - c = _cr.create(); + // check for id (empty contact) and merge + for (const auto e : _cr.view()) { + if (f_key_opt.value() == _cr.get(e).data) { + c = e; + break; + } + } - _cr.emplace(c); - _cr.emplace(c, this); - _cr.emplace(c, friend_number); - _cr.emplace(c, f_key); - _cr.emplace(c, f_key_opt.value()); - _cr.emplace(c, _friend_self); - _cr.emplace(c, _t.toxFriendGetName(friend_number).value_or("")); + if (!_cr.valid(c)) { + // else, new ent + c = _cr.create(); + _cr.emplace(c, f_key_opt.value()); + } + + _cr.emplace_or_replace(c); + _cr.emplace_or_replace(c, this); + _cr.emplace_or_replace(c, friend_number); + _cr.emplace_or_replace(c, f_key); + _cr.emplace_or_replace(c, _friend_self); + _cr.emplace_or_replace(c, _t.toxFriendGetName(friend_number).value_or("")); std::cout << "TCM2: created friend contact " << friend_number << "\n"; @@ -206,17 +217,27 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { return {_cr, c}; } - // else, new ent - c = _cr.create(); + // check for id (empty contact) and merge + for (const auto e : _cr.view()) { + if (g_key_opt.value() == _cr.get(e).data) { + c = e; + break; + } + } - _cr.emplace(c, this); - _cr.emplace(c); - _cr.emplace(c); // start empty - _cr.emplace(c, group_number); - _cr.emplace(c, g_key); - _cr.emplace(c, g_key_opt.value()); - _cr.emplace(c, _t.toxGroupGetName(group_number).value_or("")); - _cr.emplace( + if (!_cr.valid(c)) { + // else, new ent + c = _cr.create(); + _cr.emplace(c, g_key_opt.value()); + } + + _cr.emplace_or_replace(c, this); + _cr.emplace_or_replace(c); + _cr.emplace_or_replace(c); // start empty + _cr.emplace_or_replace(c, group_number); + _cr.emplace_or_replace(c, g_key); + _cr.emplace_or_replace(c, _t.toxGroupGetName(group_number).value_or("")); + _cr.emplace_or_replace( c, _t.toxGroupIsConnected(group_number).value_or(false) ? Contact::Components::ConnectionState::State::cloud @@ -224,7 +245,7 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { ); // TODO: remove and add OnNewContact - _cr.emplace(c, + _cr.emplace_or_replace(c, [](Message3Handle lh, Message3Handle rh) -> bool { if (!lh.all_of() || !rh.all_of()) { return false; // cant compare @@ -255,7 +276,7 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { auto self_opt = _t.toxGroupSelfGetPeerId(group_number); if (self_opt.has_value()) { - _cr.emplace(c, getContactGroupPeer(group_number, self_opt.value())); + _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_opt.value())); } else { std::cerr << "TCM2 error: getting self for group" << group_number << "!!\n"; } @@ -316,32 +337,42 @@ Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, uint return {_cr, c}; } - // else, new ent - c = _cr.create(); + // check for id (empty contact) and merge + for (const auto e : _cr.view()) { + if (g_p_key_opt.value() == _cr.get(e).data) { + c = e; + break; + } + } - _cr.emplace(c, group_c); + if (!_cr.valid(c)) { + // else, new ent + c = _cr.create(); + _cr.emplace(c, g_p_key_opt.value()); + } + + _cr.emplace_or_replace(c, group_c); { // add sub to parent auto& parent_sub_list = group_c.get_or_emplace().subs; if (std::find(parent_sub_list.cbegin(), parent_sub_list.cend(), c) == parent_sub_list.cend()) { parent_sub_list.push_back(c); } } - _cr.emplace(c, this); - _cr.emplace(c, group_number, peer_number); - _cr.emplace(c, g_key, g_p_key); - _cr.emplace(c, g_p_key_opt.value()); + _cr.emplace_or_replace(c, this); + _cr.emplace_or_replace(c, group_number, peer_number); + _cr.emplace_or_replace(c, g_key, g_p_key); const auto name_opt = std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)); if (name_opt.has_value()) { - _cr.emplace(c, name_opt.value()); + _cr.emplace_or_replace(c, name_opt.value()); } { // self // TODO: this is very flaky auto self_number_opt = _t.toxGroupSelfGetPeerId(group_number); if (peer_number == self_number_opt.value()) { - _cr.emplace(c); + _cr.emplace_or_replace(c); } else { - _cr.emplace(c, getContactGroupPeer(group_number, self_number_opt.value())); + _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); } } @@ -378,27 +409,38 @@ Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, cons } // TODO: maybe not create contacts via history sync - // else, new ent - c = _cr.create(); + // check for id (empty contact) and merge + const std::vector peer_key_vec{peer_key.data.cbegin(), peer_key.data.cend()}; + for (const auto e : _cr.view()) { + if (peer_key_vec == _cr.get(e).data) { + c = e; + break; + } + } - _cr.emplace(c, group_c); + if (!_cr.valid(c)) { + // else, new ent + c = _cr.create(); + _cr.emplace(c, peer_key_vec); + } + + _cr.emplace_or_replace(c, group_c); { // add sub to parent auto& parent_sub_list = group_c.get_or_emplace().subs; if (std::find(parent_sub_list.cbegin(), parent_sub_list.cend(), c) == parent_sub_list.cend()) { parent_sub_list.push_back(c); } } - _cr.emplace(c, this); - //_cr.emplace(c, group_number, peer_number); - _cr.emplace(c, g_key, peer_key); - _cr.emplace(c, std::vector{peer_key.data.cbegin(), peer_key.data.cend()}); - //_cr.emplace(c, ""); - //_cr.emplace(c, std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)).value_or("")); + _cr.emplace_or_replace(c, this); + //_cr.emplace_or_replace(c, group_number, peer_number); + _cr.emplace_or_replace(c, g_key, peer_key); + //_cr.emplace_or_replace(c, ""); + //_cr.emplace_or_replace(c, std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)).value_or("")); { // self // TODO: this is very flaky auto self_number_opt = _t.toxGroupSelfGetPeerId(group_number); - _cr.emplace(c, getContactGroupPeer(group_number, self_number_opt.value())); + _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); } std::cout << "TCM2: created group peer contact via pubkey " << group_number << "\n"; @@ -464,20 +506,32 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Request* e) { _cr.remove(c); std::cout << "TCM2: marked friend contact as requested\n"; - } else { + return false; // return false, so tox_message can handle the message + } + + // check for id (empty contact) and merge + const std::vector pub_key_vec{pub_key.data.cbegin(), pub_key.data.cend()}; + for (const auto e : _cr.view()) { + if (pub_key_vec == _cr.get(e).data) { + c = e; + break; + } + } + + if (!_cr.valid(c)) { // else, new ent c = _cr.create(); - - _cr.emplace(c); - _cr.emplace(c); - _cr.emplace(c, this); - _cr.emplace(c, pub_key); - _cr.emplace(c, std::vector{pub_key.data.cbegin(), pub_key.data.cend()}); - _cr.emplace(c, _friend_self); - - std::cout << "TCM2: created friend contact (requested)\n"; + _cr.emplace(c, pub_key_vec); } + _cr.emplace_or_replace(c); + _cr.emplace_or_replace(c); + _cr.emplace_or_replace(c, this); + _cr.emplace_or_replace(c, pub_key); + _cr.emplace_or_replace(c, _friend_self); + + std::cout << "TCM2: created friend contact (requested)\n"; + return false; // return false, so tox_message can handle the message } @@ -504,30 +558,42 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Invite* e) { if (_cr.valid(c)) { std::cout << "TCM2: already in group from invite\n"; - } else { + return false; + } + + // check for id (empty contact) and merge + const std::vector chat_id_vec{chat_id.data.cbegin(), chat_id.data.cend()}; + for (const auto e : _cr.view()) { + if (chat_id_vec == _cr.get(e).data) { + c = e; + break; + } + } + + if (!_cr.valid(c)) { // else, new ent c = _cr.create(); - - _cr.emplace(c, true, true); - _cr.emplace(c); - _cr.emplace(c, this); - _cr.emplace(c, chat_id); - _cr.emplace(c, std::vector{chat_id.data.cbegin(), chat_id.data.cend()}); - _cr.emplace(c, std::string(group_name)); - - auto& ir = _cr.emplace(c); - ir.friend_number = tox_event_group_invite_get_friend_number(e); - ir.invite_data = { - tox_event_group_invite_get_invite_data(e), - tox_event_group_invite_get_invite_data(e) + tox_event_group_invite_get_invite_data_length(e) - }; - - // TODO: self - //_cr.emplace(c, _friend_self); - - std::cout << "TCM2: created group contact (requested)\n"; + _cr.emplace(c, chat_id_vec); } + _cr.emplace_or_replace(c, true, true); + _cr.emplace_or_replace(c); + _cr.emplace_or_replace(c, this); + _cr.emplace_or_replace(c, chat_id); + _cr.emplace_or_replace(c, std::string(group_name)); + + auto& ir = _cr.emplace(c); + ir.friend_number = tox_event_group_invite_get_friend_number(e); + ir.invite_data = { + tox_event_group_invite_get_invite_data(e), + tox_event_group_invite_get_invite_data(e) + tox_event_group_invite_get_invite_data_length(e) + }; + + // TODO: self + //_cr.emplace(c, _friend_self); + + std::cout << "TCM2: created group contact (requested)\n"; + return false; }