Module creation, message routing

This commit is contained in:
Blue 2025-03-07 23:20:06 +02:00
parent bc2dc9bf07
commit c605b3ba93
Signed by: blue
GPG Key ID: 9B203B252A63EE38
14 changed files with 154 additions and 26 deletions

View File

@ -3,7 +3,8 @@
#include "actor.h" #include "actor.h"
Actor::Actor(const std::string& group) : Actor::Actor(const std::string& jid, const std::string& group) :
jid(jid),
group(group) group(group)
{} {}

View File

@ -7,10 +7,13 @@
class Actor { class Actor {
public: public:
Actor(const std::string& group); Actor(const std::string& jid, const std::string& group);
void setGroup(const std::string& newGroup); void setGroup(const std::string& newGroup);
public:
const std::string jid;
private: private:
std::string group; std::string group;
}; };

View File

@ -61,3 +61,32 @@ std::map<std::string, std::string> Config::getOwners() const {
bool Config::isValid() const { bool Config::isValid() const {
return !getBareJID().empty() && !getPassword().empty(); return !getBareJID().empty() && !getPassword().empty();
} }
Config::Module Config::getModuleConfig(const std::string& name) const {
YAML::Node modules = root["modules"];
if (!modules || !modules.IsMap())
return { false };
YAML::Node conf = modules[name];
if (!conf || !conf.IsMap())
return { false };
Module result {
conf["enabled"].as<bool>(true),
conf["alias"].as<std::string>(name)
};
YAML::Node prm = conf["permissions"];
if (prm.IsMap()) {
for (const auto& node : prm) {
Module::List& list = result.permissions.emplace(node.first.as<std::string>(), Module::List()).first->second;
YAML::Node lst = node.second;
if (lst.IsSequence())
for (const YAML::Node& member : lst)
list.emplace_back(member.as<std::string>());
}
}
return result;
}

View File

@ -11,6 +11,16 @@
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
class Config { class Config {
public:
struct Module {
typedef std::vector<std::string> List;
typedef std::map<std::string, List> Permissions;
bool enabled;
std::string alias;
Permissions permissions;
};
public: public:
Config(const std::string& path); Config(const std::string& path);
@ -23,6 +33,7 @@ public:
std::map<std::string, std::string> getOwners() const; std::map<std::string, std::string> getOwners() const;
gloox::LogLevel getLogLevel() const; gloox::LogLevel getLogLevel() const;
gloox::TLSPolicy getTLSPolicy() const; gloox::TLSPolicy getTLSPolicy() const;
Module getModuleConfig(const std::string& name) const;
private: private:
YAML::Node root; YAML::Node root;

View File

@ -12,7 +12,6 @@ void Router::registerModule(const std::string& key, const std::shared_ptr<Module
modules[key] = module; modules[key] = module;
} }
void Router::registerActor(const std::string& key, const std::string& group) { void Router::registerActor(const std::string& key, const std::string& group) {
if (key == "default") { if (key == "default") {
defaultGroup = group; defaultGroup = group;
@ -21,10 +20,27 @@ void Router::registerActor(const std::string& key, const std::string& group) {
Actors::iterator act = actors.find(key); Actors::iterator act = actors.find(key);
if (act == actors.end()) if (act == actors.end())
actors.emplace(key, group); actors.emplace(key, std::make_shared<Actor>(key, group));
else else
act->second.setGroup(group); act->second->setGroup(group);
} }
void Router::routeMessage(const std::string& sender, const std::string& body) { 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<Actor>(sender, defaultGroup)).first;
std::vector<std::string> args = Module::Module::split(body);
Modules::iterator mItr = modules.find(args[0]);
if (mItr == modules.end())
return;
std::shared_ptr<Module::Module> module = mItr->second.lock();
if (!module)
return;
args.erase(args.begin());
module->message(aItr->second, args);
} }

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector>
#include <memory> #include <memory>
#include "actor.h" #include "actor.h"
@ -20,7 +21,7 @@ public:
private: private:
typedef std::map<std::string, std::weak_ptr<Module::Module>> Modules; typedef std::map<std::string, std::weak_ptr<Module::Module>> Modules;
typedef std::map<std::string, Actor> Actors; typedef std::map<std::string, std::shared_ptr<Actor>> Actors;
Modules modules; Modules modules;
Actors actors; Actors actors;

View File

@ -1,9 +1,19 @@
logLevel: debug
jid: bot@xmpp.server jid: bot@xmpp.server
password: "supersecret" password: "supersecret"
logLevel: debug
tls: required tls: required
resource: bot resource: bot
actors: actors:
user1@xmpp.server: Owner user1@xmpp.server: Owner
user2@xmpp.server: User user2@xmpp.server: User
default: Stranger default: Stranger
modules:
actor:
alias: actor
enabled: true
permissions:
- read: [Owner, User]
- write: [Owner]

View File

@ -19,13 +19,5 @@ Message::~Message() {
} }
void Message::handleMessage(const gloox::Message& message, gloox::MessageSession* session) { void Message::handleMessage(const gloox::Message& message, gloox::MessageSession* session) {
std::shared_ptr<Config> cfg = config.lock(); callback(message.from().bare(), message.body());
if (!cfg)
return;
if (cfg->getOwners().count(message.from().bare())) {
std::cout << "Received message from owner: " << message.body() << std::endl;
} else {
std::cout << "Received message: " << message.body() << std::endl;
}
} }

19
jay.cpp
View File

@ -3,6 +3,13 @@
#include "jay.h" #include "jay.h"
#include "module/actor.h"
static const std::map<std::string, std::function<std::shared_ptr<Module::Module>(const std::shared_ptr<gloox::Client>)>> moduleNames = {
{"actor", [](const std::shared_ptr<gloox::Client> client) { return std::make_shared<Module::Actor>(client); }}
};
Jay::Jay(const std::string& configPath): Jay::Jay(const std::string& configPath):
runMutex(), runMutex(),
config(std::make_shared<Config>(configPath)), config(std::make_shared<Config>(configPath)),
@ -10,6 +17,7 @@ Jay::Jay(const std::string& configPath):
client(), client(),
messageHandler(), messageHandler(),
connectionHandler(), connectionHandler(),
modules(),
loggers() loggers()
{} {}
@ -40,6 +48,7 @@ void Jay::initialize() {
if (!connectionHandler) if (!connectionHandler)
connectionHandler = std::make_unique<Connection>(config, client); connectionHandler = std::make_unique<Connection>(config, client);
createModules();
createActors(); createActors();
} }
@ -65,6 +74,16 @@ void Jay::createActors() {
router->registerActor(pair.first, pair.second); router->registerActor(pair.first, pair.second);
} }
void Jay::createModules() {
for (const auto& pair : moduleNames) {
Config::Module conf = config->getModuleConfig(pair.first);
if (!conf.enabled)
continue;
modules.emplace_back(pair.second(client));
router->registerModule(pair.first, modules.back());
}
}
void Jay::addLogger(gloox::LogLevel level) { void Jay::addLogger(gloox::LogLevel level) {
loggers.emplace_back(std::make_unique<Logger>(client->logInstance(), level)); loggers.emplace_back(std::make_unique<Logger>(client->logInstance(), level));

3
jay.h
View File

@ -18,6 +18,7 @@
#include "component/router.h" #include "component/router.h"
#include "handler/message.h" #include "handler/message.h"
#include "handler/connection.h" #include "handler/connection.h"
#include "module/module.h"
class Jay { class Jay {
public: public:
@ -33,6 +34,7 @@ private:
void initialize(); void initialize();
void createClient(); void createClient();
void createActors(); void createActors();
void createModules();
private: private:
std::mutex runMutex; std::mutex runMutex;
@ -41,5 +43,6 @@ private:
std::shared_ptr<gloox::Client> client; std::shared_ptr<gloox::Client> client;
std::unique_ptr<Message> messageHandler; std::unique_ptr<Message> messageHandler;
std::unique_ptr<Connection> connectionHandler; std::unique_ptr<Connection> connectionHandler;
std::vector<std::shared_ptr<Module::Module>> modules;
std::vector<std::unique_ptr<Logger>> loggers; std::vector<std::unique_ptr<Logger>> loggers;
}; };

View File

@ -3,12 +3,13 @@
#include "actor.h" #include "actor.h"
Module::Actor::Actor(): Module::Actor::Actor(const std::shared_ptr<gloox::Client>& client):
Module() Module(client)
{} {}
Module::Actor::~Actor() noexcept {} Module::Actor::~Actor() noexcept {}
void Module::Actor::message(const std::string& text) { void Module::Actor::message(const std::shared_ptr<::Actor>& actor, const Module::Module::Tokens& args) {
if (args.front() == "list")
sendMessage(actor, "Me\nMyself\nI");
} }

View File

@ -9,10 +9,10 @@ namespace Module {
class Actor : public Module { class Actor : public Module {
public: public:
Actor(); Actor(const std::shared_ptr<gloox::Client>& client);
~Actor() noexcept; ~Actor() noexcept;
virtual void message(const std::string & text) override; virtual void message(const std::shared_ptr<::Actor>& actor, const Tokens& args) override;
}; };
} }

View File

@ -3,7 +3,33 @@
#include "module.h" #include "module.h"
Module::Module::Module() #include "gloox/message.h"
Module::Module::Module(const std::shared_ptr<gloox::Client>& client):
client(client)
{} {}
Module::Module::~Module() noexcept {} Module::Module::~Module() noexcept {}
std::vector<std::string> Module::Module::split(const std::string& string, const std::string& delimiter) {
std::vector<std::string> result;
std::size_t last = 0;
std::size_t next = string.find(delimiter, last);
while (next != std::string::npos) {
result.emplace_back(string.substr(last, next - last));
last = next + 1;
next = string.find(delimiter, last);
}
result.emplace_back(string.substr(last));
return result;
}
void Module::Module::sendMessage(const std::shared_ptr<Actor>& actor, const std::string& body) {
client->send(gloox::Message(
gloox::Message::Chat,
actor->jid,
body
));
}

View File

@ -4,17 +4,33 @@
#pragma once #pragma once
#include <string> #include <string>
#include <memory>
#include <vector>
#include "gloox/client.h"
#include "component/actor.h"
namespace Module { namespace Module {
class Module { class Module {
protected: public:
Module(); typedef std::vector<std::string> Tokens;
virtual void message(const std::string& text) = 0; protected:
Module(const std::shared_ptr<gloox::Client>& client);
void sendMessage(const std::shared_ptr<Actor>& actor, const std::string& body);
public: public:
virtual ~Module() noexcept; virtual ~Module() noexcept;
static Tokens split(const std::string& string, const std::string& delimiter = " ");
virtual void message(const std::shared_ptr<Actor>& actor, const Tokens& args) = 0;
protected:
std::shared_ptr<gloox::Client> client;
}; };
} }