mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Merge branch 'master' of https://github.com/fourtf/chatterino2
This commit is contained in:
commit
269a5500d8
|
@ -169,7 +169,8 @@ HEADERS += \
|
||||||
src/widgets/window.hpp \
|
src/widgets/window.hpp \
|
||||||
src/widgets/splitcontainer.hpp \
|
src/widgets/splitcontainer.hpp \
|
||||||
src/widgets/helper/droppreview.hpp \
|
src/widgets/helper/droppreview.hpp \
|
||||||
src/widgets/helper/splitcolumn.hpp
|
src/widgets/helper/splitcolumn.hpp \
|
||||||
|
src/util/irchelpers.hpp
|
||||||
|
|
||||||
|
|
||||||
PRECOMPILED_HEADER =
|
PRECOMPILED_HEADER =
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "accountmanager.hpp"
|
#include "accountmanager.hpp"
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "debug/log.hpp"
|
||||||
#include <pajlada/settings/setting.hpp>
|
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
@ -19,18 +18,84 @@ inline QString getEnvString(const char *target)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AccountManager::AccountManager()
|
std::shared_ptr<twitch::TwitchUser> TwitchAccountManager::getCurrent()
|
||||||
: currentUser("/accounts/current", "")
|
|
||||||
, twitchAnonymousUser("justinfan64537", "", "")
|
|
||||||
{
|
{
|
||||||
|
if (!this->currentUser) {
|
||||||
|
return this->anonymousUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QString> TwitchAccountManager::getUsernames() const
|
||||||
|
{
|
||||||
|
std::vector<QString> userNames;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex);
|
||||||
|
|
||||||
|
for (const auto &user : this->users) {
|
||||||
|
userNames.push_back(user->getUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return userNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<twitch::TwitchUser> TwitchAccountManager::findUserByUsername(
|
||||||
|
const QString &username) const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex);
|
||||||
|
|
||||||
|
for (const auto &user : this->users) {
|
||||||
|
if (username.compare(user->getUserName(), Qt::CaseInsensitive) == 0) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchAccountManager::userExists(const QString &username) const
|
||||||
|
{
|
||||||
|
return this->findUserByUsername(username) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchAccountManager::addUser(std::shared_ptr<twitch::TwitchUser> user)
|
||||||
|
{
|
||||||
|
if (this->userExists(user->getNickName())) {
|
||||||
|
// User already exists in user list
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex);
|
||||||
|
|
||||||
|
this->users.push_back(user);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountManager::AccountManager()
|
||||||
|
{
|
||||||
|
this->Twitch.anonymousUser.reset(new twitch::TwitchUser("justinfan64537", "", ""));
|
||||||
|
|
||||||
|
this->Twitch.currentUsername.getValueChangedSignal().connect([this](const auto &newValue) {
|
||||||
|
QString newUsername(QString::fromStdString(newValue));
|
||||||
|
auto user = this->Twitch.findUserByUsername(newUsername);
|
||||||
|
if (user) {
|
||||||
|
debug::Log("[AccountManager:currentUsernameChanged] User successfully updated to {}",
|
||||||
|
newUsername);
|
||||||
|
// XXX: Should we set the user regardless if the username is found or not?
|
||||||
|
// I can see the logic in setting it to nullptr if the `currentUsername` value has been
|
||||||
|
// set to "" or an invalid username
|
||||||
|
this->Twitch.currentUser = user;
|
||||||
|
this->Twitch.userChanged.invoke();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::load()
|
void AccountManager::load()
|
||||||
{
|
{
|
||||||
auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");
|
auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
for (const auto &uid : keys) {
|
for (const auto &uid : keys) {
|
||||||
if (uid == "current") {
|
if (uid == "current") {
|
||||||
continue;
|
continue;
|
||||||
|
@ -49,74 +114,20 @@ void AccountManager::load()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first) {
|
auto user =
|
||||||
this->setCurrentTwitchUser(qS(username));
|
std::make_shared<twitch::TwitchUser>(qS(username), qS(oauthToken), qS(clientID));
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
twitch::TwitchUser user(qS(username), qS(oauthToken), qS(clientID));
|
this->Twitch.addUser(user);
|
||||||
|
|
||||||
this->addTwitchUser(user);
|
|
||||||
|
|
||||||
printf("Adding user %s(%s)\n", username.c_str(), userID.c_str());
|
printf("Adding user %s(%s)\n", username.c_str(), userID.c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
twitch::TwitchUser &AccountManager::getTwitchAnon()
|
auto currentUser = this->Twitch.findUserByUsername(
|
||||||
{
|
QString::fromStdString(this->Twitch.currentUsername.getValue()));
|
||||||
return this->twitchAnonymousUser;
|
if (currentUser) {
|
||||||
}
|
this->Twitch.currentUser = currentUser;
|
||||||
|
this->Twitch.userChanged.invoke();
|
||||||
twitch::TwitchUser &AccountManager::getTwitchUser()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(this->twitchUsersMutex);
|
|
||||||
|
|
||||||
if (this->twitchUsers.size() == 0) {
|
|
||||||
return this->getTwitchAnon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString currentUsername = QString::fromStdString(this->currentUser);
|
|
||||||
|
|
||||||
for (auto &user : this->twitchUsers) {
|
|
||||||
if (user.getUserName() == currentUsername) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->twitchUsers.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountManager::setCurrentTwitchUser(const QString &username)
|
|
||||||
{
|
|
||||||
this->currentUser.setValue(username.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<twitch::TwitchUser> AccountManager::getTwitchUsers()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(this->twitchUsersMutex);
|
|
||||||
|
|
||||||
return std::vector<twitch::TwitchUser>(this->twitchUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AccountManager::removeTwitchUser(const QString &userName)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(this->twitchUsersMutex);
|
|
||||||
|
|
||||||
for (auto it = this->twitchUsers.begin(); it != this->twitchUsers.end(); it++) {
|
|
||||||
if ((*it).getUserName() == userName) {
|
|
||||||
this->twitchUsers.erase(it);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountManager::addTwitchUser(const twitch::TwitchUser &user)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(this->twitchUsersMutex);
|
|
||||||
|
|
||||||
this->twitchUsers.push_back(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -9,6 +9,34 @@
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
class AccountManager;
|
||||||
|
|
||||||
|
class TwitchAccountManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Returns the current twitchUsers, or the anonymous user if we're not currently logged in
|
||||||
|
std::shared_ptr<twitch::TwitchUser> getCurrent();
|
||||||
|
|
||||||
|
std::vector<QString> getUsernames() const;
|
||||||
|
|
||||||
|
std::shared_ptr<twitch::TwitchUser> findUserByUsername(const QString &username) const;
|
||||||
|
bool userExists(const QString &username) const;
|
||||||
|
|
||||||
|
pajlada::Settings::Setting<std::string> currentUsername = {"/accounts/current", ""};
|
||||||
|
pajlada::Signals::NoArgSignal userChanged;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool addUser(std::shared_ptr<twitch::TwitchUser> user);
|
||||||
|
|
||||||
|
std::shared_ptr<twitch::TwitchUser> currentUser;
|
||||||
|
|
||||||
|
std::shared_ptr<twitch::TwitchUser> anonymousUser;
|
||||||
|
std::vector<std::shared_ptr<twitch::TwitchUser>> users;
|
||||||
|
mutable std::mutex mutex;
|
||||||
|
|
||||||
|
friend class AccountManager;
|
||||||
|
};
|
||||||
|
|
||||||
class AccountManager
|
class AccountManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -20,30 +48,10 @@ public:
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
twitch::TwitchUser &getTwitchAnon();
|
TwitchAccountManager Twitch;
|
||||||
|
|
||||||
// Returns first user from twitchUsers, or twitchAnonymousUser if twitchUsers is empty
|
|
||||||
twitch::TwitchUser &getTwitchUser();
|
|
||||||
|
|
||||||
// Return a copy of the current available twitch users
|
|
||||||
std::vector<twitch::TwitchUser> getTwitchUsers();
|
|
||||||
|
|
||||||
// Remove twitch user with the given username
|
|
||||||
bool removeTwitchUser(const QString &userName);
|
|
||||||
|
|
||||||
void setCurrentTwitchUser(const QString &username);
|
|
||||||
|
|
||||||
// Add twitch user to the list of available twitch users
|
|
||||||
void addTwitchUser(const twitch::TwitchUser &user);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AccountManager();
|
AccountManager();
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::string> currentUser;
|
|
||||||
|
|
||||||
twitch::TwitchUser twitchAnonymousUser;
|
|
||||||
std::vector<twitch::TwitchUser> twitchUsers;
|
|
||||||
std::mutex twitchUsersMutex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -18,7 +18,6 @@ Application::Application()
|
||||||
, channelManager(this->windowManager, this->emoteManager, this->ircManager)
|
, channelManager(this->windowManager, this->emoteManager, this->ircManager)
|
||||||
, ircManager(this->channelManager, this->resources, this->emoteManager, this->windowManager)
|
, ircManager(this->channelManager, this->resources, this->emoteManager, this->windowManager)
|
||||||
{
|
{
|
||||||
// TODO(pajlada): Get rid of all singletons
|
|
||||||
logging::init();
|
logging::init();
|
||||||
SettingsManager::getInstance().load();
|
SettingsManager::getInstance().load();
|
||||||
|
|
||||||
|
@ -29,8 +28,6 @@ Application::Application()
|
||||||
|
|
||||||
AccountManager::getInstance().load();
|
AccountManager::getInstance().load();
|
||||||
|
|
||||||
this->ircManager.setUser(AccountManager::getInstance().getTwitchUser());
|
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
SettingsManager::getInstance().updateWordTypeMask();
|
SettingsManager::getInstance().updateWordTypeMask();
|
||||||
|
|
||||||
|
|
|
@ -25,3 +25,30 @@ public:
|
||||||
private:
|
private:
|
||||||
std::function<void()> action;
|
std::function<void()> action;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Taken from
|
||||||
|
// https://stackoverflow.com/questions/21646467/how-to-execute-a-functor-or-a-lambda-in-a-given-thread-in-qt-gcd-style
|
||||||
|
// Qt 5/4 - preferred, has least allocations
|
||||||
|
template <typename F>
|
||||||
|
static void postToThread(F &&fun, QObject *obj = qApp)
|
||||||
|
{
|
||||||
|
struct Event : public QEvent {
|
||||||
|
using Fun = typename std::decay<F>::type;
|
||||||
|
Fun fun;
|
||||||
|
Event(Fun &&fun)
|
||||||
|
: QEvent(QEvent::None)
|
||||||
|
, fun(std::move(fun))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Event(const Fun &fun)
|
||||||
|
: QEvent(QEvent::None)
|
||||||
|
, fun(fun)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~Event()
|
||||||
|
{
|
||||||
|
fun();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
QCoreApplication::postEvent(obj, new Event(std::forward<F>(fun)));
|
||||||
|
}
|
||||||
|
|
|
@ -136,4 +136,14 @@ WindowManager &ChannelManager::getWindowManager()
|
||||||
return this->windowManager;
|
return this->windowManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelManager::doOnAll(std::function<void(std::shared_ptr<TwitchChannel>)> func)
|
||||||
|
{
|
||||||
|
for (const auto &channel : this->twitchChannels) {
|
||||||
|
func(std::get<0>(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
func(this->whispersChannel);
|
||||||
|
func(this->mentionsChannel);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
EmoteManager &getEmoteManager();
|
EmoteManager &getEmoteManager();
|
||||||
WindowManager &getWindowManager();
|
WindowManager &getWindowManager();
|
||||||
|
|
||||||
|
void doOnAll(std::function<void(std::shared_ptr<twitch::TwitchChannel>)> func);
|
||||||
|
|
||||||
// Special channels
|
// Special channels
|
||||||
const std::shared_ptr<twitch::TwitchChannel> whispersChannel;
|
const std::shared_ptr<twitch::TwitchChannel> whispersChannel;
|
||||||
const std::shared_ptr<twitch::TwitchChannel> mentionsChannel;
|
const std::shared_ptr<twitch::TwitchChannel> mentionsChannel;
|
||||||
|
|
|
@ -505,7 +505,6 @@ void EmoteManager::loadFFZEmotes()
|
||||||
EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
||||||
{
|
{
|
||||||
return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &id] {
|
return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &id] {
|
||||||
qDebug() << "added twitch emote: " << id;
|
|
||||||
qreal scale;
|
qreal scale;
|
||||||
QString url = getTwitchEmoteLink(id, scale);
|
QString url = getTwitchEmoteLink(id, scale);
|
||||||
return new LazyLoadedImage(*this, this->windowManager, url, scale, emoteName,
|
return new LazyLoadedImage(*this, this->windowManager, url, scale, emoteName,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "asyncexec.hpp"
|
#include "asyncexec.hpp"
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "channelmanager.hpp"
|
#include "channelmanager.hpp"
|
||||||
|
#include "debug/log.hpp"
|
||||||
#include "emotemanager.hpp"
|
#include "emotemanager.hpp"
|
||||||
#include "messages/messageparseargs.hpp"
|
#include "messages/messageparseargs.hpp"
|
||||||
#include "twitch/twitchmessagebuilder.hpp"
|
#include "twitch/twitchmessagebuilder.hpp"
|
||||||
|
@ -12,7 +13,6 @@
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
|
|
||||||
#include <irccommand.h>
|
#include <irccommand.h>
|
||||||
#include <ircconnection.h>
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
@ -31,46 +31,65 @@ IrcManager::IrcManager(ChannelManager &_channelManager, Resources &_resources,
|
||||||
, resources(_resources)
|
, resources(_resources)
|
||||||
, emoteManager(_emoteManager)
|
, emoteManager(_emoteManager)
|
||||||
, windowManager(_windowManager)
|
, windowManager(_windowManager)
|
||||||
, account(AccountManager::getInstance().getTwitchAnon())
|
|
||||||
, currentUser("/accounts/current")
|
|
||||||
{
|
{
|
||||||
this->currentUser.getValueChangedSignal().connect([](const auto &newUsername) {
|
AccountManager::getInstance().Twitch.userChanged.connect([this]() {
|
||||||
// TODO: Implement
|
this->setUser(AccountManager::getInstance().Twitch.getCurrent());
|
||||||
qDebug() << "Current user changed, fetch new credentials and reconnect";
|
|
||||||
|
debug::Log("[IrcManager] Reconnecting to Twitch IRC as new user {}",
|
||||||
|
this->account->getUserName());
|
||||||
|
|
||||||
|
postToThread([this] { this->connect(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Initialize the connections
|
||||||
|
this->writeConnection.reset(new Communi::IrcConnection);
|
||||||
|
this->writeConnection->moveToThread(QCoreApplication::instance()->thread());
|
||||||
|
|
||||||
|
QObject::connect(this->writeConnection.get(), &Communi::IrcConnection::messageReceived, this,
|
||||||
|
&IrcManager::writeConnectionMessageReceived);
|
||||||
|
|
||||||
|
this->readConnection.reset(new Communi::IrcConnection);
|
||||||
|
this->readConnection->moveToThread(QCoreApplication::instance()->thread());
|
||||||
|
|
||||||
|
// Listen to read connection message signals
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::messageReceived, this,
|
||||||
|
&IrcManager::messageReceived);
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::privateMessageReceived,
|
||||||
|
this, &IrcManager::privateMessageReceived);
|
||||||
|
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::connected, this,
|
||||||
|
&IrcManager::onConnected);
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::disconnected, this,
|
||||||
|
&IrcManager::onDisconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
const twitch::TwitchUser &IrcManager::getUser() const
|
void IrcManager::setUser(std::shared_ptr<twitch::TwitchUser> newAccount)
|
||||||
{
|
{
|
||||||
return this->account;
|
this->account = newAccount;
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::setUser(const twitch::TwitchUser &account)
|
|
||||||
{
|
|
||||||
this->account = account;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::connect()
|
void IrcManager::connect()
|
||||||
{
|
{
|
||||||
disconnect();
|
this->disconnect();
|
||||||
|
|
||||||
async_exec([this] { beginConnecting(); });
|
this->initializeConnection(this->writeConnection, false);
|
||||||
|
this->initializeConnection(this->readConnection, true);
|
||||||
|
|
||||||
|
// XXX(pajlada): Disabled the async_exec for now, because if we happen to run the
|
||||||
|
// `beginConnecting` function in a different thread than last time, we won't be able to connect
|
||||||
|
// because we can't clean up the previous connection properly
|
||||||
|
// async_exec([this] { beginConnecting(); });
|
||||||
|
this->beginConnecting();
|
||||||
}
|
}
|
||||||
|
|
||||||
Communi::IrcConnection *IrcManager::createConnection(bool doRead)
|
void IrcManager::initializeConnection(const std::unique_ptr<Communi::IrcConnection> &connection,
|
||||||
|
bool isReadConnection)
|
||||||
{
|
{
|
||||||
Communi::IrcConnection *connection = new Communi::IrcConnection;
|
assert(this->account);
|
||||||
|
|
||||||
if (doRead) {
|
QString username = this->account->getUserName();
|
||||||
QObject::connect(connection, &Communi::IrcConnection::messageReceived, this,
|
QString oauthClient = this->account->getOAuthClient();
|
||||||
&IrcManager::messageReceived);
|
QString oauthToken = this->account->getOAuthToken();
|
||||||
QObject::connect(connection, &Communi::IrcConnection::privateMessageReceived, this,
|
|
||||||
&IrcManager::privateMessageReceived);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString username = this->account.getUserName();
|
|
||||||
QString oauthClient = this->account.getOAuthClient();
|
|
||||||
QString oauthToken = this->account.getOAuthToken();
|
|
||||||
if (!oauthToken.startsWith("oauth:")) {
|
if (!oauthToken.startsWith("oauth:")) {
|
||||||
oauthToken.prepend("oauth:");
|
oauthToken.prepend("oauth:");
|
||||||
}
|
}
|
||||||
|
@ -79,23 +98,27 @@ Communi::IrcConnection *IrcManager::createConnection(bool doRead)
|
||||||
connection->setNickName(username);
|
connection->setNickName(username);
|
||||||
connection->setRealName(username);
|
connection->setRealName(username);
|
||||||
|
|
||||||
if (!this->account.isAnon()) {
|
if (!this->account->isAnon()) {
|
||||||
connection->setPassword(oauthToken);
|
connection->setPassword(oauthToken);
|
||||||
|
|
||||||
this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doRead) {
|
if (isReadConnection) {
|
||||||
connection->sendCommand(
|
connection->sendCommand(
|
||||||
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
||||||
|
} else {
|
||||||
|
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
||||||
|
|
||||||
|
connection->sendCommand(
|
||||||
|
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
||||||
|
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
||||||
}
|
}
|
||||||
|
|
||||||
connection->setHost("irc.chat.twitch.tv");
|
connection->setHost("irc.chat.twitch.tv");
|
||||||
connection->setPort(6667);
|
connection->setPort(6667);
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
||||||
|
@ -136,43 +159,23 @@ void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oau
|
||||||
|
|
||||||
void IrcManager::beginConnecting()
|
void IrcManager::beginConnecting()
|
||||||
{
|
{
|
||||||
uint32_t generation = ++this->connectionGeneration;
|
|
||||||
|
|
||||||
Communi::IrcConnection *_writeConnection = this->createConnection(false);
|
|
||||||
Communi::IrcConnection *_readConnection = this->createConnection(true);
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
||||||
|
|
||||||
if (generation == this->connectionGeneration) {
|
|
||||||
this->writeConnection = std::shared_ptr<Communi::IrcConnection>(_writeConnection);
|
|
||||||
this->readConnection = std::shared_ptr<Communi::IrcConnection>(_readConnection);
|
|
||||||
|
|
||||||
this->writeConnection->moveToThread(QCoreApplication::instance()->thread());
|
|
||||||
this->readConnection->moveToThread(QCoreApplication::instance()->thread());
|
|
||||||
|
|
||||||
for (auto &channel : this->channelManager.getItems()) {
|
for (auto &channel : this->channelManager.getItems()) {
|
||||||
this->writeConnection->sendRaw("JOIN #" + channel->name);
|
this->writeConnection->sendRaw("JOIN #" + channel->name);
|
||||||
this->readConnection->sendRaw("JOIN #" + channel->name);
|
this->readConnection->sendRaw("JOIN #" + channel->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->writeConnection->open();
|
this->writeConnection->open();
|
||||||
this->readConnection->open();
|
this->readConnection->open();
|
||||||
} else {
|
|
||||||
delete _writeConnection;
|
|
||||||
delete _readConnection;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::disconnect()
|
void IrcManager::disconnect()
|
||||||
{
|
{
|
||||||
this->connectionMutex.lock();
|
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
||||||
|
|
||||||
auto _readConnection = this->readConnection;
|
this->readConnection->close();
|
||||||
auto _writeConnection = this->writeConnection;
|
this->writeConnection->close();
|
||||||
|
|
||||||
this->readConnection.reset();
|
|
||||||
this->writeConnection.reset();
|
|
||||||
|
|
||||||
this->connectionMutex.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::sendMessage(const QString &channelName, const QString &message)
|
void IrcManager::sendMessage(const QString &channelName, const QString &message)
|
||||||
|
@ -184,29 +187,6 @@ void IrcManager::sendMessage(const QString &channelName, const QString &message)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->connectionMutex.unlock();
|
this->connectionMutex.unlock();
|
||||||
|
|
||||||
// DEBUGGING
|
|
||||||
/*
|
|
||||||
Communi::IrcPrivateMessage msg(this->readConnection.get());
|
|
||||||
|
|
||||||
QStringList params{"#pajlada", message};
|
|
||||||
|
|
||||||
qDebug() << params;
|
|
||||||
|
|
||||||
if (message == "COMIC SANS LOL") {
|
|
||||||
FontManager::getInstance().currentFontFamily = "Comic Sans MS";
|
|
||||||
} else if (message == "ARIAL LOL") {
|
|
||||||
FontManager::getInstance().currentFontFamily = "Arial";
|
|
||||||
} else if (message == "WINGDINGS LOL") {
|
|
||||||
FontManager::getInstance().currentFontFamily = "Wingdings";
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.setParameters(params);
|
|
||||||
|
|
||||||
msg.setPrefix("pajlada!pajlada@pajlada");
|
|
||||||
|
|
||||||
this->privateMessageReceived(&msg);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::joinChannel(const QString &channelName)
|
void IrcManager::joinChannel(const QString &channelName)
|
||||||
|
@ -271,6 +251,18 @@ void IrcManager::messageReceived(Communi::IrcMessage *message)
|
||||||
this->handleUserNoticeMessage(message);
|
this->handleUserNoticeMessage(message);
|
||||||
} else if (command == "MODE") {
|
} else if (command == "MODE") {
|
||||||
this->handleModeMessage(message);
|
this->handleModeMessage(message);
|
||||||
|
} else if (command == "NOTICE") {
|
||||||
|
this->handleNoticeMessage(static_cast<Communi::IrcNoticeMessage *>(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcManager::writeConnectionMessageReceived(Communi::IrcMessage *message)
|
||||||
|
{
|
||||||
|
switch (message->type()) {
|
||||||
|
case Communi::IrcMessage::Type::Notice: {
|
||||||
|
this->handleWriteConnectionNoticeMessage(
|
||||||
|
static_cast<Communi::IrcNoticeMessage *>(message));
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,17 +284,59 @@ void IrcManager::handleRoomStateMessage(Communi::IrcMessage *message)
|
||||||
|
|
||||||
void IrcManager::handleClearChatMessage(Communi::IrcMessage *message)
|
void IrcManager::handleClearChatMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
// do nothing
|
assert(message->parameters().length() >= 1);
|
||||||
|
|
||||||
|
auto rawChannelName = message->parameter(0);
|
||||||
|
|
||||||
|
assert(rawChannelName.length() >= 2);
|
||||||
|
|
||||||
|
auto trimmedChannelName = rawChannelName.mid(1);
|
||||||
|
|
||||||
|
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
debug::Log("[IrcManager:handleClearChatMessage] Channel {} not found in channel manager",
|
||||||
|
trimmedChannelName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message->parameters().length() == 1) {
|
||||||
|
std::shared_ptr<Message> msg(
|
||||||
|
Message::createSystemMessage("Chat has been cleared by a moderator."));
|
||||||
|
|
||||||
|
c->addMessage(msg);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(message->parameters().length() >= 2);
|
||||||
|
|
||||||
|
QString username = message->parameter(1);
|
||||||
|
QString durationInSeconds, reason;
|
||||||
|
QVariant v = message->tag("ban-duration");
|
||||||
|
if (v.isValid()) {
|
||||||
|
durationInSeconds = v.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
v = message->tag("ban-reason");
|
||||||
|
if (v.isValid()) {
|
||||||
|
reason = v.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Message> msg(
|
||||||
|
Message::createTimeoutMessage(username, durationInSeconds, reason));
|
||||||
|
|
||||||
|
c->addMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::handleUserStateMessage(Communi::IrcMessage *message)
|
void IrcManager::handleUserStateMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
// do nothing
|
// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::handleWhisperMessage(Communi::IrcMessage *message)
|
void IrcManager::handleWhisperMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
// do nothing
|
// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcManager::handleUserNoticeMessage(Communi::IrcMessage *message)
|
void IrcManager::handleUserNoticeMessage(Communi::IrcMessage *message)
|
||||||
|
@ -312,16 +346,15 @@ void IrcManager::handleUserNoticeMessage(Communi::IrcMessage *message)
|
||||||
|
|
||||||
void IrcManager::handleModeMessage(Communi::IrcMessage *message)
|
void IrcManager::handleModeMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
auto channel = channelManager.getTwitchChannel(message->parameter(0).remove(0,1));
|
auto channel = channelManager.getTwitchChannel(message->parameter(0).remove(0, 1));
|
||||||
if(message->parameter(1) == "+o")
|
if (message->parameter(1) == "+o") {
|
||||||
{
|
|
||||||
channel->modList.append(message->parameter(2));
|
channel->modList.append(message->parameter(2));
|
||||||
} else if(message->parameter(1) == "-o")
|
} else if (message->parameter(1) == "-o") {
|
||||||
{
|
|
||||||
channel->modList.append(message->parameter(2));
|
channel->modList.append(message->parameter(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This does not fit in IrcManager
|
||||||
bool IrcManager::isTwitchBlockedUser(QString const &username)
|
bool IrcManager::isTwitchBlockedUser(QString const &username)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&this->twitchBlockedUsersMutex);
|
QMutexLocker locker(&this->twitchBlockedUsersMutex);
|
||||||
|
@ -331,11 +364,14 @@ bool IrcManager::isTwitchBlockedUser(QString const &username)
|
||||||
return iterator != this->twitchBlockedUsers.end();
|
return iterator != this->twitchBlockedUsers.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This does not fit in IrcManager
|
||||||
bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessage)
|
bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessage)
|
||||||
{
|
{
|
||||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account.getUserName() + "/blocks/" +
|
assert(this->account);
|
||||||
username + "?oauth_token=" + this->account.getOAuthToken() +
|
|
||||||
"&client_id=" + this->account.getOAuthClient());
|
QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
||||||
|
username + "?oauth_token=" + this->account->getOAuthToken() +
|
||||||
|
"&client_id=" + this->account->getOAuthClient());
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
auto reply = this->networkAccessManager.put(request, QByteArray());
|
auto reply = this->networkAccessManager.put(request, QByteArray());
|
||||||
|
@ -352,9 +388,11 @@ bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessag
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This does not fit in IrcManager
|
||||||
void IrcManager::addIgnoredUser(QString const &username)
|
void IrcManager::addIgnoredUser(QString const &username)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
|
@ -363,11 +401,14 @@ void IrcManager::addIgnoredUser(QString const &username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This does not fit in IrcManager
|
||||||
bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMessage)
|
bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMessage)
|
||||||
{
|
{
|
||||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account.getUserName() + "/blocks/" +
|
assert(this->account);
|
||||||
username + "?oauth_token=" + this->account.getOAuthToken() +
|
|
||||||
"&client_id=" + this->account.getOAuthClient());
|
QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
||||||
|
username + "?oauth_token=" + this->account->getOAuthToken() +
|
||||||
|
"&client_id=" + this->account->getOAuthClient());
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
auto reply = this->networkAccessManager.deleteResource(request);
|
auto reply = this->networkAccessManager.deleteResource(request);
|
||||||
|
@ -384,9 +425,11 @@ bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMes
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This does not fit in IrcManager
|
||||||
void IrcManager::removeIgnoredUser(QString const &username)
|
void IrcManager::removeIgnoredUser(QString const &username)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
|
@ -395,4 +438,79 @@ void IrcManager::removeIgnoredUser(QString const &username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IrcManager::handleNoticeMessage(Communi::IrcNoticeMessage *message)
|
||||||
|
{
|
||||||
|
auto rawChannelName = message->target();
|
||||||
|
|
||||||
|
assert(rawChannelName.length() >= 2);
|
||||||
|
|
||||||
|
auto trimmedChannelName = rawChannelName.mid(1);
|
||||||
|
|
||||||
|
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager",
|
||||||
|
trimmedChannelName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Message> msg(Message::createSystemMessage(message->content()));
|
||||||
|
|
||||||
|
c->addMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcManager::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message)
|
||||||
|
{
|
||||||
|
auto rawChannelName = message->target();
|
||||||
|
|
||||||
|
assert(rawChannelName.length() >= 2);
|
||||||
|
|
||||||
|
auto trimmedChannelName = rawChannelName.mid(1);
|
||||||
|
|
||||||
|
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager",
|
||||||
|
trimmedChannelName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant v = message->tag("msg-id");
|
||||||
|
if (!v.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString msg_id = v.toString();
|
||||||
|
|
||||||
|
static QList<QString> idsToSkip = {"timeout_success", "ban_success"};
|
||||||
|
|
||||||
|
if (idsToSkip.contains(msg_id)) {
|
||||||
|
// Already handled in the read-connection
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Message> msg(Message::createSystemMessage(message->content()));
|
||||||
|
|
||||||
|
c->addMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcManager::onConnected()
|
||||||
|
{
|
||||||
|
std::shared_ptr<Message> msg(Message::createSystemMessage("connected to chat"));
|
||||||
|
|
||||||
|
this->channelManager.doOnAll([msg](std::shared_ptr<twitch::TwitchChannel> channel) {
|
||||||
|
assert(channel);
|
||||||
|
channel->addMessage(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IrcManager::onDisconnected()
|
||||||
|
{
|
||||||
|
std::shared_ptr<Message> msg(Message::createSystemMessage("disconnected from chat"));
|
||||||
|
|
||||||
|
this->channelManager.doOnAll([msg](std::shared_ptr<twitch::TwitchChannel> channel) {
|
||||||
|
assert(channel);
|
||||||
|
channel->addMessage(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "messages/message.hpp"
|
#include "messages/message.hpp"
|
||||||
#include "twitch/twitchuser.hpp"
|
#include "twitch/twitchuser.hpp"
|
||||||
|
|
||||||
|
#include <ircconnection.h>
|
||||||
#include <IrcMessage>
|
#include <IrcMessage>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
@ -44,8 +45,7 @@ public:
|
||||||
void joinChannel(const QString &channelName);
|
void joinChannel(const QString &channelName);
|
||||||
void partChannel(const QString &channelName);
|
void partChannel(const QString &channelName);
|
||||||
|
|
||||||
const twitch::TwitchUser &getUser() const;
|
void setUser(std::shared_ptr<twitch::TwitchUser> newAccount);
|
||||||
void setUser(const twitch::TwitchUser &account);
|
|
||||||
|
|
||||||
pajlada::Signals::Signal<Communi::IrcPrivateMessage *> onPrivateMessage;
|
pajlada::Signals::Signal<Communi::IrcPrivateMessage *> onPrivateMessage;
|
||||||
|
|
||||||
|
@ -56,26 +56,20 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// variables
|
// variables
|
||||||
twitch::TwitchUser account;
|
std::shared_ptr<twitch::TwitchUser> account = nullptr;
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::string> currentUser;
|
std::unique_ptr<Communi::IrcConnection> writeConnection = nullptr;
|
||||||
|
std::unique_ptr<Communi::IrcConnection> readConnection = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<Communi::IrcConnection> writeConnection = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::shared_ptr<Communi::IrcConnection> readConnection = nullptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::mutex connectionMutex;
|
std::mutex connectionMutex;
|
||||||
uint32_t connectionGeneration = 0;
|
|
||||||
|
|
||||||
QMap<QString, bool> twitchBlockedUsers;
|
QMap<QString, bool> twitchBlockedUsers;
|
||||||
QMutex twitchBlockedUsersMutex;
|
QMutex twitchBlockedUsersMutex;
|
||||||
|
|
||||||
QNetworkAccessManager networkAccessManager;
|
QNetworkAccessManager networkAccessManager;
|
||||||
|
|
||||||
// methods
|
void initializeConnection(const std::unique_ptr<Communi::IrcConnection> &connection,
|
||||||
Communi::IrcConnection *createConnection(bool doRead);
|
bool isReadConnection);
|
||||||
|
|
||||||
void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
||||||
const QString &oauthToken);
|
const QString &oauthToken);
|
||||||
|
@ -85,12 +79,19 @@ private:
|
||||||
void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
||||||
void messageReceived(Communi::IrcMessage *message);
|
void messageReceived(Communi::IrcMessage *message);
|
||||||
|
|
||||||
|
void writeConnectionMessageReceived(Communi::IrcMessage *message);
|
||||||
|
|
||||||
void handleRoomStateMessage(Communi::IrcMessage *message);
|
void handleRoomStateMessage(Communi::IrcMessage *message);
|
||||||
void handleClearChatMessage(Communi::IrcMessage *message);
|
void handleClearChatMessage(Communi::IrcMessage *message);
|
||||||
void handleUserStateMessage(Communi::IrcMessage *message);
|
void handleUserStateMessage(Communi::IrcMessage *message);
|
||||||
void handleWhisperMessage(Communi::IrcMessage *message);
|
void handleWhisperMessage(Communi::IrcMessage *message);
|
||||||
void handleUserNoticeMessage(Communi::IrcMessage *message);
|
void handleUserNoticeMessage(Communi::IrcMessage *message);
|
||||||
void handleModeMessage(Communi::IrcMessage *message);
|
void handleModeMessage(Communi::IrcMessage *message);
|
||||||
|
void handleNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||||
|
void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||||
|
|
||||||
|
void onConnected();
|
||||||
|
void onDisconnected();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "ircmanager.hpp"
|
#include "ircmanager.hpp"
|
||||||
#include "messages/link.hpp"
|
#include "messages/link.hpp"
|
||||||
#include "resources.hpp"
|
#include "resources.hpp"
|
||||||
|
#include "util/irchelpers.hpp"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -70,5 +71,83 @@ const QString &Message::getId() const
|
||||||
return this->id;
|
return this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void AddCurrentTimestamp(Message *message)
|
||||||
|
{
|
||||||
|
std::time_t t;
|
||||||
|
time(&t);
|
||||||
|
char timeStampBuffer[69];
|
||||||
|
|
||||||
|
// Add word for timestamp with no seconds
|
||||||
|
strftime(timeStampBuffer, 69, "%H:%M", localtime(&t));
|
||||||
|
QString timestampNoSeconds(timeStampBuffer);
|
||||||
|
message->getWords().push_back(Word(timestampNoSeconds, Word::TimestampNoSeconds,
|
||||||
|
MessageColor(MessageColor::System), QString(), QString()));
|
||||||
|
|
||||||
|
// Add word for timestamp with seconds
|
||||||
|
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&t));
|
||||||
|
QString timestampWithSeconds(timeStampBuffer);
|
||||||
|
message->getWords().push_back(Word(timestampWithSeconds, Word::TimestampWithSeconds,
|
||||||
|
MessageColor(MessageColor::System), QString(), QString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/// Static
|
||||||
|
Message *Message::createSystemMessage(const QString &text)
|
||||||
|
{
|
||||||
|
Message *message = new Message;
|
||||||
|
|
||||||
|
AddCurrentTimestamp(message);
|
||||||
|
|
||||||
|
Word word(text, Word::Type::Default, MessageColor(MessageColor::Type::System), text, text);
|
||||||
|
|
||||||
|
message->getWords().push_back(word);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *Message::createTimeoutMessage(const QString &username, const QString &durationInSeconds,
|
||||||
|
const QString &reason)
|
||||||
|
{
|
||||||
|
Message *message = new Message;
|
||||||
|
|
||||||
|
AddCurrentTimestamp(message);
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
|
||||||
|
text.append(username);
|
||||||
|
if (!durationInSeconds.isEmpty()) {
|
||||||
|
text.append(" has been timed out");
|
||||||
|
|
||||||
|
// TODO: Implement who timed the user out
|
||||||
|
|
||||||
|
text.append(" for ");
|
||||||
|
text.append(durationInSeconds);
|
||||||
|
bool ok = true;
|
||||||
|
int timeoutDuration = durationInSeconds.toInt(&ok);
|
||||||
|
text.append(" second");
|
||||||
|
if (ok && timeoutDuration > 1) {
|
||||||
|
text.append("s");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text.append(" has been permanently banned");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason.length() > 0) {
|
||||||
|
text.append(": \"");
|
||||||
|
text.append(ParseTagString(reason));
|
||||||
|
text.append("\"");
|
||||||
|
}
|
||||||
|
text.append(".");
|
||||||
|
|
||||||
|
Word word(text, Word::Type::Default, MessageColor(MessageColor::Type::System), text, text);
|
||||||
|
|
||||||
|
message->getWords().push_back(word);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -33,6 +33,11 @@ public:
|
||||||
const QString text;
|
const QString text;
|
||||||
bool centered = false;
|
bool centered = false;
|
||||||
|
|
||||||
|
static Message *createSystemMessage(const QString &text);
|
||||||
|
|
||||||
|
static Message *createTimeoutMessage(const QString &username, const QString &durationInSeconds,
|
||||||
|
const QString &reason);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LazyLoadedImage *badgeStaff;
|
static LazyLoadedImage *badgeStaff;
|
||||||
static LazyLoadedImage *badgeAdmin;
|
static LazyLoadedImage *badgeAdmin;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace messages {
|
namespace messages {
|
||||||
|
|
||||||
MessageColor::MessageColor(const QColor &_color)
|
MessageColor::MessageColor(const QColor &_color)
|
||||||
: type(Type::Custom)
|
: type(Type::Custom)
|
||||||
, color(_color)
|
, color(_color)
|
||||||
|
@ -34,5 +35,6 @@ const QColor &MessageColor::getColor(ColorScheme &colorScheme) const
|
||||||
static QColor _default;
|
static QColor _default;
|
||||||
return _default;
|
return _default;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
} // namespace messages
|
||||||
|
} // namespace chatterino
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace messages {
|
namespace messages {
|
||||||
|
|
||||||
class MessageColor
|
class MessageColor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -21,5 +22,6 @@ private:
|
||||||
Type type;
|
Type type;
|
||||||
QColor color;
|
QColor color;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
} // namespace messages
|
||||||
|
} // namespace chatterino
|
||||||
|
|
16
src/util/irchelpers.hpp
Normal file
16
src/util/irchelpers.hpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
QString ParseTagString(const QString &input)
|
||||||
|
{
|
||||||
|
QString output = input;
|
||||||
|
|
||||||
|
// code goes here
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
|
@ -87,11 +87,18 @@ static void put(QUrl url, std::function<void(QJsonObject)> successCallback)
|
||||||
auto manager = new QNetworkAccessManager();
|
auto manager = new QNetworkAccessManager();
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
|
|
||||||
|
auto &accountManager = AccountManager::getInstance();
|
||||||
|
auto currentTwitchUser = accountManager.Twitch.getCurrent();
|
||||||
|
QByteArray oauthToken;
|
||||||
|
if (currentTwitchUser) {
|
||||||
|
oauthToken = currentTwitchUser->getOAuthToken().toUtf8();
|
||||||
|
} else {
|
||||||
|
// XXX(pajlada): Bail out?
|
||||||
|
}
|
||||||
|
|
||||||
request.setRawHeader("Client-ID", getDefaultClientID());
|
request.setRawHeader("Client-ID", getDefaultClientID());
|
||||||
request.setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
|
request.setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
|
||||||
request.setRawHeader(
|
request.setRawHeader("Authorization", "OAuth " + oauthToken);
|
||||||
"Authorization",
|
|
||||||
"OAuth " + AccountManager::getInstance().getTwitchUser().getOAuthToken().toUtf8());
|
|
||||||
|
|
||||||
NetworkManager::urlPut(std::move(request), [=](QNetworkReply *reply) {
|
NetworkManager::urlPut(std::move(request), [=](QNetworkReply *reply) {
|
||||||
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "widgets/accountpopup.hpp"
|
#include "widgets/accountpopup.hpp"
|
||||||
#include "util/urlfetch.hpp"
|
|
||||||
#include "accountmanager.hpp"
|
#include "accountmanager.hpp"
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "credentials.hpp"
|
#include "credentials.hpp"
|
||||||
#include "settingsmanager.hpp"
|
#include "settingsmanager.hpp"
|
||||||
#include "ui_accountpopupform.h"
|
#include "ui_accountpopupform.h"
|
||||||
|
#include "util/urlfetch.hpp"
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
@ -32,20 +32,16 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
||||||
SettingsManager &settings = SettingsManager::getInstance();
|
SettingsManager &settings = SettingsManager::getInstance();
|
||||||
|
|
||||||
permission = permissions::User;
|
permission = permissions::User;
|
||||||
for(auto button : this->_ui->profileLayout->findChildren<QPushButton*>())
|
for (auto button : this->_ui->profileLayout->findChildren<QPushButton *>()) {
|
||||||
{
|
|
||||||
button->setFocusProxy(this);
|
button->setFocusProxy(this);
|
||||||
}
|
}
|
||||||
for(auto button: this->_ui->userLayout->findChildren<QPushButton*>())
|
for (auto button : this->_ui->userLayout->findChildren<QPushButton *>()) {
|
||||||
{
|
|
||||||
button->setFocusProxy(this);
|
button->setFocusProxy(this);
|
||||||
}
|
}
|
||||||
for(auto button: this->_ui->modLayout->findChildren<QPushButton*>())
|
for (auto button : this->_ui->modLayout->findChildren<QPushButton *>()) {
|
||||||
{
|
|
||||||
button->setFocusProxy(this);
|
button->setFocusProxy(this);
|
||||||
}
|
}
|
||||||
for(auto button: this->_ui->ownerLayout->findChildren<QPushButton*>())
|
for (auto button : this->_ui->ownerLayout->findChildren<QPushButton *>()) {
|
||||||
{
|
|
||||||
button->setFocusProxy(this);
|
button->setFocusProxy(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,41 +56,42 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
||||||
sendCommand(this->_ui->mod, "/mod ");
|
sendCommand(this->_ui->mod, "/mod ");
|
||||||
sendCommand(this->_ui->unMod, "/unmod ");
|
sendCommand(this->_ui->unMod, "/unmod ");
|
||||||
|
|
||||||
QObject::connect(this->_ui->profile, &QPushButton::clicked, this, [=](){
|
auto &accountManager = AccountManager::getInstance();
|
||||||
QDesktopServices::openUrl(QUrl("https://twitch.tv/" +
|
QString userId;
|
||||||
this->_ui->lblUsername->text()));
|
QString userNickname;
|
||||||
|
auto currentTwitchUser = accountManager.Twitch.getCurrent();
|
||||||
|
if (currentTwitchUser) {
|
||||||
|
userId = currentTwitchUser->getUserId();
|
||||||
|
userNickname = currentTwitchUser->getNickName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(this->_ui->profile, &QPushButton::clicked, this, [=]() {
|
||||||
|
QDesktopServices::openUrl(QUrl("https://twitch.tv/" + this->_ui->lblUsername->text()));
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this->_ui->sendMessage, &QPushButton::clicked, this, [=](){
|
QObject::connect(this->_ui->sendMessage, &QPushButton::clicked, this, [=]() {
|
||||||
QDesktopServices::openUrl(QUrl("https://www.twitch.tv/message/compose?to=" +
|
QDesktopServices::openUrl(
|
||||||
this->_ui->lblUsername->text()));
|
QUrl("https://www.twitch.tv/message/compose?to=" + this->_ui->lblUsername->text()));
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this->_ui->copy, &QPushButton::clicked, this, [=](){
|
QObject::connect(this->_ui->copy, &QPushButton::clicked, this,
|
||||||
QApplication::clipboard()->setText(this->_ui->lblUsername->text());
|
[=]() { QApplication::clipboard()->setText(this->_ui->lblUsername->text()); });
|
||||||
|
|
||||||
|
QObject::connect(this->_ui->follow, &QPushButton::clicked, this, [=]() {
|
||||||
|
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + userId + "/follows/channels/" +
|
||||||
|
this->userID);
|
||||||
|
|
||||||
|
util::twitch::put(requestUrl,
|
||||||
|
[](QJsonObject obj) { qDebug() << "follows channel: " << obj; });
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this->_ui->follow, &QPushButton::clicked, this, [=](){
|
QObject::connect(this->_ui->ignore, &QPushButton::clicked, this, [=]() {
|
||||||
QUrl requestUrl("https://api.twitch.tv/kraken/users/" +
|
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + userId + "/blocks/" + this->userID);
|
||||||
AccountManager::getInstance().getTwitchUser().getUserId() +
|
|
||||||
"/follows/channels/" + this->userID);
|
|
||||||
|
|
||||||
util::twitch::put(requestUrl,[](QJsonObject obj){
|
util::twitch::put(requestUrl, [](QJsonObject obj) { qDebug() << "blocks user: " << obj; });
|
||||||
qDebug() << "follows channel: " << obj;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this->_ui->ignore, &QPushButton::clicked, this, [=](){
|
QObject::connect(this->_ui->disableHighlights, &QPushButton::clicked, this, [=, &settings]() {
|
||||||
QUrl requestUrl("https://api.twitch.tv/kraken/users/" +
|
|
||||||
AccountManager::getInstance().getTwitchUser().getUserId() +
|
|
||||||
"/blocks/" + this->userID);
|
|
||||||
|
|
||||||
util::twitch::put(requestUrl,[](QJsonObject obj){
|
|
||||||
qDebug() << "blocks user: " << obj;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
QObject::connect(this->_ui->disableHighlights, &QPushButton::clicked, this, [=, &settings](){
|
|
||||||
QString str = settings.highlightUserBlacklist.getnonConst();
|
QString str = settings.highlightUserBlacklist.getnonConst();
|
||||||
str.append(this->_ui->lblUsername->text() + "\n");
|
str.append(this->_ui->lblUsername->text() + "\n");
|
||||||
settings.highlightUserBlacklist.set(str);
|
settings.highlightUserBlacklist.set(str);
|
||||||
|
@ -102,7 +99,7 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
||||||
this->_ui->enableHighlights->show();
|
this->_ui->enableHighlights->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this->_ui->enableHighlights, &QPushButton::clicked, this, [=, &settings](){
|
QObject::connect(this->_ui->enableHighlights, &QPushButton::clicked, this, [=, &settings]() {
|
||||||
QString str = settings.highlightUserBlacklist.getnonConst();
|
QString str = settings.highlightUserBlacklist.getnonConst();
|
||||||
QStringList list = str.split("\n");
|
QStringList list = str.split("\n");
|
||||||
list.removeAll(this->_ui->lblUsername->text());
|
list.removeAll(this->_ui->lblUsername->text());
|
||||||
|
@ -111,20 +108,17 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
||||||
this->_ui->disableHighlights->show();
|
this->_ui->disableHighlights->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateButtons(this->_ui->userLayout, false);
|
||||||
updateButtons(this->_ui->userLayout,false);
|
updateButtons(this->_ui->modLayout, false);
|
||||||
updateButtons(this->_ui->modLayout,false);
|
updateButtons(this->_ui->ownerLayout, false);
|
||||||
updateButtons(this->_ui->ownerLayout,false);
|
|
||||||
|
|
||||||
// Close button
|
// Close button
|
||||||
connect(_ui->btnClose, &QPushButton::clicked, [=]() {
|
connect(_ui->btnClose, &QPushButton::clicked, [=]() {
|
||||||
hide(); //
|
hide(); //
|
||||||
});
|
});
|
||||||
|
|
||||||
util::twitch::getUserID(AccountManager::getInstance().getTwitchUser().getNickName(), this,
|
util::twitch::getUserID(userNickname, this,
|
||||||
[=](const QString &id){
|
[=](const QString &id) { currentTwitchUser->setUserId(id); });
|
||||||
AccountManager::getInstance().getTwitchUser().setUserId(id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountPopupWidget::setName(const QString &name)
|
void AccountPopupWidget::setName(const QString &name)
|
||||||
|
@ -140,7 +134,7 @@ void AccountPopupWidget::setChannel(std::shared_ptr<Channel> channel)
|
||||||
|
|
||||||
void AccountPopupWidget::getUserId()
|
void AccountPopupWidget::getUserId()
|
||||||
{
|
{
|
||||||
util::twitch::getUserID(this->_ui->lblUsername->text(), this, [=](const QString &id){
|
util::twitch::getUserID(this->_ui->lblUsername->text(), this, [=](const QString &id) {
|
||||||
userID = id;
|
userID = id;
|
||||||
getUserData();
|
getUserData();
|
||||||
});
|
});
|
||||||
|
@ -148,7 +142,8 @@ void AccountPopupWidget::getUserId()
|
||||||
|
|
||||||
void AccountPopupWidget::getUserData()
|
void AccountPopupWidget::getUserData()
|
||||||
{
|
{
|
||||||
util::twitch::get("https://api.twitch.tv/kraken/channels/" + userID, this, [=](const QJsonObject &obj){
|
util::twitch::get(
|
||||||
|
"https://api.twitch.tv/kraken/channels/" + userID, this, [=](const QJsonObject &obj) {
|
||||||
_ui->lblFollowers->setText(QString::number(obj.value("followers").toInt()));
|
_ui->lblFollowers->setText(QString::number(obj.value("followers").toInt()));
|
||||||
_ui->lblViews->setText(QString::number(obj.value("views").toInt()));
|
_ui->lblViews->setText(QString::number(obj.value("views").toInt()));
|
||||||
_ui->lblAccountAge->setText(obj.value("created_at").toString().section("T", 0, 0));
|
_ui->lblAccountAge->setText(obj.value("created_at").toString().section("T", 0, 0));
|
||||||
|
@ -185,34 +180,39 @@ void AccountPopupWidget::loadAvatar(const QUrl &avatarUrl)
|
||||||
|
|
||||||
void AccountPopupWidget::updatePermissions()
|
void AccountPopupWidget::updatePermissions()
|
||||||
{
|
{
|
||||||
if(this->_channel.get()->name == AccountManager::getInstance().getTwitchUser().getNickName())
|
AccountManager &accountManager = AccountManager::getInstance();
|
||||||
{
|
auto currentTwitchUser = accountManager.Twitch.getCurrent();
|
||||||
permission = permissions::Owner;
|
if (!currentTwitchUser) {
|
||||||
|
// No twitch user set (should never happen)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if(this->_channel->modList.contains(AccountManager::getInstance().getTwitchUser().getNickName()))
|
|
||||||
{
|
if (this->_channel.get()->name == currentTwitchUser->getNickName()) {
|
||||||
|
permission = permissions::Owner;
|
||||||
|
} else if (this->_channel->modList.contains(currentTwitchUser->getNickName())) {
|
||||||
|
// XXX(pajlada): This might always trigger if user is anonymous (if nickName is empty?)
|
||||||
permission = permissions::Mod;
|
permission = permissions::Mod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountPopupWidget::updateButtons(QWidget* layout, bool state)
|
void AccountPopupWidget::updateButtons(QWidget *layout, bool state)
|
||||||
{
|
{
|
||||||
for(auto button : layout->findChildren<QPushButton*>())
|
for (auto button : layout->findChildren<QPushButton *>()) {
|
||||||
{
|
|
||||||
button->setVisible(state);
|
button->setVisible(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountPopupWidget::timeout(QPushButton *button, int time)
|
void AccountPopupWidget::timeout(QPushButton *button, int time)
|
||||||
{
|
{
|
||||||
QObject::connect(button, &QPushButton::clicked, this, [=](){
|
QObject::connect(button, &QPushButton::clicked, this, [=]() {
|
||||||
this->_channel->sendMessage("/timeout " + this->_ui->lblUsername->text() + " " + QString::number(time));
|
this->_channel->sendMessage("/timeout " + this->_ui->lblUsername->text() + " " +
|
||||||
|
QString::number(time));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountPopupWidget::sendCommand(QPushButton *button, QString command)
|
void AccountPopupWidget::sendCommand(QPushButton *button, QString command)
|
||||||
{
|
{
|
||||||
QObject::connect(button, &QPushButton::clicked, this, [=](){
|
QObject::connect(button, &QPushButton::clicked, this, [=]() {
|
||||||
this->_channel->sendMessage(command + this->_ui->lblUsername->text());
|
this->_channel->sendMessage(command + this->_ui->lblUsername->text());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -229,42 +229,39 @@ void AccountPopupWidget::focusOutEvent(QFocusEvent *event)
|
||||||
|
|
||||||
void AccountPopupWidget::showEvent(QShowEvent *event)
|
void AccountPopupWidget::showEvent(QShowEvent *event)
|
||||||
{
|
{
|
||||||
if(this->_ui->lblUsername->text() != AccountManager::getInstance().getTwitchUser().getNickName())
|
AccountManager &accountManager = AccountManager::getInstance();
|
||||||
{
|
auto currentTwitchUser = accountManager.Twitch.getCurrent();
|
||||||
|
if (!currentTwitchUser) {
|
||||||
|
// No twitch user set (should never happen)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->_ui->lblUsername->text() != currentTwitchUser->getNickName()) {
|
||||||
updateButtons(this->_ui->userLayout, true);
|
updateButtons(this->_ui->userLayout, true);
|
||||||
if(permission != permissions::User)
|
if (permission != permissions::User) {
|
||||||
{
|
if (!this->_channel->modList.contains(this->_ui->lblUsername->text())) {
|
||||||
if(!this->_channel->modList.contains(this->_ui->lblUsername->text()))
|
|
||||||
{
|
|
||||||
updateButtons(this->_ui->modLayout, true);
|
updateButtons(this->_ui->modLayout, true);
|
||||||
}
|
}
|
||||||
if(permission == permissions::Owner)
|
if (permission == permissions::Owner) {
|
||||||
{
|
|
||||||
updateButtons(this->_ui->ownerLayout, true);
|
updateButtons(this->_ui->ownerLayout, true);
|
||||||
updateButtons(this->_ui->modLayout, true);
|
updateButtons(this->_ui->modLayout, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
updateButtons(this->_ui->modLayout, false);
|
updateButtons(this->_ui->modLayout, false);
|
||||||
updateButtons(this->_ui->userLayout, false);
|
updateButtons(this->_ui->userLayout, false);
|
||||||
updateButtons(this->_ui->ownerLayout, false);
|
updateButtons(this->_ui->ownerLayout, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString blacklisted = SettingsManager::getInstance().highlightUserBlacklist.getnonConst();
|
QString blacklisted = SettingsManager::getInstance().highlightUserBlacklist.getnonConst();
|
||||||
QStringList list = blacklisted.split("\n",QString::SkipEmptyParts);
|
QStringList list = blacklisted.split("\n", QString::SkipEmptyParts);
|
||||||
if(list.contains(this->_ui->lblUsername->text(),Qt::CaseInsensitive))
|
if (list.contains(this->_ui->lblUsername->text(), Qt::CaseInsensitive)) {
|
||||||
{
|
|
||||||
this->_ui->disableHighlights->hide();
|
this->_ui->disableHighlights->hide();
|
||||||
this->_ui->enableHighlights->show();
|
this->_ui->enableHighlights->show();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this->_ui->disableHighlights->show();
|
this->_ui->disableHighlights->show();
|
||||||
this->_ui->enableHighlights->hide();
|
this->_ui->enableHighlights->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "concurrentmap.hpp"
|
#include "concurrentmap.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
#include "twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
|
@ -35,9 +36,9 @@ private:
|
||||||
void getUserData();
|
void getUserData();
|
||||||
void loadAvatar(const QUrl &avatarUrl);
|
void loadAvatar(const QUrl &avatarUrl);
|
||||||
|
|
||||||
void updateButtons(QWidget* layout, bool state);
|
void updateButtons(QWidget *layout, bool state);
|
||||||
void timeout(QPushButton* button, int time);
|
void timeout(QPushButton *button, int time);
|
||||||
void sendCommand(QPushButton* button, QString command);
|
void sendCommand(QPushButton *button, QString command);
|
||||||
|
|
||||||
enum class permissions { User, Mod, Owner };
|
enum class permissions { User, Mod, Owner };
|
||||||
permissions permission;
|
permissions permission;
|
||||||
|
|
|
@ -802,7 +802,7 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
|
||||||
float distance = util::distanceBetweenPoints(this->lastPressPosition, event->screenPos());
|
float distance = util::distanceBetweenPoints(this->lastPressPosition, event->screenPos());
|
||||||
|
|
||||||
qDebug() << "Distance: " << distance;
|
// qDebug() << "Distance: " << distance;
|
||||||
|
|
||||||
if (fabsf(distance) > 15.f) {
|
if (fabsf(distance) > 15.f) {
|
||||||
// It wasn't a proper click, so we don't care about that here
|
// It wasn't a proper click, so we don't care about that here
|
||||||
|
|
|
@ -129,13 +129,14 @@ QVBoxLayout *SettingsDialog::createAccountsTab()
|
||||||
// listview
|
// listview
|
||||||
auto listWidget = new QListWidget(this);
|
auto listWidget = new QListWidget(this);
|
||||||
|
|
||||||
for (auto &user : AccountManager::getInstance().getTwitchUsers()) {
|
for (const auto &userName : AccountManager::getInstance().Twitch.getUsernames()) {
|
||||||
listWidget->addItem(user.getUserName());
|
listWidget->addItem(userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select the currently logged in user
|
||||||
if (listWidget->count() > 0) {
|
if (listWidget->count() > 0) {
|
||||||
const auto ¤tUser = AccountManager::getInstance().getTwitchUser();
|
const QString ¤tUsername =
|
||||||
QString currentUsername = currentUser.getUserName();
|
AccountManager::getInstance().Twitch.getCurrent()->getUserName();
|
||||||
for (int i = 0; i < listWidget->count(); ++i) {
|
for (int i = 0; i < listWidget->count(); ++i) {
|
||||||
QString itemText = listWidget->item(i)->text();
|
QString itemText = listWidget->item(i)->text();
|
||||||
if (itemText.compare(currentUsername, Qt::CaseInsensitive) == 0) {
|
if (itemText.compare(currentUsername, Qt::CaseInsensitive) == 0) {
|
||||||
|
@ -147,7 +148,8 @@ QVBoxLayout *SettingsDialog::createAccountsTab()
|
||||||
|
|
||||||
QObject::connect(listWidget, &QListWidget::clicked, this, [&, listWidget] {
|
QObject::connect(listWidget, &QListWidget::clicked, this, [&, listWidget] {
|
||||||
if (!listWidget->selectedItems().isEmpty()) {
|
if (!listWidget->selectedItems().isEmpty()) {
|
||||||
AccountManager::getInstance().setCurrentTwitchUser(listWidget->currentItem()->text());
|
QString newUsername = listWidget->currentItem()->text();
|
||||||
|
AccountManager::getInstance().Twitch.currentUsername = newUsername.toStdString();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -79,15 +79,10 @@ Split::Split(ChannelManager &_channelManager, SplitContainer *parent)
|
||||||
ezShortcut(this, "CTRL+R", &Split::doChangeChannel);
|
ezShortcut(this, "CTRL+R", &Split::doChangeChannel);
|
||||||
|
|
||||||
// xd
|
// xd
|
||||||
//ezShortcut(this, "ALT+SHIFT+RIGHT", &Split::doIncFlexX);
|
// ezShortcut(this, "ALT+SHIFT+RIGHT", &Split::doIncFlexX);
|
||||||
//ezShortcut(this, "ALT+SHIFT+LEFT", &Split::doDecFlexX);
|
// ezShortcut(this, "ALT+SHIFT+LEFT", &Split::doDecFlexX);
|
||||||
//ezShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY);
|
// ezShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY);
|
||||||
//ezShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY);
|
// ezShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// F12: Toggle message spawning
|
|
||||||
ezShortcut(this, "ALT+Q", &Split::doToggleMessageSpawning);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
this->channelName.getValueChangedSignal().connect(
|
this->channelName.getValueChangedSignal().connect(
|
||||||
std::bind(&Split::channelNameUpdated, this, std::placeholders::_1));
|
std::bind(&Split::channelNameUpdated, this, std::placeholders::_1));
|
||||||
|
@ -102,10 +97,6 @@ Split::Split(ChannelManager &_channelManager, SplitContainer *parent)
|
||||||
this->input.clearSelection();
|
this->input.clearSelection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QTimer *timer = new QTimer(this);
|
|
||||||
connect(timer, &QTimer::timeout, this, &Split::test);
|
|
||||||
timer->start(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Split::~Split()
|
Split::~Split()
|
||||||
|
@ -462,30 +453,6 @@ void Split::doCopy()
|
||||||
QApplication::clipboard()->setText(this->view.getSelectedText());
|
QApplication::clipboard()->setText(this->view.getSelectedText());
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> usernameVariants = {
|
|
||||||
"pajlada", //
|
|
||||||
"trump", //
|
|
||||||
"Chancu", //
|
|
||||||
"pajaWoman", //
|
|
||||||
"fourtf", //
|
|
||||||
"weneedmoreautisticbots", //
|
|
||||||
"fourtfbot", //
|
|
||||||
"pajbot", //
|
|
||||||
"snusbot", //
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::vector<std::string> messageVariants = {
|
|
||||||
"hehe", //
|
|
||||||
"lol pajlada", //
|
|
||||||
"hehe BANNEDWORD", //
|
|
||||||
"someone ordered pizza", //
|
|
||||||
"for ice poseidon", //
|
|
||||||
"and delivery guy said it is for enza denino", //
|
|
||||||
"!gn", //
|
|
||||||
"for my laptop", //
|
|
||||||
"should I buy a Herschel backpack?", //
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iter, typename RandomGenerator>
|
template <typename Iter, typename RandomGenerator>
|
||||||
static Iter select_randomly(Iter start, Iter end, RandomGenerator &g)
|
static Iter select_randomly(Iter start, Iter end, RandomGenerator &g)
|
||||||
{
|
{
|
||||||
|
@ -502,41 +469,6 @@ static Iter select_randomly(Iter start, Iter end)
|
||||||
return select_randomly(start, end, gen);
|
return select_randomly(start, end, gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Split::test()
|
|
||||||
{
|
|
||||||
if (this->testEnabled) {
|
|
||||||
messages::MessageParseArgs args;
|
|
||||||
|
|
||||||
auto message =
|
|
||||||
new Communi::IrcPrivateMessage(this->channelManager.ircManager.readConnection.get());
|
|
||||||
|
|
||||||
std::string text = *(select_randomly(messageVariants.begin(), messageVariants.end()));
|
|
||||||
std::string username = *(select_randomly(usernameVariants.begin(), usernameVariants.end()));
|
|
||||||
std::string usernameString = username + "!" + username + "@" + username;
|
|
||||||
|
|
||||||
QStringList params{"#pajlada", text.c_str()};
|
|
||||||
|
|
||||||
qDebug() << params;
|
|
||||||
|
|
||||||
message->setParameters(params);
|
|
||||||
|
|
||||||
message->setPrefix(usernameString.c_str());
|
|
||||||
|
|
||||||
auto twitchChannel = std::dynamic_pointer_cast<twitch::TwitchChannel>(this->channel);
|
|
||||||
|
|
||||||
twitch::TwitchMessageBuilder builder(
|
|
||||||
twitchChannel.get(), this->channelManager.ircManager.resources,
|
|
||||||
this->channelManager.emoteManager, this->channelManager.windowManager, message, args);
|
|
||||||
|
|
||||||
twitchChannel->addMessage(builder.parse());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Split::doToggleMessageSpawning()
|
|
||||||
{
|
|
||||||
this->testEnabled = !this->testEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Split::doIncFlexX()
|
void Split::doIncFlexX()
|
||||||
{
|
{
|
||||||
this->setFlexSizeX(this->getFlexSizeX() * 1.2);
|
this->setFlexSizeX(this->getFlexSizeX() * 1.2);
|
||||||
|
|
|
@ -52,7 +52,6 @@ public:
|
||||||
CompletionManager &completionManager;
|
CompletionManager &completionManager;
|
||||||
pajlada::Settings::Setting<std::string> channelName;
|
pajlada::Settings::Setting<std::string> channelName;
|
||||||
boost::signals2::signal<void()> channelChanged;
|
boost::signals2::signal<void()> channelChanged;
|
||||||
bool testEnabled = false;
|
|
||||||
|
|
||||||
std::shared_ptr<Channel> getChannel() const;
|
std::shared_ptr<Channel> getChannel() const;
|
||||||
std::shared_ptr<Channel> &getChannelRef();
|
std::shared_ptr<Channel> &getChannelRef();
|
||||||
|
@ -122,8 +121,6 @@ public slots:
|
||||||
// Open viewer list of the channel
|
// Open viewer list of the channel
|
||||||
void doOpenViewerList();
|
void doOpenViewerList();
|
||||||
|
|
||||||
void doToggleMessageSpawning();
|
|
||||||
void test();
|
|
||||||
void doIncFlexX();
|
void doIncFlexX();
|
||||||
void doDecFlexX();
|
void doDecFlexX();
|
||||||
void doIncFlexY();
|
void doIncFlexY();
|
||||||
|
|
Loading…
Reference in a new issue