// SPDX-FileCopyrightText: 2024 Yury Gubich // SPDX-License-Identifier: GPL-3.0-or-later #include "router.h" #include "module/module.h" #include "connection/connection.h" Router::Router(const Shared::Logger& logger): Shared::Loggable(logger, {"Router"}), modules(), actors(), defaultGroup("Stranger"), responses({ {Shared::forbidden, { "Forbidden" }}, {Shared::error, { "Command error" }}, {Shared::unhandled, { "No such command" }}, }), generator(std::random_device{}()) {} void Router::registerModule(const std::string& key, const std::shared_ptr& module) { modules[key] = module; } void Router::registerActor(const std::string& key, const std::string& group) { if (key == "default") { defaultGroup = group; return; } Actors::iterator act = actors.find(key); if (act == actors.end()) actors.emplace(key, std::make_shared(key, group)); else act->second->setGroup(group); } void Router::routeMessage(const std::string& sender, const std::string& body) { Actors::iterator aItr = actors.find(sender); if (aItr == actors.end()) aItr = actors.emplace(sender, std::make_shared(sender, defaultGroup)).first; std::vector args = Module::Module::split(body); std::string moduleAlias = Module::Module::lower(args[0]); Modules::iterator mItr = modules.find(moduleAlias); if (mItr == modules.end()) { debug("could not find module \"" + moduleAlias + "\" to handle message from " + sender); return onMessageResult(Shared::unhandled, sender); } std::shared_ptr module = mItr->second.lock(); if (!module) { error("could not lock module \"" + mItr->first + "\" to handle message from " + sender); return onMessageResult(Shared::error, sender); } args.erase(args.begin()); Shared::Result result; try { result = module->message(aItr->second, args); if (result == Shared::success) debug("module \"" + mItr->first + "\" successfully handled message from " + sender); } catch (...) { error("module \"" + mItr->first + "\" thew an unhandled exception handling message from " + sender); result = Shared::error; } onMessageResult(result, sender); } std::map Router::getActors() const { std::map result; for (const std::pair>& pair : actors) result.emplace(pair.first, pair.second->getGroup()); return result; } std::string Router::getDefaultGroup() const { return defaultGroup; } void Router::setConnection(const std::shared_ptr& cn) { connection = cn; } void Router::setResponses(Shared::Result result, const Shared::Strings& options) { responses[result] = options; } std::string Router::getGroup(const std::string& key) const { Actors::const_iterator itr = actors.find(key); if (itr == actors.end()) return defaultGroup; return itr->second->getGroup(); } void Router::onMessageResult(Shared::Result result, const std::string& sender) { Responses::const_iterator rItr = responses.find(result); if (rItr == responses.end() || rItr->second.empty()) return; std::shared_ptr cn = connection.lock(); if (!cn) { warn("Couldn't send a message to " + sender + ", connection is not available"); return; } const List& options = rItr->second; std::uniform_int_distribution dist(0, options.size() - 1); cn->send(sender, options[dist(generator)]); }