// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "service-db/DBServiceAPI.hpp" #include "service-db/DBThreadMessage.hpp" #include "service-db/DBSMSMessage.hpp" #include "service-db/DBSMSTemplateMessage.hpp" #include "service-db/DBContactMessage.hpp" #include "service-db/DBNotesMessage.hpp" #include "service-db/DBCalllogMessage.hpp" #include "service-db/DBCountryCodeMessage.hpp" #include "service-db/DBServiceMessage.hpp" #include "service-db/QueryMessage.hpp" #include "service-db/DBServiceName.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sys { class Service; } // namespace sys struct NotesRecord; std::unique_ptr DBServiceAPI::ThreadGetByNumber(sys::Service *serv, const utils::PhoneNumber::View &phoneNumber, std::uint32_t timeout) { auto [code, msg] = DBServiceAPI::GetQueryWithReply( serv, db::Interface::Name::SMSThread, std::make_unique(phoneNumber), timeout); if (code == sys::ReturnCodes::Success && msg != nullptr) { auto queryResponse = dynamic_cast(msg.get()); assert(queryResponse != nullptr); auto threadResponse = queryResponse->getResult(); auto threadResult = dynamic_cast(threadResponse.get()); assert(threadResult != nullptr); return std::make_unique(std::move(threadResult->getThread())); } return nullptr; } bool DBServiceAPI::ThreadGetLimitOffset(sys::Service *serv, uint32_t offset, uint32_t limit) { std::shared_ptr msg = std::make_shared(MessageType::DBThreadGetLimitOffset); msg->offset = offset; msg->limit = limit; sys::Bus::SendUnicast(msg, service::name::db, serv); return true; } uint32_t DBServiceAPI::ThreadGetCount(sys::Service *serv, EntryState state) { auto msg = std::make_shared(state); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBThreadResponseMessage *threadResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (threadResponse->retCode == true)) { return threadResponse->count; } else { return false; } } std::unique_ptr> DBServiceAPI::ContactGetByID(sys::Service *serv, uint32_t contactID) { ContactRecord rec; rec.ID = contactID; std::shared_ptr msg = std::make_shared(MessageType::DBContactGetByID, rec); return std::move(ContactGetByIDCommon(serv, std::move(msg))); } std::unique_ptr> DBServiceAPI::ContactGetByIDWithTemporary(sys::Service *serv, uint32_t contactID) { ContactRecord rec; rec.ID = contactID; std::shared_ptr msg = std::make_shared(MessageType::DBContactGetByID, rec); msg->withTemporary = true; return std::move(ContactGetByIDCommon(serv, std::move(msg))); } std::unique_ptr> DBServiceAPI::ContactGetByIDCommon( sys::Service *serv, std::shared_ptr contactMsg) { auto ret = sys::Bus::SendUnicast(contactMsg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return std::move(contactResponse->records); } else { return std::make_unique>(); } } std::unique_ptr> DBServiceAPI::ContactGetBySpeeddial(sys::Service *serv, UTF8 speeddial) { if (speeddial.length() == 0) return std::make_unique>(); ContactRecord rec; rec.speeddial = speeddial; std::shared_ptr msg = std::make_shared(MessageType::DBContactGetBySpeedDial, rec); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return std::move(contactResponse->records); } else { return std::make_unique>(); } } std::unique_ptr> DBServiceAPI::ContactGetByPhoneNumber(sys::Service *serv, UTF8 phoneNumber) { ContactRecord rec; auto number = ContactRecord::Number(utils::PhoneNumber(phoneNumber).getView(), ContactNumberType ::PAGER); rec.numbers.push_back(number); std::shared_ptr msg = std::make_shared(MessageType::DBContactGetByNumber, rec); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); auto *contactResponse = dynamic_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return std::move(contactResponse->records); } else { return std::make_unique>(); } } std::unique_ptr DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, const utils::PhoneNumber::View &numberView) { auto msg = std::make_shared(numberView); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); auto *contactResponse = dynamic_cast(ret.second.get()); assert(contactResponse); return std::move(contactResponse->contact); } DBServiceAPI::ContactVerificationError DBServiceAPI::verifyContact(sys::Service *serv, const ContactRecord &rec) { if (rec.primaryName.length() == 0 && rec.alternativeName.length() == 0 && rec.numbers.empty() && rec.mail.length() == 0 && rec.address.length() == 0 && rec.note.length() == 0) { return emptyContactError; } auto retSpeedDial = ContactGetBySpeeddial(serv, rec.speeddial); if (!retSpeedDial->empty() && (*retSpeedDial)[0].ID != rec.ID) { return speedDialError; } if (rec.numbers.size() > 0 && rec.numbers[0].number.getEntered().size() > 0) { auto retPhone1 = MatchContactByPhoneNumber(serv, rec.numbers[0].number); if (retPhone1 && retPhone1->ID != rec.ID) { return primaryNumberError; } } if (rec.numbers.size() > 1 && rec.numbers[1].number.getEntered().size() > 0) { auto retPhone2 = MatchContactByPhoneNumber(serv, rec.numbers[1].number); if (retPhone2 && retPhone2->ID != rec.ID) { return secondaryNumberError; } } return noError; } std::string DBServiceAPI::getVerificationErrorString(const ContactVerificationError err) { switch (err) { case noError: return "No error occurred"; case emptyContactError: return "Contact record is empty"; case speedDialError: return "Invalid or duplicate speed dial number"; case primaryNumberError: return "Invalid or duplicate primary number"; case secondaryNumberError: return "Invalid or duplicate secondary number"; default: return "Unknown error"; } } bool DBServiceAPI::ContactAdd(sys::Service *serv, const ContactRecord &rec) { std::shared_ptr msg = std::make_shared(MessageType::DBContactAdd, rec); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return true; } else { return false; } } bool DBServiceAPI::ContactRemove(sys::Service *serv, uint32_t id) { std::shared_ptr msg = std::make_shared(MessageType::DBContactRemove); msg->id = id; auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return true; } else { return false; } } bool DBServiceAPI::ContactUpdate(sys::Service *serv, const ContactRecord &rec) { std::shared_ptr msg = std::make_shared(MessageType::DBContactUpdate, rec); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return true; } else { return false; } } std::unique_ptr> DBServiceAPI::ContactSearch(sys::Service *serv, UTF8 primaryName, UTF8 alternativeName, UTF8 number) { std::shared_ptr msg = std::make_shared(MessageType::DBContactSearch, (primaryName.length() > 0) ? primaryName.c_str() : "", (alternativeName.length() > 0) ? alternativeName.c_str() : "", (number.length() > 0) ? number.c_str() : ""); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBContactResponseMessage *contactResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (contactResponse->retCode == true)) { return std::move(contactResponse->records); } else { return std::make_unique>(); } } CalllogRecord DBServiceAPI::CalllogAdd(sys::Service *serv, const CalllogRecord &rec) { std::shared_ptr msg = std::make_shared(MessageType::DBCalllogAdd, rec); LOG_DEBUG("CalllogAdd %s", utils::to_string(rec).c_str()); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBCalllogResponseMessage *calllogResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (calllogResponse->retCode == true)) { auto records = *calllogResponse->records; if (!records.empty()) { return records[0]; } } return CalllogRecord(); } bool DBServiceAPI::CalllogRemove(sys::Service *serv, uint32_t id) { std::shared_ptr msg = std::make_shared(MessageType::DBCalllogRemove); msg->id = id; auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBCalllogResponseMessage *calllogResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (calllogResponse->retCode == true)) { return true; } else { return false; } } bool DBServiceAPI::CalllogUpdate(sys::Service *serv, const CalllogRecord &rec) { std::shared_ptr msg = std::make_shared(MessageType::DBCalllogUpdate, rec); LOG_DEBUG("CalllogUpdate %s", utils::to_string(rec).c_str()); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBCalllogResponseMessage *calllogResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (calllogResponse->retCode == true)) { return true; } else { return false; } } uint32_t DBServiceAPI::CalllogGetCount(sys::Service *serv, EntryState state) { std::shared_ptr msg = std::make_shared(state); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBCalllogResponseMessage *calllogResponse = reinterpret_cast(ret.second.get()); if ((ret.first == sys::ReturnCodes::Success) && (calllogResponse->retCode == true)) { return calllogResponse->count; } else { return 0; } } bool DBServiceAPI::CalllogGetLimitOffset(sys::Service *serv, uint32_t offset, uint32_t limit) { std::shared_ptr msg = std::make_shared(MessageType::DBCalllogGetLimitOffset); msg->offset = offset; msg->limit = limit; sys::Bus::SendUnicast(msg, service::name::db, serv); return true; } uint32_t DBServiceAPI::GetCountryCodeByMCC(sys::Service *serv, uint32_t mcc) { std::shared_ptr msg = std::make_shared(MessageType::DBCountryCode, mcc, 0); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); DBCountryCodeResponseMessage *response = reinterpret_cast(ret.second.get()); if (ret.first == sys::ReturnCodes::Success) { return (response->row.country_code); } else { return (0); } } bool DBServiceAPI::DBBackup(sys::Service *serv, std::string backupPath) { LOG_INFO("DBBackup %s", backupPath.c_str()); std::shared_ptr msg = std::make_shared(MessageType::DBServiceBackup, backupPath); auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs); if (ret.first == sys::ReturnCodes::Success) { return true; } else { LOG_ERROR("DBBackup error, return code: %s", c_str(ret.first)); return false; } }