#include "./tox_avatar_manager.hpp" // TODO: this whole thing needs a rewrite and is currently disabled #include //#include #include // for comp transfer tox filekind (TODO: generalize -> content system?) #include #include #include #include #include #include #include // see https://github.com/Tox/Tox-Client-Standard/blob/master/user_identification/avatar.md // see (old) https://github.com/Tox-Archive/Tox-STS/blob/master/STS.md#avatars // https://youtu.be/_uuCLRqc9QA namespace Components { struct TagAvatarImageHandled {}; }; ToxAvatarManager::ToxAvatarManager( //RegistryMessageModel& rmm, ObjectStore2& os, Contact3Registry& cr, ConfigModelI& conf ) : /*_rmm(rmm)*/ _os(os), _cr(cr), _conf(conf) { _os.subscribe(this, ObjectStore_Event::object_construct); _os.subscribe(this, ObjectStore_Event::object_update); if (!_conf.has_string("ToxAvatarManager", "save_path")) { // or on linux: $HOME/.config/tox/avatars/ _conf.set("ToxAvatarManager", "save_path", std::string_view{"tmp_avatar_dir"}); } //_conf.set("TransferAutoAccept", "autoaccept_limit", int64_t(50l*1024l*1024l)); // sane default const std::string_view avatar_save_path {_conf.get_string("ToxAvatarManager", "save_path").value()}; // make sure it exists std::filesystem::create_directories(avatar_save_path); { // scan tox contacts for cached avatars // old sts says pubkey.png _cr.view().each([this](auto c, const Contact::Components::ToxFriendPersistent& tox_pers) { addAvatarFileToContact(c, tox_pers.key); }); _cr.view().each([this](auto c, const Contact::Components::ToxGroupPersistent& tox_pers) { addAvatarFileToContact(c, tox_pers.chat_id); }); // TODO: also for group peers? // TODO: conf? } } void ToxAvatarManager::iterate(void) { // cancel queue // accept queue for (auto& [o, path] : _accept_queue) { if (o.any_of()) { continue; // already accepted / done } o.emplace(path, true); std::cout << "TAM: auto accepted transfer\n"; _os.throwEventUpdate(o); } _accept_queue.clear(); // - add message/content/transfer listener for onComplete } std::string ToxAvatarManager::getAvatarPath(const ToxKey& key) const { const std::string_view avatar_save_path {_conf.get_string("ToxAvatarManager", "save_path").value()}; const auto pub_key_string = bin2hex({key.data.cbegin(), key.data.cend()}); const auto file_path = std::filesystem::path(avatar_save_path) / (pub_key_string + ".png"); return file_path.generic_u8string(); } void ToxAvatarManager::addAvatarFileToContact(const Contact3 c, const ToxKey& key) { const auto file_path = getAvatarPath(key); if (std::filesystem::is_regular_file(file_path)) { // avatar file png file exists _cr.emplace_or_replace(c, file_path); _cr.emplace_or_replace(c); } } void ToxAvatarManager::clearAvatarFromContact(const Contact3 c) { if (_cr.all_of(c)) { std::filesystem::remove(_cr.get(c).file_path); _cr.remove(c); _cr.emplace_or_replace(c); } } void ToxAvatarManager::checkObj(ObjectHandle o) { if (o.any_of< ObjComp::Ephemeral::File::ActionTransferAccept, Components::TagAvatarImageHandled >()) { return; // already accepted or handled } if (!o.any_of< ObjComp::Ephemeral::File::TagTransferPaused, ObjComp::F::TagLocalHaveAll >()) { // we only handle unaccepted or finished return; } if (!o.all_of< ObjComp::Tox::TagIncomming, //ObjComp::Ephemeral::Backend, ObjComp::F::SingleInfo, ObjComp::Tox::FileKind // TODO: mesage? how do we know where a file is from?? //Message::Components::ContactFrom // should always be there, just making sure >()) { return; } // TCS-2.2.11 (big list, should have been sub points ...) if (o.get().kind != 1) { // not an avatar return; } const auto& file_info = o.get(); //const auto contact = h.get().c; // TCS-2.2.4 if (file_info.file_size > 65536ul) { // TODO: mark handled? return; // too large } #if 0 // TODO: make avatars work again !!!!! // TCS-2.2.10 if (file_info.file_name.empty() || file_info.file_size == 0) { // reset clearAvatarFromContact(contact); // TODO: cancel return; } if (!o.all_of< ObjComp::Tox::FileID >()) { return; } std::string file_path; if (_cr.all_of(contact)) { file_path = getAvatarPath(_cr.get(contact).key); } else if (_cr.all_of(contact)) { file_path = getAvatarPath(_cr.get(contact).chat_id); } else { std::cerr << "TAM error: cant get toxkey for contact\n"; // TODO: mark handled? return; } if (o.all_of()) { std::cout << "TAM: full avatar received\n"; if (_cr.all_of(contact)) { addAvatarFileToContact(contact, _cr.get(contact).key); } else if (_cr.all_of(contact)) { addAvatarFileToContact(contact, _cr.get(contact).chat_id); } else { std::cerr << "TAM error: cant get toxkey for contact\n"; } o.emplace_or_replace(); } else { // check file id for existing hash if (std::filesystem::is_regular_file(file_path)) { //const auto& supposed_file_hash = h.get().id; // load file // hash file //_t.toxHash(); std::filesystem::remove(file_path); // hack, hard replace existing file } std::cout << "TAM: accepted avatar ft\n"; // if not already on disk _accept_queue.push_back(AcceptEntry{o, file_path}); } #endif } bool ToxAvatarManager::onEvent(const ObjectStore::Events::ObjectConstruct& e) { checkObj(e.e); return false; } bool ToxAvatarManager::onEvent(const ObjectStore::Events::ObjectUpdate& e) { checkObj(e.e); return false; }