From a262ab9d3a23cf23169e76dae2c3a3c362285773 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sat, 29 Jul 2023 20:07:22 +0200 Subject: [PATCH] add friend requests and group invites --- solanaceae/tox_contacts/components.hpp | 6 + solanaceae/tox_contacts/components_id.inl | 1 + .../tox_contacts/tox_contact_model2.cpp | 127 ++++++++++++++++++ .../tox_contacts/tox_contact_model2.hpp | 8 ++ 4 files changed, 142 insertions(+) diff --git a/solanaceae/tox_contacts/components.hpp b/solanaceae/tox_contacts/components.hpp index c4fcf71..d46cf82 100644 --- a/solanaceae/tox_contacts/components.hpp +++ b/solanaceae/tox_contacts/components.hpp @@ -42,6 +42,12 @@ namespace Contact::Components { uint32_t group_number; }; + struct ToxGroupIncomingRequest { + //Contact3 friend_c; + uint32_t friend_number; + std::vector invite_data; + }; + struct ToxGroupPeerPersistent { ToxKey chat_id; ToxKey peer_key; diff --git a/solanaceae/tox_contacts/components_id.inl b/solanaceae/tox_contacts/components_id.inl index 5af528e..769bff6 100644 --- a/solanaceae/tox_contacts/components_id.inl +++ b/solanaceae/tox_contacts/components_id.inl @@ -18,6 +18,7 @@ DEFINE_COMP_ID(Contact::Components::ToxConfPersistent) DEFINE_COMP_ID(Contact::Components::ToxConfEhpemeral) DEFINE_COMP_ID(Contact::Components::ToxGroupPersistent) DEFINE_COMP_ID(Contact::Components::ToxGroupEphemeral) +DEFINE_COMP_ID(Contact::Components::ToxGroupIncomingRequest) DEFINE_COMP_ID(Contact::Components::ToxGroupPeerPersistent) DEFINE_COMP_ID(Contact::Components::ToxGroupPeerEphemeral) diff --git a/solanaceae/tox_contacts/tox_contact_model2.cpp b/solanaceae/tox_contacts/tox_contact_model2.cpp index 418898a..1653f4d 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.cpp +++ b/solanaceae/tox_contacts/tox_contact_model2.cpp @@ -13,9 +13,11 @@ ToxContactModel2::ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProvid _tep.subscribe(this, Tox_Event::TOX_EVENT_FRIEND_CONNECTION_STATUS); _tep.subscribe(this, Tox_Event::TOX_EVENT_FRIEND_STATUS); _tep.subscribe(this, Tox_Event::TOX_EVENT_FRIEND_NAME); + _tep.subscribe(this, Tox_Event::TOX_EVENT_FRIEND_REQUEST); // TODO: conf + _tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_INVITE); _tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_SELF_JOIN); _tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_PEER_JOIN); _tep.subscribe(this, Tox_Event::TOX_EVENT_GROUP_PEER_EXIT); @@ -43,6 +45,48 @@ ToxContactModel2::ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProvid } } +void ToxContactModel2::acceptRequest(Contact3 c, std::string_view self_name, std::string_view password) { + assert(!_cr.any_of(c)); + assert(_cr.all_of(c)); + + if (_cr.all_of(c)) { + const auto& key = _cr.get(c).key.data; + auto [friend_number_opt, _] = _t.toxFriendAddNorequest({key.cbegin(), key.cend()}); + if (friend_number_opt.has_value()) { + _cr.emplace(c, friend_number_opt.value()); + _cr.remove(c); + } else { + std::cerr << "TCM2 error: failed to accept friend request/invite\n"; + } + } else if (false) { // conf + } else if (_cr.all_of(c)) { // group + const auto& ir = _cr.get(c); + auto [group_number_opt, _] = _t.toxGroupInviteAccept(ir.friend_number, ir.invite_data, self_name, password); + if (group_number_opt.has_value()) { + _cr.emplace(c, group_number_opt.value()); + + if (auto group_chatid_opt = _t.toxGroupGetChatId(group_number_opt.value()); group_chatid_opt.has_value()) { + _cr.emplace_or_replace(c, group_chatid_opt.value()); + } else { + std::cerr << "TCM2 error: getting chatid for group" << group_number_opt.value() << "!!\n"; + } + + if (auto self_opt = _t.toxGroupSelfGetPeerId(group_number_opt.value()); self_opt.has_value()) { + _cr.emplace_or_replace(c, getContactGroupPeer(group_number_opt.value(), self_opt.value())); + } else { + std::cerr << "TCM2 error: getting self for group" << group_number_opt.value() << "!!\n"; + } + + _cr.remove(c); + _cr.remove(c); + } else { + std::cerr << "TCM2 error: failed to accept group request/invite\n"; + } + } else { + std::cerr << "TCM2 error: failed to accept request (unk)\n"; + } +} + Contact3Handle ToxContactModel2::getContactFriend(uint32_t friend_number) { Contact3 c = entt::null; @@ -326,6 +370,89 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Name* e) { return false; // return true? } +bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Request* e) { + const ToxKey pub_key{tox_event_friend_request_get_public_key(e), TOX_PUBLIC_KEY_SIZE}; + + Contact3 c = entt::null; + + // check for existing + for (const auto e : _cr.view()) { + if (pub_key == _cr.get(e).key) { + c = e; + break; + } + } + + if (_cr.valid(c)) { + _cr.emplace_or_replace(c); + _cr.remove(c); + + std::cout << "TCM2: marked friend contact as requested\n"; + } else { + // else, new ent + c = _cr.create(); + + _cr.emplace(c); + _cr.emplace(c); + _cr.emplace(c, this); + _cr.emplace(c, pub_key); + _cr.emplace(c, _friend_self); + + std::cout << "TCM2: created friend contact (requested)\n"; + } + + return false; // return false, so tox_message can handle the message +} + +bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Invite* e) { + const std::string_view group_name { + reinterpret_cast(tox_event_group_invite_get_group_name(e)), + tox_event_group_invite_get_group_name_length(e) + }; + + // HACK: extract chatid + // TODO: request better api + assert(tox_event_group_invite_get_invite_data_length(e) == TOX_GROUP_CHAT_ID_SIZE + TOX_GROUP_PEER_PUBLIC_KEY_SIZE); + const ToxKey chat_id{tox_event_group_invite_get_invite_data(e), TOX_GROUP_CHAT_ID_SIZE}; + + Contact3 c = entt::null; + + // check for existing + for (const auto e : _cr.view()) { + if (chat_id == _cr.get(e).chat_id) { + c = e; + break; + } + } + + if (_cr.valid(c)) { + std::cout << "TCM2: already in group from invite\n"; + } else { + // 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::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; +} + bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Self_Join* e) { const uint32_t group_number = tox_event_group_self_join_get_group_number(e); if (const auto self_id_opt = _t.toxGroupSelfGetPeerId(group_number); self_id_opt.has_value()) { diff --git a/solanaceae/tox_contacts/tox_contact_model2.hpp b/solanaceae/tox_contacts/tox_contact_model2.hpp index 0da844e..b8a59d2 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.hpp +++ b/solanaceae/tox_contacts/tox_contact_model2.hpp @@ -1,5 +1,6 @@ #pragma once +#include "tox/tox_events.h" #include #include @@ -23,6 +24,11 @@ class ToxContactModel2 : public ContactModel3I, public ToxEventI { // TODO: continually fetch group peer connection state, since JF does not want to add cb/event //void iterate(void); + + protected: // mmi + // accept incoming request + void acceptRequest(Contact3 c, std::string_view self_name, std::string_view password) override; + public: // util for tox code // also creates if non existant Contact3Handle getContactFriend(uint32_t friend_number); @@ -36,7 +42,9 @@ class ToxContactModel2 : public ContactModel3I, public ToxEventI { bool onToxEvent(const Tox_Event_Friend_Connection_Status* e) override; bool onToxEvent(const Tox_Event_Friend_Status* e) override; bool onToxEvent(const Tox_Event_Friend_Name* e) override; + bool onToxEvent(const Tox_Event_Friend_Request* e) override; + bool onToxEvent(const Tox_Event_Group_Invite* e) override; bool onToxEvent(const Tox_Event_Group_Self_Join* e) override; bool onToxEvent(const Tox_Event_Group_Peer_Join* e) override; bool onToxEvent(const Tox_Event_Group_Peer_Exit* e) override;