Compare commits
14 Commits
0be741947c
...
master
Author | SHA1 | Date | |
---|---|---|---|
4fea965521 | |||
d29f45dbd2 | |||
981e8e3048 | |||
5ebeeef3c2 | |||
54bda18e7c | |||
4d74826a95 | |||
3657634be5 | |||
51a5e841a6 | |||
e4eaf91a68 | |||
7973c7a320 | |||
f5cf44119b | |||
d7280771ce | |||
ae817987c6 | |||
3cb37e33a2 |
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Erik Scholz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,5 +1,7 @@
|
||||
#include <solanaceae/plugin/solana_plugin_v1.h>
|
||||
|
||||
#include <solanaceae/contact/contact_store_i.hpp>
|
||||
|
||||
#include <solanaceae/ircclient/ircclient.hpp>
|
||||
#include <solanaceae/ircclient_contacts/ircclient_contact_model.hpp>
|
||||
#include <solanaceae/ircclient_messages/ircclient_message_manager.hpp>
|
||||
@ -34,15 +36,15 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api)
|
||||
}
|
||||
|
||||
try {
|
||||
auto* cr = PLUG_RESOLVE_INSTANCE_VERSIONED(Contact3Registry, "1");
|
||||
auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModel);
|
||||
auto* cs = PLUG_RESOLVE_INSTANCE(ContactStore4I);
|
||||
auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModelI);
|
||||
auto* conf = PLUG_RESOLVE_INSTANCE(ConfigModelI);
|
||||
|
||||
// static store, could be anywhere tho
|
||||
// construct with fetched dependencies
|
||||
g_ircc = std::make_unique<IRCClient1>(*conf);
|
||||
g_ircccm = std::make_unique<IRCClientContactModel>(*cr, *conf, *g_ircc);
|
||||
g_irccmm = std::make_unique<IRCClientMessageManager>(*rmm, *cr, *conf, *g_ircc, *g_ircccm);
|
||||
g_ircccm = std::make_unique<IRCClientContactModel>(*cs, *conf, *g_ircc);
|
||||
g_irccmm = std::make_unique<IRCClientMessageManager>(*rmm, *cs, *conf, *g_ircc, *g_ircccm);
|
||||
|
||||
// register types
|
||||
PLUG_PROVIDE_INSTANCE(IRCClient1, plugin_name, g_ircc.get());
|
||||
@ -59,14 +61,13 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api)
|
||||
SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void) {
|
||||
std::cout << "PLUGIN " << plugin_name << " STOP()\n";
|
||||
|
||||
g_irccmm.reset();
|
||||
g_ircccm.reset();
|
||||
g_ircc.reset();
|
||||
}
|
||||
|
||||
SOLANA_PLUGIN_EXPORT float solana_plugin_tick(float delta) {
|
||||
(void)delta;
|
||||
g_ircc->iterate(); // TODO: return interval, respect dcc etc
|
||||
|
||||
return 1.f; // expect atleast once per sec
|
||||
return g_ircc->iterate(delta);
|
||||
}
|
||||
|
||||
} // extern C
|
||||
|
@ -8,6 +8,7 @@ add_library(solanaceae_ircclient
|
||||
)
|
||||
|
||||
target_include_directories(solanaceae_ircclient PUBLIC .)
|
||||
target_compile_definitions(solanaceae_ircclient PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||
target_compile_features(solanaceae_ircclient PRIVATE cxx_std_20)
|
||||
target_compile_features(solanaceae_ircclient INTERFACE cxx_std_17)
|
||||
target_link_libraries(solanaceae_ircclient PUBLIC
|
||||
@ -27,6 +28,7 @@ add_library(solanaceae_ircclient_contacts
|
||||
)
|
||||
|
||||
target_include_directories(solanaceae_ircclient_contacts PUBLIC .)
|
||||
target_compile_definitions(solanaceae_ircclient_contacts PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||
target_compile_features(solanaceae_ircclient_contacts PRIVATE cxx_std_20)
|
||||
target_compile_features(solanaceae_ircclient_contacts INTERFACE cxx_std_17)
|
||||
target_link_libraries(solanaceae_ircclient_contacts PUBLIC
|
||||
@ -43,6 +45,7 @@ add_library(solanaceae_ircclient_messages
|
||||
)
|
||||
|
||||
target_include_directories(solanaceae_ircclient_messages PUBLIC .)
|
||||
target_compile_definitions(solanaceae_ircclient_messages PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||
target_compile_features(solanaceae_ircclient_messages PRIVATE cxx_std_20)
|
||||
target_compile_features(solanaceae_ircclient_messages INTERFACE cxx_std_17)
|
||||
target_link_libraries(solanaceae_ircclient_messages PUBLIC
|
||||
|
@ -26,6 +26,7 @@ void IRCClient1::on_event_numeric(irc_session_t* session, unsigned int event, co
|
||||
|
||||
auto ircc = static_cast<IRCClient1*>(irc_get_ctx(session));
|
||||
ircc->dispatch(IRCClient_Event::NUMERIC, IRCClient::Events::Numeric{event, origin, params_view});
|
||||
ircc->_event_fired = true;
|
||||
}
|
||||
|
||||
IRCClient1::IRCClient1(
|
||||
@ -77,7 +78,111 @@ IRCClient1::IRCClient1(
|
||||
irc_option_set(_irc_session, LIBIRC_OPTION_STRIPNICKS);
|
||||
irc_option_set(_irc_session, LIBIRC_OPTION_SSL_NO_VERIFY); // why
|
||||
|
||||
connectSession();
|
||||
}
|
||||
|
||||
IRCClient1::~IRCClient1(void) {
|
||||
irc_destroy_session(_irc_session);
|
||||
}
|
||||
|
||||
// tmp
|
||||
void IRCClient1::run(void) {
|
||||
if (irc_run(_irc_session) != 0) {
|
||||
std::cerr << "error failed to run: " << irc_strerror(irc_errno(_irc_session)) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
float IRCClient1::iterate(float delta) {
|
||||
//if ( session->state != LIBIRC_STATE_CONNECTING )
|
||||
//{
|
||||
//session->lasterror = LIBIRC_ERR_STATE;
|
||||
//return 1;
|
||||
//}
|
||||
|
||||
if (!irc_is_connected(_irc_session)) {
|
||||
if (_try_connecting_state) {
|
||||
// try to connect, every 20sec
|
||||
_try_connecting_cooldown -= delta;
|
||||
if (_try_connecting_cooldown <= 0.f) {
|
||||
std::cerr << "IRCC: trying to connect\n";
|
||||
connectSession();
|
||||
}
|
||||
} else {
|
||||
std::cerr << "IRCC error: not connected, trying to reconnect\n";
|
||||
|
||||
dispatch(IRCClient_Event::DISCONNECT, IRCClient::Events::Disconnect{});
|
||||
connectSession(); // potentially enters trying phase
|
||||
}
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
_event_fired = false;
|
||||
|
||||
struct timeval tv;
|
||||
fd_set in_set, out_set;
|
||||
int maxfd = 0;
|
||||
|
||||
//tv.tv_usec = 20000; // 20ms
|
||||
tv.tv_usec = 1000; // 1ms
|
||||
tv.tv_sec = 0;
|
||||
|
||||
// Init sets
|
||||
FD_ZERO(&in_set);
|
||||
FD_ZERO(&out_set);
|
||||
|
||||
if (irc_add_select_descriptors(_irc_session, &in_set, &out_set, &maxfd) != 0) {
|
||||
std::cerr << "IRCC error: adding select descriptors\n";
|
||||
}
|
||||
|
||||
if (select(maxfd + 1, &in_set, &out_set, 0, &tv) < 0) {
|
||||
std::cerr << "IRCC error: select returned error\n";
|
||||
#if 0
|
||||
if (socket_error() == EINTR) {
|
||||
//continue;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//session->lasterror = LIBIRC_ERR_TERMINATED;
|
||||
//return 1;
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
if (irc_process_select_descriptors(_irc_session, &in_set, &out_set) != 0) {
|
||||
std::cerr << "IRCC error: processing socket select\n";
|
||||
//return 1;
|
||||
}
|
||||
|
||||
// TODO: handle dcc
|
||||
if (_event_fired) {
|
||||
return 0.1f;
|
||||
} else {
|
||||
return 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
irc_session_t* IRCClient1::getSession(void) {
|
||||
return _irc_session;
|
||||
}
|
||||
|
||||
const std::string_view IRCClient1::getServerName(void) const {
|
||||
return _server_name;
|
||||
}
|
||||
|
||||
void IRCClient1::join(std::string_view channel) {
|
||||
assert(false && "implement me");
|
||||
}
|
||||
|
||||
void IRCClient1::connectSession(void) {
|
||||
_try_connecting_state = true;
|
||||
_try_connecting_cooldown = 20.f;
|
||||
|
||||
// reset connection
|
||||
// only closes potentially open sockets and sets state to init
|
||||
// nothing else is touched
|
||||
irc_disconnect(_irc_session);
|
||||
|
||||
// TODO: do we need to set this every time?
|
||||
if (!_conf.has_string("IRCClient", "server")) {
|
||||
std::cerr << "IRCC error: no irc server in config!!\n";
|
||||
throw std::runtime_error("missing server in config");
|
||||
@ -111,70 +216,14 @@ IRCClient1::IRCClient1(
|
||||
}
|
||||
|
||||
if (irc_connect(_irc_session, server.c_str(), port, nullptr, nick.c_str(), username.c_str(), realname.c_str()) != 0) {
|
||||
std::cerr << "error failed to connect: (" << irc_errno(_irc_session) << ") " << irc_strerror(irc_errno(_irc_session)) << "\n";
|
||||
throw std::runtime_error("failed to connect to irc");
|
||||
}
|
||||
}
|
||||
std::cerr << "IRCC error: failed to connect: (" << irc_errno(_irc_session) << ") " << irc_strerror(irc_errno(_irc_session)) << "\n";
|
||||
|
||||
IRCClient1::~IRCClient1(void) {
|
||||
irc_destroy_session(_irc_session);
|
||||
}
|
||||
irc_disconnect(_irc_session);
|
||||
|
||||
// tmp
|
||||
void IRCClient1::run(void) {
|
||||
if (irc_run(_irc_session) != 0) {
|
||||
std::cerr << "error failed to run: " << irc_strerror(irc_errno(_irc_session)) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void IRCClient1::iterate(void) {
|
||||
//if ( session->state != LIBIRC_STATE_CONNECTING )
|
||||
//{
|
||||
//session->lasterror = LIBIRC_ERR_STATE;
|
||||
//return 1;
|
||||
//}
|
||||
|
||||
if (!irc_is_connected(_irc_session)) {
|
||||
//throw std::runtime_error("failed to connect to irc");
|
||||
return;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
fd_set in_set, out_set;
|
||||
int maxfd = 0;
|
||||
|
||||
//tv.tv_usec = 20000; // 20ms
|
||||
tv.tv_usec = 1000; // 1ms
|
||||
tv.tv_sec = 0;
|
||||
|
||||
// Init sets
|
||||
FD_ZERO (&in_set);
|
||||
FD_ZERO (&out_set);
|
||||
|
||||
irc_add_select_descriptors(_irc_session, &in_set, &out_set, &maxfd);
|
||||
|
||||
if (select(maxfd + 1, &in_set, &out_set, 0, &tv) < 0)
|
||||
{
|
||||
#if 0
|
||||
if (socket_error() == EINTR) {
|
||||
//continue;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//session->lasterror = LIBIRC_ERR_TERMINATED;
|
||||
//return 1;
|
||||
return;
|
||||
_try_connecting_state = false;
|
||||
}
|
||||
|
||||
if (irc_process_select_descriptors(_irc_session, &in_set, &out_set)) {
|
||||
//return 1;
|
||||
}
|
||||
}
|
||||
|
||||
irc_session_t* IRCClient1::getSession(void) {
|
||||
return _irc_session;
|
||||
}
|
||||
|
||||
const std::string_view IRCClient1::getServerName(void) const {
|
||||
return _server_name;
|
||||
}
|
||||
|
@ -110,6 +110,11 @@ namespace IRCClient::Events {
|
||||
std::vector<std::string_view> params;
|
||||
};
|
||||
|
||||
struct Disconnect {
|
||||
// TODO: reason
|
||||
// this is not a libircclient event (bad lib)
|
||||
};
|
||||
|
||||
} // Events
|
||||
|
||||
enum class IRCClient_Event : uint32_t {
|
||||
@ -135,6 +140,8 @@ enum class IRCClient_Event : uint32_t {
|
||||
|
||||
UNKNOWN,
|
||||
|
||||
DISCONNECT,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
@ -162,6 +169,7 @@ struct IRCClientEventI {
|
||||
virtual bool onEvent(const IRCClient::Events::CTCP_Rep&) { return false; }
|
||||
virtual bool onEvent(const IRCClient::Events::CTCP_Action&) { return false; }
|
||||
virtual bool onEvent(const IRCClient::Events::Unknown&) { return false; }
|
||||
virtual bool onEvent(const IRCClient::Events::Disconnect&) { return false; }
|
||||
};
|
||||
|
||||
using IRCClientEventProviderI = EventProviderI<IRCClientEventI>;
|
||||
@ -170,7 +178,11 @@ using IRCClientEventProviderI = EventProviderI<IRCClientEventI>;
|
||||
class IRCClient1 : public IRCClientEventProviderI {
|
||||
ConfigModelI& _conf;
|
||||
|
||||
irc_session_t* _irc_session = nullptr;
|
||||
irc_session_t* _irc_session {nullptr};
|
||||
bool _try_connecting_state {false};
|
||||
float _try_connecting_cooldown {0.f};
|
||||
|
||||
bool _event_fired {false};
|
||||
|
||||
std::string _server_name; // name of the irc network this iirc is connected to
|
||||
|
||||
@ -181,9 +193,10 @@ class IRCClient1 : public IRCClientEventProviderI {
|
||||
|
||||
~IRCClient1(void);
|
||||
|
||||
|
||||
// tmp
|
||||
void run(void);
|
||||
void iterate(void);
|
||||
float iterate(float delta);
|
||||
|
||||
// raw access
|
||||
irc_session_t* getSession(void);
|
||||
@ -193,17 +206,23 @@ class IRCClient1 : public IRCClientEventProviderI {
|
||||
// join
|
||||
void join(std::string_view channel);
|
||||
|
||||
private:
|
||||
// connects an already existing session
|
||||
void connectSession(void);
|
||||
|
||||
private: // callbacks for libircclient
|
||||
static void on_event_numeric(irc_session_t* session, unsigned int event, const char* origin, const char** params, unsigned int count);
|
||||
|
||||
template<IRCClient_Event event_type_enum, typename EventType>
|
||||
static void on_event_generic_new(irc_session_t* session, const char* event, const char* origin, const char** params, unsigned int count) {
|
||||
assert(session != nullptr);
|
||||
|
||||
std::vector<std::string_view> params_view;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
params_view.push_back(params[i]);
|
||||
}
|
||||
|
||||
std::cout << "IRC: event " << event << " " << origin << "\n";
|
||||
std::cout << "IRC: event '" << (event?event:"<nullptr>") << "' o:" << (origin?origin:"<nullptr>") << "\n";
|
||||
|
||||
#if 0
|
||||
if (std::string_view{event} == "ACTION") {
|
||||
@ -219,7 +238,9 @@ class IRCClient1 : public IRCClientEventProviderI {
|
||||
auto* ircc = static_cast<IRCClient1*>(irc_get_ctx(session));
|
||||
assert(ircc != nullptr);
|
||||
|
||||
ircc->dispatch(event_type_enum, EventType{origin, params_view});
|
||||
// hack if origin is null
|
||||
ircc->dispatch(event_type_enum, EventType{origin?origin:"<nullptr>", params_view});
|
||||
ircc->_event_fired = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,12 +2,16 @@
|
||||
|
||||
#include "./components.hpp"
|
||||
|
||||
#include <solanaceae/contact/contact_store_i.hpp>
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
#include <solanaceae/util/utils.hpp>
|
||||
|
||||
#include <libirc_rfcnumeric.h>
|
||||
#include <libircclient.h>
|
||||
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/entity/handle.hpp>
|
||||
|
||||
#include <sodium/crypto_hash_sha256.h>
|
||||
|
||||
#include <cstdint>
|
||||
@ -16,20 +20,24 @@
|
||||
#include <iostream>
|
||||
|
||||
IRCClientContactModel::IRCClientContactModel(
|
||||
Contact3Registry& cr,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf,
|
||||
IRCClient1& ircc
|
||||
) : _cr(cr), _conf(conf), _ircc(ircc) {
|
||||
_ircc.subscribe(this, IRCClient_Event::CONNECT);
|
||||
) : _cs(cs), _conf(conf), _ircc(ircc), _ircc_sr(_ircc.newSubRef(this)) {
|
||||
_ircc_sr
|
||||
.subscribe(IRCClient_Event::CONNECT)
|
||||
|
||||
_ircc.subscribe(this, IRCClient_Event::NUMERIC);
|
||||
.subscribe(IRCClient_Event::NUMERIC)
|
||||
|
||||
_ircc.subscribe(this, IRCClient_Event::JOIN);
|
||||
_ircc.subscribe(this, IRCClient_Event::PART);
|
||||
_ircc.subscribe(this, IRCClient_Event::TOPIC);
|
||||
_ircc.subscribe(this, IRCClient_Event::QUIT);
|
||||
.subscribe(IRCClient_Event::JOIN)
|
||||
.subscribe(IRCClient_Event::PART)
|
||||
.subscribe(IRCClient_Event::TOPIC)
|
||||
.subscribe(IRCClient_Event::QUIT)
|
||||
|
||||
_ircc.subscribe(this, IRCClient_Event::CTCP_REQ);
|
||||
.subscribe(IRCClient_Event::CTCP_REQ)
|
||||
|
||||
.subscribe(IRCClient_Event::DISCONNECT)
|
||||
;
|
||||
|
||||
// dont create server self etc until connect event comes
|
||||
|
||||
@ -58,6 +66,18 @@ void IRCClientContactModel::join(const std::string& channel) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IRCClientContactModel::addContact(Contact4 c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRCClientContactModel::acceptRequest(Contact4 c, std::string_view self_name, std::string_view password) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRCClientContactModel::leave(Contact4 c, std::string_view reason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> IRCClientContactModel::getHash(std::string_view value) {
|
||||
assert(!value.empty());
|
||||
|
||||
@ -83,33 +103,35 @@ std::vector<uint8_t> IRCClientContactModel::getIDHash(std::string_view name) {
|
||||
return getHash(data);
|
||||
}
|
||||
|
||||
Contact3Handle IRCClientContactModel::getC(std::string_view channel) {
|
||||
ContactHandle4 IRCClientContactModel::getC(std::string_view channel) {
|
||||
const auto server_name = _ircc.getServerName();
|
||||
const auto& cr = _cs.registry();
|
||||
// TODO: this needs a better way
|
||||
for (const auto e : _cr.view<Contact::Components::IRC::ServerName, Contact::Components::IRC::ChannelName>()) {
|
||||
if (_cr.get<Contact::Components::IRC::ServerName>(e).name == server_name && _cr.get<Contact::Components::IRC::ChannelName>(e).name == channel) {
|
||||
return {_cr, e};
|
||||
for (const auto e : cr.view<Contact::Components::IRC::ServerName, Contact::Components::IRC::ChannelName>()) {
|
||||
if (cr.get<Contact::Components::IRC::ServerName>(e).name == server_name && cr.get<Contact::Components::IRC::ChannelName>(e).name == channel) {
|
||||
return _cs.contactHandle(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {_cr, entt::null};
|
||||
return {};
|
||||
}
|
||||
|
||||
Contact3Handle IRCClientContactModel::getU(std::string_view nick) {
|
||||
ContactHandle4 IRCClientContactModel::getU(std::string_view nick) {
|
||||
const auto server_name = _ircc.getServerName();
|
||||
const auto& cr = _cs.registry();
|
||||
// TODO: this needs a better way
|
||||
for (const auto e : _cr.view<Contact::Components::IRC::ServerName, Contact::Components::IRC::UserName>()) {
|
||||
if (_cr.get<Contact::Components::IRC::ServerName>(e).name == server_name && _cr.get<Contact::Components::IRC::UserName>(e).name == nick) {
|
||||
return {_cr, e};
|
||||
for (const auto e : cr.view<Contact::Components::IRC::ServerName, Contact::Components::IRC::UserName>()) {
|
||||
if (cr.get<Contact::Components::IRC::ServerName>(e).name == server_name && cr.get<Contact::Components::IRC::UserName>(e).name == nick) {
|
||||
return _cs.contactHandle(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {_cr, entt::null};
|
||||
return {};
|
||||
}
|
||||
|
||||
Contact3Handle IRCClientContactModel::getCU(std::string_view name) {
|
||||
ContactHandle4 IRCClientContactModel::getCU(std::string_view name) {
|
||||
if (name.empty()) {
|
||||
return {_cr, entt::null};
|
||||
return {};
|
||||
}
|
||||
|
||||
static constexpr std::string_view channel_prefixes{
|
||||
@ -133,63 +155,59 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Connect& e) {
|
||||
_server_hash = getHash(_ircc.getServerName());
|
||||
_connected = true;
|
||||
|
||||
auto& cr = _cs.registry();
|
||||
|
||||
bool server_contact_created {false};
|
||||
{ // server
|
||||
if (!_cr.valid(_server)) {
|
||||
if (!cr.valid(_server)) {
|
||||
// check for empty contact by id
|
||||
for (const auto e : _cr.view<Contact::Components::ID>()) {
|
||||
if (_cr.get<Contact::Components::ID>(e).data == _server_hash) {
|
||||
_server = e;
|
||||
break;
|
||||
_server = _cs.getOneContactByID(ByteSpan{_server_hash});
|
||||
|
||||
if (!cr.valid(_server)) {
|
||||
_server = cr.create();
|
||||
server_contact_created = true;
|
||||
cr.emplace_or_replace<Contact::Components::ID>(_server, _server_hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_cr.valid(_server)) {
|
||||
_server = _cr.create();
|
||||
_cr.emplace_or_replace<Contact::Components::ID>(_server, _server_hash);
|
||||
}
|
||||
}
|
||||
|
||||
_cr.emplace_or_replace<Contact::Components::ContactModel>(_server, this);
|
||||
_cr.emplace_or_replace<Contact::Components::IRC::ServerName>(_server, std::string{_ircc.getServerName()}); // really?
|
||||
_cr.emplace_or_replace<Contact::Components::Name>(_server, std::string{_ircc.getServerName()}); // TODO: add special string?
|
||||
cr.emplace_or_replace<Contact::Components::ContactModel>(_server, this);
|
||||
cr.emplace_or_replace<Contact::Components::IRC::ServerName>(_server, std::string{_ircc.getServerName()}); // really?
|
||||
cr.emplace_or_replace<Contact::Components::Name>(_server, std::string{_ircc.getServerName()}); // TODO: add special string?
|
||||
|
||||
// does this make sense ?
|
||||
_cr.emplace_or_replace<Contact::Components::ConnectionState>(_server, Contact::Components::ConnectionState::State::direct);
|
||||
cr.emplace_or_replace<Contact::Components::ConnectionState>(_server, Contact::Components::ConnectionState::State::direct);
|
||||
|
||||
_cr.emplace_or_replace<Contact::Components::TagBig>(_server);
|
||||
cr.emplace_or_replace<Contact::Components::TagBig>(_server);
|
||||
// the server connection is also the root contact (ircccm only handles 1 server 1 user)
|
||||
_cr.emplace_or_replace<Contact::Components::TagRoot>(_server);
|
||||
cr.emplace_or_replace<Contact::Components::TagRoot>(_server);
|
||||
// TODO: should this be its own node instead? or should the server node be created on construction?
|
||||
}
|
||||
|
||||
bool self_contact_created {false};
|
||||
{ // self
|
||||
if (!_cr.valid(_self)) {
|
||||
if (!cr.valid(_self)) {
|
||||
// TODO: this can create self with peexisting id
|
||||
if (!e.params.empty()) {
|
||||
const auto self_hash = getIDHash(e.params.front());
|
||||
|
||||
// check for empty contact by id
|
||||
for (const auto e : _cr.view<Contact::Components::ID>()) {
|
||||
if (_cr.get<Contact::Components::ID>(e).data == self_hash) {
|
||||
_self = e;
|
||||
break;
|
||||
_server = _cs.getOneContactByID(_server, ByteSpan{self_hash});
|
||||
}
|
||||
if (!cr.valid(_self)) {
|
||||
_self = cr.create();
|
||||
self_contact_created = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_cr.valid(_self)) {
|
||||
_self = _cr.create();
|
||||
}
|
||||
}
|
||||
_cr.emplace_or_replace<Contact::Components::ContactModel>(_self, this);
|
||||
_cr.emplace_or_replace<Contact::Components::Parent>(_self, _server);
|
||||
_cr.emplace_or_replace<Contact::Components::TagSelfStrong>(_self);
|
||||
_cr.emplace_or_replace<Contact::Components::IRC::ServerName>(_self, std::string{_ircc.getServerName()}); // really?
|
||||
cr.emplace_or_replace<Contact::Components::ContactModel>(_self, this);
|
||||
cr.emplace_or_replace<Contact::Components::Parent>(_self, _server);
|
||||
cr.emplace_or_replace<Contact::Components::TagSelfStrong>(_self);
|
||||
cr.emplace_or_replace<Contact::Components::IRC::ServerName>(_self, std::string{_ircc.getServerName()}); // really?
|
||||
if (!e.params.empty()) {
|
||||
_cr.emplace_or_replace<Contact::Components::IRC::UserName>(_self, std::string{e.params.front()});
|
||||
_cr.emplace_or_replace<Contact::Components::Name>(_self, std::string{e.params.front()});
|
||||
cr.emplace_or_replace<Contact::Components::IRC::UserName>(_self, std::string{e.params.front()});
|
||||
cr.emplace_or_replace<Contact::Components::Name>(_self, std::string{e.params.front()});
|
||||
// make id hash(hash(ServerName)+UserName)
|
||||
// or irc name format, but those might cause collisions
|
||||
_cr.emplace_or_replace<Contact::Components::ID>(_self, getIDHash(e.params.front()));
|
||||
cr.emplace_or_replace<Contact::Components::ID>(_self, getIDHash(e.params.front()));
|
||||
|
||||
#if 0
|
||||
std::cout << "### created self with"
|
||||
@ -201,14 +219,34 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Connect& e) {
|
||||
#endif
|
||||
}
|
||||
|
||||
_cr.emplace_or_replace<Contact::Components::ConnectionState>(_self, Contact::Components::ConnectionState::State::direct);
|
||||
cr.emplace_or_replace<Contact::Components::ConnectionState>(_self, Contact::Components::ConnectionState::State::direct);
|
||||
|
||||
// add self to server
|
||||
_cr.emplace_or_replace<Contact::Components::Self>(_server, _self);
|
||||
cr.emplace_or_replace<Contact::Components::Self>(_server, _self);
|
||||
}
|
||||
|
||||
// check for preexisting channels,
|
||||
// since this might be a reconnect
|
||||
// and reissue joins
|
||||
cr.view<Contact::Components::IRC::ServerName, Contact::Components::IRC::ChannelName>().each([this](const auto c, const auto& sn_c, const auto& cn_c) {
|
||||
// HACK: by name
|
||||
// should be by parent instead
|
||||
if (sn_c.name != _ircc.getServerName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: implement join lol
|
||||
irc_cmd_join(
|
||||
_ircc.getSession(),
|
||||
cn_c.name.c_str(),
|
||||
""
|
||||
);
|
||||
});
|
||||
|
||||
// join queued
|
||||
// TODO: merge with above
|
||||
while (!_join_queue.empty()) {
|
||||
// TODO: implement join lol
|
||||
irc_cmd_join(
|
||||
_ircc.getSession(),
|
||||
_join_queue.front().c_str(),
|
||||
@ -217,6 +255,18 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Connect& e) {
|
||||
_join_queue.pop();
|
||||
}
|
||||
|
||||
if (server_contact_created) {
|
||||
_cs.throwEventConstruct(_server);
|
||||
} else {
|
||||
_cs.throwEventUpdate(_server);
|
||||
}
|
||||
|
||||
if (self_contact_created) {
|
||||
_cs.throwEventConstruct(_self);
|
||||
} else {
|
||||
_cs.throwEventUpdate(_self);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -244,7 +294,7 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Numeric& e) {
|
||||
|
||||
const auto& channel_name = e.params.at(2);
|
||||
auto channel = getC(channel_name);
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
std::cerr << "IRCCCM error: name list for unknown channel\n";
|
||||
return false;
|
||||
}
|
||||
@ -295,17 +345,15 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Numeric& e) {
|
||||
//std::cout << "u: " << user_str << "\n";
|
||||
|
||||
auto user = getU(user_str);
|
||||
if (!user.valid()) {
|
||||
bool user_throw_event {false};
|
||||
bool user_created {false};
|
||||
if (!static_cast<bool>(user)) {
|
||||
const auto user_hash = getIDHash(user_str);
|
||||
// check for empty contact by id
|
||||
for (const auto e : _cr.view<Contact::Components::ID>()) {
|
||||
if (_cr.get<Contact::Components::ID>(e).data == user_hash) {
|
||||
user = {_cr, e};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!user.valid()) {
|
||||
user = {_cr, _cr.create()};
|
||||
user = _cs.getOneContactByID(_server, ByteSpan{user_hash});
|
||||
if (!static_cast<bool>(user)) {
|
||||
user = _cs.contactHandle(_cs.registry().create());
|
||||
user_created = true;
|
||||
user.emplace_or_replace<Contact::Components::ID>(user_hash);
|
||||
}
|
||||
|
||||
@ -315,11 +363,15 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Numeric& e) {
|
||||
// add to channel?
|
||||
user.emplace_or_replace<Contact::Components::IRC::UserName>(std::string{user_str});
|
||||
user.emplace_or_replace<Contact::Components::Name>(std::string{user_str});
|
||||
|
||||
user_throw_event = true;
|
||||
}
|
||||
|
||||
if (user.entity() != _self) {
|
||||
user.emplace_or_replace<Contact::Components::ConnectionState>(Contact::Components::ConnectionState::State::cloud);
|
||||
user.emplace_or_replace<Contact::Components::Self>(_self);
|
||||
|
||||
user_throw_event = true;
|
||||
}
|
||||
|
||||
{ // add user to channel
|
||||
@ -327,6 +379,15 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Numeric& e) {
|
||||
if (std::find(channel_user_list.begin(), channel_user_list.end(), user) == channel_user_list.end()) {
|
||||
//std::cout << "!!!!!!!! new user in channel!\n";
|
||||
channel_user_list.push_back(user);
|
||||
user_throw_event = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user_throw_event) {
|
||||
if (user_created) {
|
||||
_cs.throwEventConstruct(user);
|
||||
} else {
|
||||
_cs.throwEventUpdate(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,13 +418,14 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Numeric& e) {
|
||||
|
||||
const auto channel_name = e.params.at(1);
|
||||
auto channel = getC(channel_name);
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
std::cerr << "IRCCCM error: topic for unknown channel\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto topic = e.params.at(2);
|
||||
channel.emplace_or_replace<Contact::Components::StatusText>(std::string{topic}).fillFirstLineLength();
|
||||
_cs.throwEventUpdate(channel);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -377,22 +439,23 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Join& e) {
|
||||
|
||||
//std::cout << "JOIN!!!! " << e.origin << " in " << joined_channel_name << "\n";
|
||||
|
||||
auto& cr = _cs.registry();
|
||||
|
||||
bool channel_created {false};
|
||||
auto channel = getC(e.params.front());
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
const auto channel_hash = getIDHash(joined_channel_name);
|
||||
// check for empty contact by id
|
||||
for (const auto e : _cr.view<Contact::Components::ID>()) {
|
||||
if (_cr.get<Contact::Components::ID>(e).data == channel_hash) {
|
||||
channel = {_cr, e};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!channel.valid()) {
|
||||
channel = {_cr, _cr.create()};
|
||||
channel = _cs.getOneContactByID(_server, ByteSpan{channel_hash});
|
||||
if (!static_cast<bool>(channel)) {
|
||||
//channel = {_cr, _cr.create()};
|
||||
channel = _cs.contactHandle(cr.create());
|
||||
channel_created = true;
|
||||
channel.emplace_or_replace<Contact::Components::ID>(channel_hash);
|
||||
}
|
||||
channel.emplace_or_replace<Contact::Components::ContactModel>(this);
|
||||
channel.emplace_or_replace<Contact::Components::Parent>(_server);
|
||||
cr.get_or_emplace<Contact::Components::ParentOf>(_server).subs.push_back(channel);
|
||||
channel.emplace_or_replace<Contact::Components::ParentOf>(); // start empty
|
||||
channel.emplace_or_replace<Contact::Components::IRC::ServerName>(std::string{_ircc.getServerName()});
|
||||
channel.emplace_or_replace<Contact::Components::IRC::ChannelName>(std::string{joined_channel_name});
|
||||
@ -400,27 +463,30 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Join& e) {
|
||||
|
||||
std::cout << "IRCCCM: joined '" << joined_channel_name << "' id:" << bin2hex(channel.get<Contact::Components::ID>().data) << "\n";
|
||||
|
||||
channel.emplace_or_replace<Contact::Components::ConnectionState>(Contact::Components::ConnectionState::State::cloud);
|
||||
|
||||
channel.emplace_or_replace<Contact::Components::TagBig>();
|
||||
channel.emplace_or_replace<Contact::Components::TagGroup>();
|
||||
|
||||
// add self to channel
|
||||
channel.emplace_or_replace<Contact::Components::Self>(_self);
|
||||
}
|
||||
channel.emplace_or_replace<Contact::Components::ConnectionState>(Contact::Components::ConnectionState::State::cloud);
|
||||
|
||||
if (channel_created) {
|
||||
_cs.throwEventConstruct(channel);
|
||||
} else {
|
||||
_cs.throwEventUpdate(channel);
|
||||
}
|
||||
|
||||
auto user = getU(e.origin);
|
||||
if (!user.valid()) {
|
||||
bool user_throw_event {false};
|
||||
bool user_created {false};
|
||||
if (!static_cast<bool>(user)) {
|
||||
const auto user_hash = getIDHash(e.origin);
|
||||
// check for empty contact by id
|
||||
for (const auto e : _cr.view<Contact::Components::ID>()) {
|
||||
if (_cr.get<Contact::Components::ID>(e).data == user_hash) {
|
||||
user = {_cr, e};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!user.valid()) {
|
||||
user = {_cr, _cr.create()};
|
||||
user = _cs.getOneContactByID(_server, ByteSpan{user_hash});
|
||||
if (!static_cast<bool>(user)) {
|
||||
user = _cs.contactHandle(cr.create());
|
||||
user_created = true;
|
||||
user.emplace_or_replace<Contact::Components::ID>(user_hash);
|
||||
std::cerr << "IRCCCM error: had to create joining user (self?)\n";
|
||||
}
|
||||
@ -433,16 +499,28 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Join& e) {
|
||||
user.emplace_or_replace<Contact::Components::IRC::UserName>(std::string{e.origin});
|
||||
user.emplace_or_replace<Contact::Components::Name>(std::string{e.origin});
|
||||
|
||||
user_throw_event = true;
|
||||
|
||||
// ???
|
||||
std::cout << "### created self(?) with"
|
||||
<< " ircn:" << _cr.get<Contact::Components::IRC::UserName>(_self).name
|
||||
<< " ircsn:" << _cr.get<Contact::Components::IRC::ServerName>(_self).name
|
||||
<< " id:" << bin2hex(_cr.get<Contact::Components::ID>(_self).data)
|
||||
<< " ircn:" << cr.get<Contact::Components::IRC::UserName>(_self).name
|
||||
<< " ircsn:" << cr.get<Contact::Components::IRC::ServerName>(_self).name
|
||||
<< " id:" << bin2hex(cr.get<Contact::Components::ID>(_self).data)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if (user.entity() != _self) {
|
||||
user.emplace_or_replace<Contact::Components::ConnectionState>(Contact::Components::ConnectionState::State::cloud);
|
||||
user.emplace_or_replace<Contact::Components::Self>(_self);
|
||||
user_throw_event = true;
|
||||
}
|
||||
|
||||
if (user_throw_event) {
|
||||
if (user_created) {
|
||||
_cs.throwEventConstruct(user);
|
||||
} else {
|
||||
_cs.throwEventUpdate(user);
|
||||
}
|
||||
}
|
||||
|
||||
{ // add user to channel
|
||||
@ -450,6 +528,7 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Join& e) {
|
||||
if (std::find(channel_user_list.begin(), channel_user_list.end(), user) == channel_user_list.end()) {
|
||||
//std::cout << "!!!!!!!! new user in channel!\n";
|
||||
channel_user_list.push_back(user);
|
||||
_cs.throwEventUpdate(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,7 +543,7 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Part& e) {
|
||||
|
||||
// e.origin // is the parting user
|
||||
auto user = getU(e.origin);
|
||||
if (!user.valid()) {
|
||||
if (!static_cast<bool>(user)) {
|
||||
// ignoring unknown users, might be caused by a bug
|
||||
std::cerr << "ignoring unknown users, might be caused by a bug\n";
|
||||
return false;
|
||||
@ -472,7 +551,7 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Part& e) {
|
||||
|
||||
// e.params.front() is the channel
|
||||
auto channel = getC(e.params.front());
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
// ignoring unknown channel, might be caused by a bug
|
||||
std::cerr << "ignoring unknown channel, might be caused by a bug\n";
|
||||
return false;
|
||||
@ -483,11 +562,14 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Part& e) {
|
||||
if (auto it = std::find(channel_user_list.begin(), channel_user_list.end(), user); it != channel_user_list.end()) {
|
||||
//std::cout << "!!!!!!!! removing user from channel!\n";
|
||||
channel_user_list.erase(it);
|
||||
_cs.throwEventUpdate(channel);
|
||||
} else {
|
||||
//std::cout << "!!!!!!!! unknown user leaving channel!\n";
|
||||
}
|
||||
}
|
||||
|
||||
_cs.throwEventUpdate(user); // ??
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -504,13 +586,14 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Topic& e) {
|
||||
|
||||
const auto channel_name = e.params.at(0);
|
||||
auto channel = getC(channel_name);
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
std::cerr << "IRCCCM error: new topic for unknown channel\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto topic = e.params.at(1);
|
||||
channel.emplace_or_replace<Contact::Components::StatusText>(std::string{topic}).fillFirstLineLength();
|
||||
_cs.throwEventUpdate(channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -520,7 +603,7 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Quit& e) {
|
||||
// e.params.front() is the quit reason
|
||||
|
||||
auto user = getU(e.origin);
|
||||
if (!user.valid()) {
|
||||
if (!static_cast<bool>(user)) {
|
||||
// ignoring unknown users, might be caused by a bug
|
||||
return false;
|
||||
}
|
||||
@ -531,6 +614,8 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Quit& e) {
|
||||
|
||||
// should we remove the user from the channel?
|
||||
|
||||
_cs.throwEventUpdate(user);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -545,3 +630,36 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::CTCP_Req& e) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRCClientContactModel::onEvent(const IRCClient::Events::Disconnect&) {
|
||||
_connected = false;
|
||||
auto& cr = _cs.registry();
|
||||
if (!cr.valid(_server)) {
|
||||
// skip if where already offline
|
||||
return false;
|
||||
}
|
||||
cr.get<Contact::Components::ConnectionState>(_server).state = Contact::Components::ConnectionState::disconnected;
|
||||
|
||||
// HACK: by name
|
||||
ContactHandle4 server;
|
||||
cr.view<Contact::Components::IRC::ServerName, Contact::Components::ConnectionState>().each([this, &server](const auto c, const auto& sn_c, auto&) {
|
||||
// HACK: by name
|
||||
// should be by parent instead
|
||||
if (sn_c.name != _ircc.getServerName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
server = _cs.contactHandle(c);
|
||||
});
|
||||
|
||||
if (!static_cast<bool>(server)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
server.get_or_emplace<Contact::Components::ConnectionState>().state = Contact::Components::ConnectionState::disconnected;
|
||||
|
||||
_cs.throwEventUpdate(server);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/contact/contact_model3.hpp>
|
||||
#include <solanaceae/contact/contact_model4.hpp>
|
||||
#include <solanaceae/util/config_model.hpp>
|
||||
|
||||
#include <solanaceae/ircclient/ircclient.hpp>
|
||||
|
||||
#include <entt/entity/entity.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
@ -12,24 +14,25 @@
|
||||
|
||||
#include <iostream> // tmp
|
||||
|
||||
class IRCClientContactModel : public IRCClientEventI, public ContactModel3I {
|
||||
Contact3Registry& _cr;
|
||||
class IRCClientContactModel : public IRCClientEventI, public ContactModel4I {
|
||||
ContactStore4I& _cs;
|
||||
ConfigModelI& _conf;
|
||||
IRCClient1& _ircc;
|
||||
IRCClient1::SubscriptionReference _ircc_sr;
|
||||
|
||||
// cm needs the connect event to happen
|
||||
bool _connected {false};
|
||||
|
||||
std::vector<uint8_t> _server_hash; // cached for id gen
|
||||
Contact3 _server = entt::null;
|
||||
Contact3 _self = entt::null;
|
||||
Contact4 _server {entt::null};
|
||||
Contact4 _self {entt::null};
|
||||
|
||||
// used if not connected
|
||||
std::queue<std::string> _join_queue;
|
||||
|
||||
public:
|
||||
IRCClientContactModel(
|
||||
Contact3Registry& cr,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf,
|
||||
IRCClient1& ircc
|
||||
);
|
||||
@ -38,6 +41,11 @@ class IRCClientContactModel : public IRCClientEventI, public ContactModel3I {
|
||||
|
||||
void join(const std::string& channel);
|
||||
|
||||
protected: // interface
|
||||
bool addContact(Contact4 c) override;
|
||||
bool acceptRequest(Contact4 c, std::string_view self_name, std::string_view password) override;
|
||||
bool leave(Contact4 c, std::string_view reason) override;
|
||||
|
||||
private:
|
||||
// just the hash algo
|
||||
std::vector<uint8_t> getHash(std::string_view value);
|
||||
@ -48,10 +56,10 @@ class IRCClientContactModel : public IRCClientEventI, public ContactModel3I {
|
||||
// eg: hash(hash(ServerName)+ChannelName)
|
||||
std::vector<uint8_t> getIDHash(std::string_view name);
|
||||
|
||||
Contact3Handle getC(std::string_view channel);
|
||||
Contact3Handle getU(std::string_view nick);
|
||||
ContactHandle4 getC(std::string_view channel);
|
||||
ContactHandle4 getU(std::string_view nick);
|
||||
// user or channel using channel prefix
|
||||
Contact3Handle getCU(std::string_view name);
|
||||
ContactHandle4 getCU(std::string_view name);
|
||||
|
||||
private: // ircclient
|
||||
bool onEvent(const IRCClient::Events::Connect& e) override;
|
||||
@ -61,4 +69,5 @@ class IRCClientContactModel : public IRCClientEventI, public ContactModel3I {
|
||||
bool onEvent(const IRCClient::Events::Topic& e) override;
|
||||
bool onEvent(const IRCClient::Events::Quit& e) override;
|
||||
bool onEvent(const IRCClient::Events::CTCP_Req&) override;
|
||||
bool onEvent(const IRCClient::Events::Disconnect&) override;
|
||||
};
|
||||
|
@ -1,8 +1,11 @@
|
||||
#include "./ircclient_message_manager.hpp"
|
||||
|
||||
#include <solanaceae/util/time.hpp>
|
||||
|
||||
#include <solanaceae/ircclient_contacts/components.hpp>
|
||||
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
#include <solanaceae/contact/contact_store_i.hpp>
|
||||
#include <solanaceae/message3/components.hpp>
|
||||
#include <solanaceae/message3/registry_message_model.hpp>
|
||||
|
||||
@ -17,26 +20,28 @@
|
||||
#include <iostream>
|
||||
|
||||
IRCClientMessageManager::IRCClientMessageManager(
|
||||
RegistryMessageModel& rmm,
|
||||
Contact3Registry& cr,
|
||||
RegistryMessageModelI& rmm,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf,
|
||||
IRCClient1& ircc,
|
||||
IRCClientContactModel& ircccm
|
||||
) : _rmm(rmm), _cr(cr), _conf(conf), _ircc(ircc), _ircccm(ircccm) {
|
||||
_ircc.subscribe(this, IRCClient_Event::CHANNEL);
|
||||
_ircc.subscribe(this, IRCClient_Event::PRIVMSG);
|
||||
_ircc.subscribe(this, IRCClient_Event::NOTICE);
|
||||
_ircc.subscribe(this, IRCClient_Event::CHANNELNOTICE);
|
||||
_ircc.subscribe(this, IRCClient_Event::CTCP_ACTION);
|
||||
) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _cs(cs), _conf(conf), _ircc(ircc), _ircc_sr(_ircc.newSubRef(this)), _ircccm(ircccm) {
|
||||
_ircc_sr
|
||||
.subscribe(IRCClient_Event::CHANNEL)
|
||||
.subscribe(IRCClient_Event::PRIVMSG)
|
||||
.subscribe(IRCClient_Event::NOTICE)
|
||||
.subscribe(IRCClient_Event::CHANNELNOTICE)
|
||||
.subscribe(IRCClient_Event::CTCP_ACTION)
|
||||
;
|
||||
|
||||
_rmm.subscribe(this, RegistryMessageModel_Event::send_text);
|
||||
_rmm_sr.subscribe(RegistryMessageModel_Event::send_text);
|
||||
}
|
||||
|
||||
IRCClientMessageManager::~IRCClientMessageManager(void) {
|
||||
}
|
||||
|
||||
bool IRCClientMessageManager::processMessage(Contact3Handle from, Contact3Handle to, std::string_view message_text, bool action) {
|
||||
const uint64_t ts = Message::getTimeMS();
|
||||
bool IRCClientMessageManager::processMessage(ContactHandle4 from, ContactHandle4 to, std::string_view message_text, bool action) {
|
||||
const uint64_t ts = getTimeMS();
|
||||
|
||||
Message3Registry* reg_ptr = nullptr;
|
||||
if (to.all_of<Contact::Components::TagSelfStrong>()) {
|
||||
@ -77,8 +82,10 @@ bool IRCClientMessageManager::processMessage(Contact3Handle from, Contact3Handle
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRCClientMessageManager::sendText(const Contact3 c, std::string_view message, bool action) {
|
||||
if (!_cr.valid(c)) {
|
||||
bool IRCClientMessageManager::sendText(const Contact4 c, std::string_view message, bool action) {
|
||||
const auto& cr = _cs.registry();
|
||||
|
||||
if (!cr.valid(c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -86,23 +93,23 @@ bool IRCClientMessageManager::sendText(const Contact3 c, std::string_view messag
|
||||
return false; // TODO: empty messages allowed?
|
||||
}
|
||||
|
||||
const uint64_t ts = Message::getTimeMS();
|
||||
const uint64_t ts = getTimeMS();
|
||||
|
||||
if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) {
|
||||
if (cr.all_of<Contact::Components::TagSelfStrong>(c)) {
|
||||
return false; // message to self? not with irc
|
||||
}
|
||||
|
||||
// test for contact irc specific components
|
||||
// TODO: what about commands and server messages?
|
||||
if (!_cr.any_of<Contact::Components::IRC::UserName, Contact::Components::IRC::ChannelName>(c)) {
|
||||
if (!cr.any_of<Contact::Components::IRC::UserName, Contact::Components::IRC::ChannelName>(c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string to_str;
|
||||
if (_cr.all_of<Contact::Components::IRC::UserName>(c)) {
|
||||
to_str = _cr.get<Contact::Components::IRC::UserName>(c).name;
|
||||
if (cr.all_of<Contact::Components::IRC::UserName>(c)) {
|
||||
to_str = cr.get<Contact::Components::IRC::UserName>(c).name;
|
||||
} else {
|
||||
to_str = _cr.get<Contact::Components::IRC::ChannelName>(c).name;
|
||||
to_str = cr.get<Contact::Components::IRC::ChannelName>(c).name;
|
||||
}
|
||||
|
||||
auto* reg_ptr = _rmm.get(c);
|
||||
@ -110,7 +117,7 @@ bool IRCClientMessageManager::sendText(const Contact3 c, std::string_view messag
|
||||
return false; // nope
|
||||
}
|
||||
|
||||
if (!_cr.all_of<Contact::Components::Self>(c)) {
|
||||
if (!cr.all_of<Contact::Components::Self>(c)) {
|
||||
std::cerr << "IRCCMM error: cant get self\n";
|
||||
return false;
|
||||
}
|
||||
@ -141,7 +148,7 @@ bool IRCClientMessageManager::sendText(const Contact3 c, std::string_view messag
|
||||
}
|
||||
}
|
||||
|
||||
const Contact3 c_self = _cr.get<Contact::Components::Self>(c).self;
|
||||
const Contact4 c_self = cr.get<Contact::Components::Self>(c).self;
|
||||
|
||||
auto new_msg = Message3Handle{*reg_ptr, reg_ptr->create()};
|
||||
|
||||
@ -174,14 +181,14 @@ bool IRCClientMessageManager::onEvent(const IRCClient::Events::Channel& e) {
|
||||
|
||||
// e.origin is sender
|
||||
auto sender = _ircccm.getU(e.origin); // assuming its always a user // aka ContactFrom
|
||||
if (!sender.valid()) {
|
||||
if (!static_cast<bool>(sender)) {
|
||||
std::cerr << "IRCCMM error: channel event unknown sender\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// e.params.at(0) is channel
|
||||
auto channel = _ircccm.getC(e.params.at(0)); // aka ContactTo
|
||||
if (!channel.valid()) {
|
||||
if (!static_cast<bool>(channel)) {
|
||||
std::cerr << "IRCCMM error: channel event unknown channel\n";
|
||||
return false;
|
||||
}
|
||||
@ -200,14 +207,14 @@ bool IRCClientMessageManager::onEvent(const IRCClient::Events::PrivMSG& e) {
|
||||
|
||||
// e.origin is sender
|
||||
auto from = _ircccm.getU(e.origin); // assuming its always a user // aka ContactFrom
|
||||
if (!from.valid()) {
|
||||
if (!static_cast<bool>(from)) {
|
||||
std::cerr << "IRCCMM error: privmsg event unknown sender\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// e.params.at(0) is receiver (us?)
|
||||
auto to = _ircccm.getU(e.params.at(0)); // aka ContactTo
|
||||
if (!to.valid()) {
|
||||
if (!static_cast<bool>(to)) {
|
||||
std::cerr << "IRCCMM error: privmsg event unknown channel\n";
|
||||
return false;
|
||||
}
|
||||
@ -252,14 +259,14 @@ bool IRCClientMessageManager::onEvent(const IRCClient::Events::ChannelNotice& e)
|
||||
|
||||
// e.origin is sending user (probably)
|
||||
auto from = _ircccm.getU(e.origin);
|
||||
if (!from.valid()) {
|
||||
if (!static_cast<bool>(from)) {
|
||||
std::cerr << "IRCCMM error: channel notice event unknown sender\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// e.params.at(0) is channel
|
||||
auto to = _ircccm.getC(e.params.at(0));
|
||||
if (!to.valid()) {
|
||||
if (!static_cast<bool>(to)) {
|
||||
std::cerr << "IRCCMM error: unknown receiver\n";
|
||||
return false;
|
||||
}
|
||||
@ -278,14 +285,14 @@ bool IRCClientMessageManager::onEvent(const IRCClient::Events::CTCP_Action& e) {
|
||||
|
||||
// e.origin is sender
|
||||
auto from = _ircccm.getU(e.origin); // assuming its always a user // aka ContactFrom
|
||||
if (!from.valid()) {
|
||||
if (!static_cast<bool>(from)) {
|
||||
std::cerr << "IRCCMM error: channel event unknown sender\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// e.params.at(0) is receiver (self if pm or channel if channel)
|
||||
auto receiver = _ircccm.getCU(e.params.at(0));
|
||||
if (!receiver.valid()) {
|
||||
if (!static_cast<bool>(receiver)) {
|
||||
std::cerr << "IRCCMM error: unknown receiver\n";
|
||||
return false;
|
||||
}
|
||||
|
@ -6,16 +6,18 @@
|
||||
|
||||
class IRCClientMessageManager : public IRCClientEventI, public RegistryMessageModelEventI {
|
||||
protected:
|
||||
RegistryMessageModel& _rmm;
|
||||
Contact3Registry& _cr;
|
||||
RegistryMessageModelI& _rmm;
|
||||
RegistryMessageModelI::SubscriptionReference _rmm_sr;
|
||||
ContactStore4I& _cs;
|
||||
ConfigModelI& _conf;
|
||||
IRCClient1& _ircc;
|
||||
IRCClient1::SubscriptionReference _ircc_sr;
|
||||
IRCClientContactModel& _ircccm;
|
||||
|
||||
public:
|
||||
IRCClientMessageManager(
|
||||
RegistryMessageModel& rmm,
|
||||
Contact3Registry& cr,
|
||||
RegistryMessageModelI& rmm,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf,
|
||||
IRCClient1& ircc,
|
||||
IRCClientContactModel& ircccm
|
||||
@ -27,10 +29,10 @@ class IRCClientMessageManager : public IRCClientEventI, public RegistryMessageMo
|
||||
using IRCClientEventI::onEvent;
|
||||
using RegistryMessageModelEventI::onEvent;
|
||||
private:
|
||||
bool processMessage(Contact3Handle from, Contact3Handle to, std::string_view message_text, bool action);
|
||||
bool processMessage(ContactHandle4 from, ContactHandle4 to, std::string_view message_text, bool action);
|
||||
|
||||
private: // mm3
|
||||
bool sendText(const Contact3 c, std::string_view message, bool action = false) override;
|
||||
bool sendText(const Contact4 c, std::string_view message, bool action = false) override;
|
||||
|
||||
private: // ircclient
|
||||
bool onEvent(const IRCClient::Events::Channel& e) override;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <chrono>
|
||||
#include <solanaceae/util/simple_config_model.hpp>
|
||||
#include <solanaceae/contact/contact_model3.hpp>
|
||||
#include <solanaceae/message3/registry_message_model.hpp>
|
||||
#include <solanaceae/message3/registry_message_model_impl.hpp>
|
||||
#include <solanaceae/ircclient/ircclient.hpp>
|
||||
#include <solanaceae/ircclient_contacts/ircclient_contact_model.hpp>
|
||||
#include <solanaceae/ircclient_messages/ircclient_message_manager.hpp>
|
||||
@ -9,6 +10,8 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
int main(void) {
|
||||
SimpleConfigModel conf;
|
||||
@ -19,7 +22,7 @@ int main(void) {
|
||||
conf.set("IRCClient", "autojoin", "#green_testing", true);
|
||||
|
||||
Contact3Registry cr;
|
||||
RegistryMessageModel rmm{cr};
|
||||
RegistryMessageModelImpl rmm{cr};
|
||||
|
||||
IRCClient1 ircc{conf};
|
||||
|
||||
@ -29,7 +32,8 @@ int main(void) {
|
||||
//ircccm.join("#green_testing");
|
||||
|
||||
while (irc_is_connected(ircc.getSession())) {
|
||||
ircc.iterate();
|
||||
ircc.iterate(0.005f);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user