diff --git a/src/providers/irc/AbstractIrcServer.cpp b/src/providers/irc/AbstractIrcServer.cpp index 0a3019e5c..2618465a5 100644 --- a/src/providers/irc/AbstractIrcServer.cpp +++ b/src/providers/irc/AbstractIrcServer.cpp @@ -71,8 +71,30 @@ AbstractIrcServer::AbstractIrcServer() }); } +void AbstractIrcServer::initializeIrc() +{ + assert(!this->initialized_); + + if (this->hasSeparateWriteConnection()) + { + this->initializeConnectionSignals(this->writeConnection_.get(), + ConnectionType::Write); + this->initializeConnectionSignals(this->readConnection_.get(), + ConnectionType::Read); + } + else + { + this->initializeConnectionSignals(this->readConnection_.get(), + ConnectionType::Both); + } + + this->initialized_ = true; +} + void AbstractIrcServer::connect() { + assert(this->initialized_); + this->disconnect(); if (this->hasSeparateWriteConnection()) diff --git a/src/providers/irc/AbstractIrcServer.hpp b/src/providers/irc/AbstractIrcServer.hpp index 20d782490..1c865ef52 100644 --- a/src/providers/irc/AbstractIrcServer.hpp +++ b/src/providers/irc/AbstractIrcServer.hpp @@ -21,6 +21,10 @@ public: virtual ~AbstractIrcServer() = default; + // initializeIrc must be called from the derived class + // this allows us to initialize the abstract irc server based on the derived class's parameters + void initializeIrc(); + // connection void connect(); void disconnect(); @@ -45,8 +49,15 @@ public: protected: AbstractIrcServer(); + // initializeConnectionSignals is called on a connection once in its lifetime. + // it can be used to connect signals to your class + virtual void initializeConnectionSignals(IrcConnection *connection, + ConnectionType type){}; + + // initializeConnection is called every time before we try to connect to the irc server virtual void initializeConnection(IrcConnection *connection, ConnectionType type) = 0; + virtual std::shared_ptr createChannel( const QString &channelName) = 0; @@ -83,6 +94,8 @@ private: // bool autoReconnect_ = false; pajlada::Signals::SignalHolder connections_; + + bool initialized_{false}; }; } // namespace chatterino diff --git a/src/providers/irc/IrcServer.cpp b/src/providers/irc/IrcServer.cpp index dd7505ff9..1b3aea5fe 100644 --- a/src/providers/irc/IrcServer.cpp +++ b/src/providers/irc/IrcServer.cpp @@ -15,6 +15,8 @@ namespace chatterino { IrcServer::IrcServer(const IrcServerData &data) : data_(new IrcServerData(data)) { + this->initializeIrc(); + this->connect(); } @@ -51,6 +53,57 @@ const QString &IrcServer::nick() return this->data_->nick.isEmpty() ? this->data_->user : this->data_->nick; } +void IrcServer::initializeConnectionSignals(IrcConnection *connection, + ConnectionType type) +{ + assert(type == Both); + + QObject::connect( + connection, &Communi::IrcConnection::socketError, this, + [this](QAbstractSocket::SocketError error) { + static int index = + QAbstractSocket::staticMetaObject.indexOfEnumerator( + "SocketError"); + + std::lock_guard lock(this->channelMutex); + + for (auto &&weak : this->channels) + { + if (auto shared = weak.lock()) + { + shared->addMessage(makeSystemMessage( + QStringLiteral("Socket error: ") + + QAbstractSocket::staticMetaObject.enumerator(index) + .valueToKey(error))); + } + } + }); + + QObject::connect(connection, &Communi::IrcConnection::nickNameRequired, + this, [](const QString &reserved, QString *result) { + *result = reserved + (std::rand() % 100); + }); + + QObject::connect(connection, &Communi::IrcConnection::noticeMessageReceived, + this, [this](Communi::IrcNoticeMessage *message) { + MessageBuilder builder; + + builder.emplace(); + builder.emplace( + message->nick(), MessageElementFlag::Username); + builder.emplace( + "-> you:", MessageElementFlag::Username); + builder.emplace(message->content(), + MessageElementFlag::Text); + + auto msg = builder.release(); + + for (auto &&weak : this->channels) + if (auto shared = weak.lock()) + shared->addMessage(msg); + }); +} + void IrcServer::initializeConnection(IrcConnection *connection, ConnectionType type) { @@ -90,47 +143,6 @@ void IrcServer::initializeConnection(IrcConnection *connection, this->open(Both); } } - - QObject::connect( - connection, &Communi::IrcConnection::socketError, this, - [this](QAbstractSocket::SocketError error) { - static int index = - QAbstractSocket::staticMetaObject.indexOfEnumerator( - "SocketError"); - - std::lock_guard lock(this->channelMutex); - - for (auto &&weak : this->channels) - if (auto shared = weak.lock()) - shared->addMessage(makeSystemMessage( - QStringLiteral("Socket error: ") + - QAbstractSocket::staticMetaObject.enumerator(index) - .valueToKey(error))); - }); - - QObject::connect(connection, &Communi::IrcConnection::nickNameRequired, - this, [](const QString &reserved, QString *result) { - *result = reserved + (std::rand() % 100); - }); - - QObject::connect(connection, &Communi::IrcConnection::noticeMessageReceived, - this, [this](Communi::IrcNoticeMessage *message) { - MessageBuilder builder; - - builder.emplace(); - builder.emplace( - message->nick(), MessageElementFlag::Username); - builder.emplace( - "-> you:", MessageElementFlag::Username); - builder.emplace(message->content(), - MessageElementFlag::Text); - - auto msg = builder.release(); - - for (auto &&weak : this->channels) - if (auto shared = weak.lock()) - shared->addMessage(msg); - }); } std::shared_ptr IrcServer::createChannel(const QString &channelName) diff --git a/src/providers/irc/IrcServer.hpp b/src/providers/irc/IrcServer.hpp index 0b5a0aad5..6c1251fa8 100644 --- a/src/providers/irc/IrcServer.hpp +++ b/src/providers/irc/IrcServer.hpp @@ -21,6 +21,8 @@ public: // AbstractIrcServer interface protected: + void initializeConnectionSignals(IrcConnection *connection, + ConnectionType type) override; void initializeConnection(IrcConnection *connection, ConnectionType type) override; std::shared_ptr createChannel(const QString &channelName) override; diff --git a/src/providers/twitch/TwitchIrcServer.cpp b/src/providers/twitch/TwitchIrcServer.cpp index 7ed568c8f..0f1d4884d 100644 --- a/src/providers/twitch/TwitchIrcServer.cpp +++ b/src/providers/twitch/TwitchIrcServer.cpp @@ -27,6 +27,8 @@ TwitchIrcServer::TwitchIrcServer() , mentionsChannel(new Channel("/mentions", Channel::Type::TwitchMentions)) , watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching) { + this->initializeIrc(); + this->pubsub = new PubSub; // getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) {