mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
credentials are now loaded when needed
This commit is contained in:
parent
d33a8b1b3a
commit
13d1fab303
15 changed files with 100 additions and 63 deletions
|
@ -79,6 +79,8 @@ void Application::initialize(Settings &settings, Paths &paths)
|
|||
assert(isAppInitialized == false);
|
||||
isAppInitialized = true;
|
||||
|
||||
Irc::getInstance().load();
|
||||
|
||||
for (auto &singleton : this->singletons_)
|
||||
{
|
||||
singleton->initialize(settings, paths);
|
||||
|
@ -98,7 +100,6 @@ int Application::run(QApplication &qtApp)
|
|||
assert(isAppInitialized);
|
||||
|
||||
this->twitch.server->connect();
|
||||
Irc::getInstance().load();
|
||||
|
||||
this->windows->getMainWindow().show();
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ Credentials::Credentials()
|
|||
}
|
||||
|
||||
void Credentials::get(const QString &provider, const QString &name_,
|
||||
QObject *receiver,
|
||||
std::function<void(const QString &)> &&onLoaded)
|
||||
{
|
||||
assertInGuiThread();
|
||||
|
@ -97,7 +98,7 @@ void Credentials::get(const QString &provider, const QString &name_,
|
|||
auto job = new QKeychain::ReadPasswordJob("chatterino");
|
||||
job->setAutoDelete(true);
|
||||
job->setKey(name);
|
||||
QObject::connect(job, &QKeychain::Job::finished, qApp,
|
||||
QObject::connect(job, &QKeychain::Job::finished, receiver,
|
||||
[job, onLoaded = std::move(onLoaded)](auto) mutable {
|
||||
onLoaded(job->textData());
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ class Credentials
|
|||
public:
|
||||
static Credentials &getInstance();
|
||||
|
||||
void get(const QString &provider, const QString &name,
|
||||
void get(const QString &provider, const QString &name, QObject *receiver,
|
||||
std::function<void(const QString &)> &&onLoaded);
|
||||
void set(const QString &provider, const QString &name,
|
||||
const QString &credential);
|
||||
|
|
|
@ -78,19 +78,26 @@ void AbstractIrcServer::connect()
|
|||
|
||||
if (this->hasSeparateWriteConnection())
|
||||
{
|
||||
this->initializeConnection(this->writeConnection_.get(), false, true);
|
||||
this->initializeConnection(this->readConnection_.get(), true, false);
|
||||
this->initializeConnection(this->writeConnection_.get(), Write);
|
||||
this->initializeConnection(this->readConnection_.get(), Read);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->initializeConnection(this->readConnection_.get(), true, true);
|
||||
this->initializeConnection(this->readConnection_.get(), Both);
|
||||
}
|
||||
}
|
||||
|
||||
// fourtf: this should be asynchronous
|
||||
void AbstractIrcServer::open(ConnectionType type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock1(this->connectionMutex_);
|
||||
std::lock_guard<std::mutex> lock2(this->channelMutex);
|
||||
|
||||
if (type == Write)
|
||||
{
|
||||
this->writeConnection_->open();
|
||||
}
|
||||
if (type & Read)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock1(this->connectionMutex_);
|
||||
std::lock_guard<std::mutex> lock2(this->channelMutex);
|
||||
|
||||
for (std::weak_ptr<Channel> &weak : this->channels.values())
|
||||
{
|
||||
if (auto channel = weak.lock())
|
||||
|
@ -98,11 +105,6 @@ void AbstractIrcServer::connect()
|
|||
this->readConnection_->sendRaw("JOIN #" + channel->getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hasSeparateWriteConnection())
|
||||
{
|
||||
this->writeConnection_->open();
|
||||
}
|
||||
this->readConnection_->open();
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +256,16 @@ void AbstractIrcServer::onReadConnected(IrcConnection *connection)
|
|||
|
||||
std::lock_guard lock(this->channelMutex);
|
||||
|
||||
// join channels
|
||||
for (auto &&weak : this->channels)
|
||||
{
|
||||
if (auto channel = weak.lock())
|
||||
{
|
||||
connection->sendRaw("JOIN #" + channel->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// connected/disconnected message
|
||||
auto connectedMsg = makeSystemMessage("connected");
|
||||
connectedMsg->flags.set(MessageFlag::ConnectedMessage);
|
||||
auto reconnected = makeSystemMessage("reconnected");
|
||||
|
|
|
@ -17,6 +17,8 @@ using ChannelPtr = std::shared_ptr<Channel>;
|
|||
class AbstractIrcServer : public QObject
|
||||
{
|
||||
public:
|
||||
enum ConnectionType { Read = 1, Write = 2, Both = 3 };
|
||||
|
||||
virtual ~AbstractIrcServer() = default;
|
||||
|
||||
// connection
|
||||
|
@ -43,8 +45,8 @@ public:
|
|||
protected:
|
||||
AbstractIrcServer();
|
||||
|
||||
virtual void initializeConnection(IrcConnection *connection, bool isRead,
|
||||
bool isWrite) = 0;
|
||||
virtual void initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type) = 0;
|
||||
virtual std::shared_ptr<Channel> createChannel(
|
||||
const QString &channelName) = 0;
|
||||
|
||||
|
@ -63,6 +65,8 @@ protected:
|
|||
virtual bool hasSeparateWriteConnection() const = 0;
|
||||
virtual QString cleanChannelName(const QString &dirtyChannelName);
|
||||
|
||||
void open(ConnectionType type);
|
||||
|
||||
QMap<QString, std::weak_ptr<Channel>> channels;
|
||||
std::mutex channelMutex;
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace {
|
|||
row[3]->data(Qt::EditRole).toString(), // user
|
||||
row[4]->data(Qt::EditRole).toString(), // nick
|
||||
row[5]->data(Qt::EditRole).toString(), // real
|
||||
original.password, // password
|
||||
original.connectCommands, // connectCommands
|
||||
original.id, // id
|
||||
};
|
||||
|
@ -70,6 +69,18 @@ inline QString getCredentialName(const IrcServerData &data)
|
|||
escape(data.host);
|
||||
}
|
||||
|
||||
void IrcServerData::getPassword(
|
||||
QObject *receiver, std::function<void(const QString &)> &&onLoaded) const
|
||||
{
|
||||
Credentials::getInstance().get("irc", getCredentialName(*this), receiver,
|
||||
std::move(onLoaded));
|
||||
}
|
||||
|
||||
void IrcServerData::setPassword(const QString &password)
|
||||
{
|
||||
Credentials::getInstance().set("irc", getCredentialName(*this), password);
|
||||
}
|
||||
|
||||
Irc::Irc()
|
||||
{
|
||||
this->connections.itemInserted.connect([this](auto &&args) {
|
||||
|
@ -99,10 +110,6 @@ Irc::Irc()
|
|||
this->servers_.emplace(args.item.id,
|
||||
std::make_unique<IrcServer>(args.item));
|
||||
}
|
||||
|
||||
// store password
|
||||
Credentials::getInstance().set("irc", getCredentialName(args.item),
|
||||
args.item.password);
|
||||
});
|
||||
|
||||
this->connections.itemRemoved.connect([this](auto &&args) {
|
||||
|
@ -217,6 +224,8 @@ void Irc::load()
|
|||
file.open(QIODevice::ReadOnly);
|
||||
auto object = QJsonDocument::fromJson(file.readAll()).object();
|
||||
|
||||
std::unordered_set<int> ids;
|
||||
|
||||
// load servers
|
||||
for (auto server : object.value("servers").toArray())
|
||||
{
|
||||
|
@ -233,18 +242,11 @@ void Irc::load()
|
|||
data.id = obj.value("id").toInt(data.id);
|
||||
|
||||
// duplicate id's are not allowed :(
|
||||
if (this->abandonedChannels_.find(data.id) ==
|
||||
this->abandonedChannels_.end())
|
||||
if (ids.find(data.id) == ids.end())
|
||||
{
|
||||
// insert element
|
||||
this->abandonedChannels_[data.id];
|
||||
ids.insert(data.id);
|
||||
|
||||
Credentials::getInstance().get(
|
||||
"irc", getCredentialName(data),
|
||||
[=](const QString &password) mutable {
|
||||
data.password = password;
|
||||
this->connections.appendItem(data);
|
||||
});
|
||||
this->connections.appendItem(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,10 @@ struct IrcServerData {
|
|||
QString real;
|
||||
|
||||
// IrcAuthType authType = Anonymous;
|
||||
QString password;
|
||||
void getPassword(QObject *receiver,
|
||||
std::function<void(const QString &)> &&onLoaded) const;
|
||||
void setPassword(const QString &password);
|
||||
|
||||
QStringList connectCommands;
|
||||
|
||||
int id;
|
||||
|
|
|
@ -20,6 +20,7 @@ void IrcChannel::sendMessage(const QString &message)
|
|||
this->server()->sendMessage(this->getName(), message);
|
||||
|
||||
MessageBuilder builder;
|
||||
builder.emplace<TimestampElement>();
|
||||
builder.emplace<TextElement>(this->server()->nick() + ":",
|
||||
MessageElementFlag::Username);
|
||||
builder.emplace<TextElement>(message, MessageElementFlag::Text);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "messages/MessageBuilder.hpp"
|
||||
#include "providers/irc/Irc2.hpp"
|
||||
#include "providers/irc/IrcChannel2.hpp"
|
||||
#include "util/QObjectRef.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
|
@ -44,13 +45,13 @@ const QString &IrcServer::user()
|
|||
|
||||
const QString &IrcServer::nick()
|
||||
{
|
||||
return this->data_->nick;
|
||||
return this->data_->nick.isEmpty() ? this->data_->user : this->data_->nick;
|
||||
}
|
||||
|
||||
void IrcServer::initializeConnection(IrcConnection *connection, bool isRead,
|
||||
bool isWrite)
|
||||
void IrcServer::initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type)
|
||||
{
|
||||
assert(isRead && isWrite);
|
||||
assert(type == Both);
|
||||
|
||||
connection->setSecure(this->data_->ssl);
|
||||
connection->setHost(this->data_->host);
|
||||
|
@ -61,7 +62,18 @@ void IrcServer::initializeConnection(IrcConnection *connection, bool isRead,
|
|||
: this->data_->nick);
|
||||
connection->setRealName(this->data_->real.isEmpty() ? this->data_->user
|
||||
: this->data_->nick);
|
||||
connection->setPassword(this->data_->password);
|
||||
|
||||
this->data_->getPassword(
|
||||
this, [conn = new QObjectRef(connection) /* can't copy */,
|
||||
this](const QString &password) mutable {
|
||||
if (*conn)
|
||||
{
|
||||
(*conn)->setPassword(password);
|
||||
this->open(Both);
|
||||
}
|
||||
|
||||
delete conn;
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<Channel> IrcServer::createChannel(const QString &channelName)
|
||||
|
@ -76,22 +88,16 @@ bool IrcServer::hasSeparateWriteConnection() const
|
|||
|
||||
void IrcServer::onReadConnected(IrcConnection *connection)
|
||||
{
|
||||
AbstractIrcServer::onReadConnected(connection);
|
||||
|
||||
std::lock_guard lock(this->channelMutex);
|
||||
|
||||
for (auto &&command : this->data_->connectCommands)
|
||||
{
|
||||
connection->sendRaw(command + "\r\n");
|
||||
}
|
||||
std::lock_guard lock(this->channelMutex);
|
||||
|
||||
for (auto &&weak : this->channels)
|
||||
{
|
||||
if (auto channel = weak.lock())
|
||||
for (auto &&command : this->data_->connectCommands)
|
||||
{
|
||||
connection->sendRaw("JOIN #" + channel->getName());
|
||||
connection->sendRaw(command + "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
AbstractIrcServer::onReadConnected(connection);
|
||||
}
|
||||
|
||||
void IrcServer::privateMessageReceived(Communi::IrcPrivateMessage *message)
|
||||
|
|
|
@ -21,8 +21,8 @@ public:
|
|||
|
||||
// AbstractIrcServer interface
|
||||
protected:
|
||||
void initializeConnection(IrcConnection *connection, bool isRead,
|
||||
bool isWrite) override;
|
||||
void initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type) override;
|
||||
std::shared_ptr<Channel> createChannel(const QString &channelName) override;
|
||||
bool hasSeparateWriteConnection() const override;
|
||||
|
||||
|
|
|
@ -63,11 +63,9 @@ void TwitchServer::initialize(Settings &settings, Paths &paths)
|
|||
this->ffz.loadEmotes();
|
||||
}
|
||||
|
||||
void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,
|
||||
bool isWrite)
|
||||
void TwitchServer::initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type)
|
||||
{
|
||||
this->singleConnection_ = isRead == isWrite;
|
||||
|
||||
std::shared_ptr<TwitchAccount> account =
|
||||
getApp()->accounts->twitch.getCurrent();
|
||||
|
||||
|
@ -97,6 +95,8 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,
|
|||
// SSL enabled: irc://irc.chat.twitch.tv:6697
|
||||
connection->setHost("irc.chat.twitch.tv");
|
||||
connection->setPort(6697);
|
||||
|
||||
this->open(type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)
|
||||
|
|
|
@ -44,8 +44,8 @@ public:
|
|||
const FfzEmotes &getFfzEmotes() const;
|
||||
|
||||
protected:
|
||||
virtual void initializeConnection(IrcConnection *connection, bool isRead,
|
||||
bool isWrite) override;
|
||||
virtual void initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type) override;
|
||||
virtual std::shared_ptr<Channel> createChannel(
|
||||
const QString &channelName) override;
|
||||
|
||||
|
@ -75,7 +75,6 @@ private:
|
|||
std::chrono::steady_clock::time_point lastErrorTimeSpeed_;
|
||||
std::chrono::steady_clock::time_point lastErrorTimeAmount_;
|
||||
|
||||
bool singleConnection_ = false;
|
||||
TwitchBadges twitchBadges;
|
||||
BttvEmotes bttv;
|
||||
FfzEmotes ffz;
|
||||
|
|
|
@ -62,8 +62,9 @@ private:
|
|||
if (other)
|
||||
{
|
||||
this->conn_ =
|
||||
QObject::connect(other, &QObject::destroyed,
|
||||
[this](QObject *) { this->set(nullptr); });
|
||||
QObject::connect(other, &QObject::destroyed, qApp,
|
||||
[this](QObject *) { this->set(nullptr); },
|
||||
Qt::DirectConnection);
|
||||
}
|
||||
|
||||
this->t_ = other;
|
||||
|
|
|
@ -28,7 +28,10 @@ IrcConnectionEditor::IrcConnectionEditor(const IrcServerData &data, bool isAdd,
|
|||
this->ui_->realNameLineEdit->setText(data.real);
|
||||
this->ui_->connectCommandsEditor->setPlainText(
|
||||
data.connectCommands.join('\n'));
|
||||
this->ui_->passwordLineEdit->setText(data.password);
|
||||
|
||||
data.getPassword(this, [this](const QString &password) {
|
||||
this->ui_->passwordLineEdit->setText(password);
|
||||
});
|
||||
|
||||
QFont font("Monospace");
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
|
@ -51,7 +54,7 @@ IrcServerData IrcConnectionEditor::data()
|
|||
data.real = this->ui_->realNameLineEdit->text();
|
||||
data.connectCommands =
|
||||
this->ui_->connectCommandsEditor->toPlainText().split('\n');
|
||||
data.password = this->ui_->passwordLineEdit->text();
|
||||
data.setPassword(this->ui_->passwordLineEdit->text());
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,11 @@
|
|||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="connectCommandsLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Send IRC commands</p><p>on connect:</p></body></html></string>
|
||||
<string>Send IRC commands
|
||||
on connect:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Loading…
Reference in a new issue