Compare commits

..

2 Commits

Author SHA1 Message Date
Green Sky
54bda18e7c
port to contact4, still needs contact model interface impls 2025-03-10 20:35:27 +01:00
Erik Scholz
4d74826a95
Create LICENSE 2025-02-07 12:31:22 +01:00
6 changed files with 223 additions and 121 deletions

21
LICENSE Normal file
View 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.

View File

@ -34,15 +34,15 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api)
}
try {
auto* cr = PLUG_RESOLVE_INSTANCE_VERSIONED(Contact3Registry, "1");
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());

View File

@ -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,10 +20,10 @@
#include <iostream>
IRCClientContactModel::IRCClientContactModel(
Contact3Registry& cr,
ContactStore4I& cs,
ConfigModelI& conf,
IRCClient1& ircc
) : _cr(cr), _conf(conf), _ircc(ircc), _ircc_sr(_ircc.newSubRef(this)) {
) : _cs(cs), _conf(conf), _ircc(ircc), _ircc_sr(_ircc.newSubRef(this)) {
_ircc_sr
.subscribe(IRCClient_Event::CONNECT)
@ -62,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());
@ -87,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{
@ -137,63 +155,59 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Connect& e) {
_server_hash = getHash(_ircc.getServerName());
_connected = true;
{ // 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;
}
}
auto& cr = _cs.registry();
if (!_cr.valid(_server)) {
_server = _cr.create();
_cr.emplace_or_replace<Contact::Components::ID>(_server, _server_hash);
bool server_contact_created {false};
{ // server
if (!cr.valid(_server)) {
// check for empty contact by id
_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);
}
}
_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();
if (!cr.valid(_self)) {
_self = cr.create();
self_contact_created = true;
}
}
_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"
@ -205,16 +219,16 @@ 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) {
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()) {
@ -241,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;
}
@ -268,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;
}
@ -319,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);
}
@ -339,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
@ -351,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);
}
}
}
@ -381,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;
}
@ -401,23 +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);
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});
@ -433,18 +471,22 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Join& e) {
}
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";
}
@ -457,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
@ -474,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);
}
}
@ -488,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;
@ -496,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;
@ -507,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;
}
@ -528,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;
}
@ -544,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;
}
@ -555,6 +614,8 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::Quit& e) {
// should we remove the user from the channel?
_cs.throwEventUpdate(user);
return false;
}
@ -572,23 +633,33 @@ bool IRCClientContactModel::onEvent(const IRCClient::Events::CTCP_Req& e) {
bool IRCClientContactModel::onEvent(const IRCClient::Events::Disconnect&) {
_connected = false;
if (!_cr.valid(_server)) {
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;
cr.get<Contact::Components::ConnectionState>(_server).state = Contact::Components::ConnectionState::disconnected;
// HACK: by name
_cr.view<Contact::Components::IRC::ServerName, Contact::Components::ConnectionState>().each([this](const auto c, const auto& sn_c, auto& cs) {
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;
}
cs.state = Contact::Components::ConnectionState::disconnected;
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;
}

View File

@ -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,8 +14,8 @@
#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;
@ -22,15 +24,15 @@ class IRCClientContactModel : public IRCClientEventI, public ContactModel3I {
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
);
@ -39,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);
@ -49,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;

View File

@ -5,6 +5,7 @@
#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>
@ -20,11 +21,11 @@
IRCClientMessageManager::IRCClientMessageManager(
RegistryMessageModelI& rmm,
Contact3Registry& cr,
ContactStore4I& cs,
ConfigModelI& conf,
IRCClient1& ircc,
IRCClientContactModel& ircccm
) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _cr(cr), _conf(conf), _ircc(ircc), _ircc_sr(_ircc.newSubRef(this)), _ircccm(ircccm) {
) : _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)
@ -39,7 +40,7 @@ IRCClientMessageManager::IRCClientMessageManager(
IRCClientMessageManager::~IRCClientMessageManager(void) {
}
bool IRCClientMessageManager::processMessage(Contact3Handle from, Contact3Handle to, std::string_view message_text, bool action) {
bool IRCClientMessageManager::processMessage(ContactHandle4 from, ContactHandle4 to, std::string_view message_text, bool action) {
const uint64_t ts = getTimeMS();
Message3Registry* reg_ptr = nullptr;
@ -81,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;
}
@ -92,21 +95,21 @@ bool IRCClientMessageManager::sendText(const Contact3 c, std::string_view messag
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);
@ -114,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;
}
@ -145,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()};
@ -178,7 +181,7 @@ 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;
}

View File

@ -8,7 +8,7 @@ class IRCClientMessageManager : public IRCClientEventI, public RegistryMessageMo
protected:
RegistryMessageModelI& _rmm;
RegistryMessageModelI::SubscriptionReference _rmm_sr;
Contact3Registry& _cr;
ContactStore4I& _cs;
ConfigModelI& _conf;
IRCClient1& _ircc;
IRCClient1::SubscriptionReference _ircc_sr;
@ -17,7 +17,7 @@ class IRCClientMessageManager : public IRCClientEventI, public RegistryMessageMo
public:
IRCClientMessageManager(
RegistryMessageModelI& rmm,
Contact3Registry& cr,
ContactStore4I& cs,
ConfigModelI& conf,
IRCClient1& ircc,
IRCClientContactModel& ircccm
@ -29,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;