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/splitcontainer.hpp \
|
||||
src/widgets/helper/droppreview.hpp \
|
||||
src/widgets/helper/splitcolumn.hpp
|
||||
src/widgets/helper/splitcolumn.hpp \
|
||||
src/util/irchelpers.hpp
|
||||
|
||||
|
||||
PRECOMPILED_HEADER =
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "accountmanager.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#include <pajlada/settings/setting.hpp>
|
||||
#include "debug/log.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
|
@ -19,18 +18,84 @@ inline QString getEnvString(const char *target)
|
|||
|
||||
} // namespace
|
||||
|
||||
AccountManager::AccountManager()
|
||||
: currentUser("/accounts/current", "")
|
||||
, twitchAnonymousUser("justinfan64537", "", "")
|
||||
std::shared_ptr<twitch::TwitchUser> TwitchAccountManager::getCurrent()
|
||||
{
|
||||
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()
|
||||
{
|
||||
auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (const auto &uid : keys) {
|
||||
if (uid == "current") {
|
||||
continue;
|
||||
|
@ -49,74 +114,20 @@ void AccountManager::load()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (first) {
|
||||
this->setCurrentTwitchUser(qS(username));
|
||||
first = false;
|
||||
}
|
||||
auto user =
|
||||
std::make_shared<twitch::TwitchUser>(qS(username), qS(oauthToken), qS(clientID));
|
||||
|
||||
twitch::TwitchUser user(qS(username), qS(oauthToken), qS(clientID));
|
||||
|
||||
this->addTwitchUser(user);
|
||||
this->Twitch.addUser(user);
|
||||
|
||||
printf("Adding user %s(%s)\n", username.c_str(), userID.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
twitch::TwitchUser &AccountManager::getTwitchAnon()
|
||||
{
|
||||
return this->twitchAnonymousUser;
|
||||
}
|
||||
|
||||
twitch::TwitchUser &AccountManager::getTwitchUser()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(this->twitchUsersMutex);
|
||||
|
||||
if (this->twitchUsers.size() == 0) {
|
||||
return this->getTwitchAnon();
|
||||
auto currentUser = this->Twitch.findUserByUsername(
|
||||
QString::fromStdString(this->Twitch.currentUsername.getValue()));
|
||||
if (currentUser) {
|
||||
this->Twitch.currentUser = currentUser;
|
||||
this->Twitch.userChanged.invoke();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -9,6 +9,34 @@
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -20,30 +48,10 @@ public:
|
|||
|
||||
void load();
|
||||
|
||||
twitch::TwitchUser &getTwitchAnon();
|
||||
|
||||
// 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);
|
||||
TwitchAccountManager Twitch;
|
||||
|
||||
private:
|
||||
AccountManager();
|
||||
|
||||
pajlada::Settings::Setting<std::string> currentUser;
|
||||
|
||||
twitch::TwitchUser twitchAnonymousUser;
|
||||
std::vector<twitch::TwitchUser> twitchUsers;
|
||||
std::mutex twitchUsersMutex;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -18,7 +18,6 @@ Application::Application()
|
|||
, channelManager(this->windowManager, this->emoteManager, this->ircManager)
|
||||
, ircManager(this->channelManager, this->resources, this->emoteManager, this->windowManager)
|
||||
{
|
||||
// TODO(pajlada): Get rid of all singletons
|
||||
logging::init();
|
||||
SettingsManager::getInstance().load();
|
||||
|
||||
|
@ -29,8 +28,6 @@ Application::Application()
|
|||
|
||||
AccountManager::getInstance().load();
|
||||
|
||||
this->ircManager.setUser(AccountManager::getInstance().getTwitchUser());
|
||||
|
||||
// XXX
|
||||
SettingsManager::getInstance().updateWordTypeMask();
|
||||
|
||||
|
|
|
@ -25,3 +25,30 @@ public:
|
|||
private:
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
EmoteManager &getEmoteManager();
|
||||
WindowManager &getWindowManager();
|
||||
|
||||
void doOnAll(std::function<void(std::shared_ptr<twitch::TwitchChannel>)> func);
|
||||
|
||||
// Special channels
|
||||
const std::shared_ptr<twitch::TwitchChannel> whispersChannel;
|
||||
const std::shared_ptr<twitch::TwitchChannel> mentionsChannel;
|
||||
|
|
|
@ -505,7 +505,6 @@ void EmoteManager::loadFFZEmotes()
|
|||
EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
||||
{
|
||||
return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &id] {
|
||||
qDebug() << "added twitch emote: " << id;
|
||||
qreal scale;
|
||||
QString url = getTwitchEmoteLink(id, scale);
|
||||
return new LazyLoadedImage(*this, this->windowManager, url, scale, emoteName,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "asyncexec.hpp"
|
||||
#include "channel.hpp"
|
||||
#include "channelmanager.hpp"
|
||||
#include "debug/log.hpp"
|
||||
#include "emotemanager.hpp"
|
||||
#include "messages/messageparseargs.hpp"
|
||||
#include "twitch/twitchmessagebuilder.hpp"
|
||||
|
@ -12,7 +13,6 @@
|
|||
#include "windowmanager.hpp"
|
||||
|
||||
#include <irccommand.h>
|
||||
#include <ircconnection.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
@ -31,46 +31,65 @@ IrcManager::IrcManager(ChannelManager &_channelManager, Resources &_resources,
|
|||
, resources(_resources)
|
||||
, emoteManager(_emoteManager)
|
||||
, windowManager(_windowManager)
|
||||
, account(AccountManager::getInstance().getTwitchAnon())
|
||||
, currentUser("/accounts/current")
|
||||
{
|
||||
this->currentUser.getValueChangedSignal().connect([](const auto &newUsername) {
|
||||
// TODO: Implement
|
||||
qDebug() << "Current user changed, fetch new credentials and reconnect";
|
||||
AccountManager::getInstance().Twitch.userChanged.connect([this]() {
|
||||
this->setUser(AccountManager::getInstance().Twitch.getCurrent());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void IrcManager::setUser(const twitch::TwitchUser &account)
|
||||
{
|
||||
this->account = account;
|
||||
this->account = newAccount;
|
||||
}
|
||||
|
||||
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) {
|
||||
QObject::connect(connection, &Communi::IrcConnection::messageReceived, this,
|
||||
&IrcManager::messageReceived);
|
||||
QObject::connect(connection, &Communi::IrcConnection::privateMessageReceived, this,
|
||||
&IrcManager::privateMessageReceived);
|
||||
}
|
||||
|
||||
QString username = this->account.getUserName();
|
||||
QString oauthClient = this->account.getOAuthClient();
|
||||
QString oauthToken = this->account.getOAuthToken();
|
||||
QString username = this->account->getUserName();
|
||||
QString oauthClient = this->account->getOAuthClient();
|
||||
QString oauthToken = this->account->getOAuthToken();
|
||||
if (!oauthToken.startsWith("oauth:")) {
|
||||
oauthToken.prepend("oauth:");
|
||||
}
|
||||
|
@ -79,23 +98,27 @@ Communi::IrcConnection *IrcManager::createConnection(bool doRead)
|
|||
connection->setNickName(username);
|
||||
connection->setRealName(username);
|
||||
|
||||
if (!this->account.isAnon()) {
|
||||
if (!this->account->isAnon()) {
|
||||
connection->setPassword(oauthToken);
|
||||
|
||||
this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
||||
}
|
||||
|
||||
if (doRead) {
|
||||
if (isReadConnection) {
|
||||
connection->sendCommand(
|
||||
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
||||
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->setPort(6667);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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);
|
||||
|
||||
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()) {
|
||||
this->writeConnection->sendRaw("JOIN #" + channel->name);
|
||||
this->readConnection->sendRaw("JOIN #" + channel->name);
|
||||
}
|
||||
this->writeConnection->open();
|
||||
this->readConnection->open();
|
||||
} else {
|
||||
delete _writeConnection;
|
||||
delete _readConnection;
|
||||
for (auto &channel : this->channelManager.getItems()) {
|
||||
this->writeConnection->sendRaw("JOIN #" + channel->name);
|
||||
this->readConnection->sendRaw("JOIN #" + channel->name);
|
||||
}
|
||||
|
||||
this->writeConnection->open();
|
||||
this->readConnection->open();
|
||||
}
|
||||
|
||||
void IrcManager::disconnect()
|
||||
{
|
||||
this->connectionMutex.lock();
|
||||
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
||||
|
||||
auto _readConnection = this->readConnection;
|
||||
auto _writeConnection = this->writeConnection;
|
||||
|
||||
this->readConnection.reset();
|
||||
this->writeConnection.reset();
|
||||
|
||||
this->connectionMutex.unlock();
|
||||
this->readConnection->close();
|
||||
this->writeConnection->close();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// 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)
|
||||
|
@ -271,6 +251,18 @@ void IrcManager::messageReceived(Communi::IrcMessage *message)
|
|||
this->handleUserNoticeMessage(message);
|
||||
} else if (command == "MODE") {
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// do nothing
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
void IrcManager::handleWhisperMessage(Communi::IrcMessage *message)
|
||||
{
|
||||
// do nothing
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
void IrcManager::handleUserNoticeMessage(Communi::IrcMessage *message)
|
||||
|
@ -312,16 +346,15 @@ void IrcManager::handleUserNoticeMessage(Communi::IrcMessage *message)
|
|||
|
||||
void IrcManager::handleModeMessage(Communi::IrcMessage *message)
|
||||
{
|
||||
auto channel = channelManager.getTwitchChannel(message->parameter(0).remove(0,1));
|
||||
if(message->parameter(1) == "+o")
|
||||
{
|
||||
channel->modList.append(message->parameter(2));
|
||||
} else if(message->parameter(1) == "-o")
|
||||
{
|
||||
channel->modList.append(message->parameter(2));
|
||||
}
|
||||
auto channel = channelManager.getTwitchChannel(message->parameter(0).remove(0, 1));
|
||||
if (message->parameter(1) == "+o") {
|
||||
channel->modList.append(message->parameter(2));
|
||||
} else if (message->parameter(1) == "-o") {
|
||||
channel->modList.append(message->parameter(2));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This does not fit in IrcManager
|
||||
bool IrcManager::isTwitchBlockedUser(QString const &username)
|
||||
{
|
||||
QMutexLocker locker(&this->twitchBlockedUsersMutex);
|
||||
|
@ -331,11 +364,14 @@ bool IrcManager::isTwitchBlockedUser(QString const &username)
|
|||
return iterator != this->twitchBlockedUsers.end();
|
||||
}
|
||||
|
||||
// XXX: This does not fit in IrcManager
|
||||
bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessage)
|
||||
{
|
||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account.getUserName() + "/blocks/" +
|
||||
username + "?oauth_token=" + this->account.getOAuthToken() +
|
||||
"&client_id=" + this->account.getOAuthClient());
|
||||
assert(this->account);
|
||||
|
||||
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);
|
||||
auto reply = this->networkAccessManager.put(request, QByteArray());
|
||||
|
@ -352,9 +388,11 @@ bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessag
|
|||
reply->deleteLater();
|
||||
|
||||
errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX: This does not fit in IrcManager
|
||||
void IrcManager::addIgnoredUser(QString const &username)
|
||||
{
|
||||
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)
|
||||
{
|
||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account.getUserName() + "/blocks/" +
|
||||
username + "?oauth_token=" + this->account.getOAuthToken() +
|
||||
"&client_id=" + this->account.getOAuthClient());
|
||||
assert(this->account);
|
||||
|
||||
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);
|
||||
auto reply = this->networkAccessManager.deleteResource(request);
|
||||
|
@ -384,9 +425,11 @@ bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMes
|
|||
reply->deleteLater();
|
||||
|
||||
errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX: This does not fit in IrcManager
|
||||
void IrcManager::removeIgnoredUser(QString const &username)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "messages/message.hpp"
|
||||
#include "twitch/twitchuser.hpp"
|
||||
|
||||
#include <ircconnection.h>
|
||||
#include <IrcMessage>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
@ -44,8 +45,7 @@ public:
|
|||
void joinChannel(const QString &channelName);
|
||||
void partChannel(const QString &channelName);
|
||||
|
||||
const twitch::TwitchUser &getUser() const;
|
||||
void setUser(const twitch::TwitchUser &account);
|
||||
void setUser(std::shared_ptr<twitch::TwitchUser> newAccount);
|
||||
|
||||
pajlada::Signals::Signal<Communi::IrcPrivateMessage *> onPrivateMessage;
|
||||
|
||||
|
@ -56,26 +56,20 @@ public:
|
|||
|
||||
private:
|
||||
// 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;
|
||||
uint32_t connectionGeneration = 0;
|
||||
|
||||
QMap<QString, bool> twitchBlockedUsers;
|
||||
QMutex twitchBlockedUsersMutex;
|
||||
|
||||
QNetworkAccessManager networkAccessManager;
|
||||
|
||||
// methods
|
||||
Communi::IrcConnection *createConnection(bool doRead);
|
||||
void initializeConnection(const std::unique_ptr<Communi::IrcConnection> &connection,
|
||||
bool isReadConnection);
|
||||
|
||||
void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
||||
const QString &oauthToken);
|
||||
|
@ -85,12 +79,19 @@ private:
|
|||
void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
||||
void messageReceived(Communi::IrcMessage *message);
|
||||
|
||||
void writeConnectionMessageReceived(Communi::IrcMessage *message);
|
||||
|
||||
void handleRoomStateMessage(Communi::IrcMessage *message);
|
||||
void handleClearChatMessage(Communi::IrcMessage *message);
|
||||
void handleUserStateMessage(Communi::IrcMessage *message);
|
||||
void handleWhisperMessage(Communi::IrcMessage *message);
|
||||
void handleUserNoticeMessage(Communi::IrcMessage *message);
|
||||
void handleModeMessage(Communi::IrcMessage *message);
|
||||
void handleNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||
void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "ircmanager.hpp"
|
||||
#include "messages/link.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "util/irchelpers.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <list>
|
||||
|
@ -70,5 +71,83 @@ const QString &Message::getId() const
|
|||
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 chatterino
|
||||
|
|
|
@ -33,6 +33,11 @@ public:
|
|||
const QString text;
|
||||
bool centered = false;
|
||||
|
||||
static Message *createSystemMessage(const QString &text);
|
||||
|
||||
static Message *createTimeoutMessage(const QString &username, const QString &durationInSeconds,
|
||||
const QString &reason);
|
||||
|
||||
private:
|
||||
static LazyLoadedImage *badgeStaff;
|
||||
static LazyLoadedImage *badgeAdmin;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace chatterino {
|
||||
namespace messages {
|
||||
|
||||
MessageColor::MessageColor(const QColor &_color)
|
||||
: type(Type::Custom)
|
||||
, color(_color)
|
||||
|
@ -34,5 +35,6 @@ const QColor &MessageColor::getColor(ColorScheme &colorScheme) const
|
|||
static QColor _default;
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
namespace chatterino {
|
||||
namespace messages {
|
||||
|
||||
class MessageColor
|
||||
{
|
||||
public:
|
||||
|
@ -21,5 +22,6 @@ private:
|
|||
Type type;
|
||||
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();
|
||||
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("Accept", "application/vnd.twitchtv.v5+json");
|
||||
request.setRawHeader(
|
||||
"Authorization",
|
||||
"OAuth " + AccountManager::getInstance().getTwitchUser().getOAuthToken().toUtf8());
|
||||
request.setRawHeader("Authorization", "OAuth " + oauthToken);
|
||||
|
||||
NetworkManager::urlPut(std::move(request), [=](QNetworkReply *reply) {
|
||||
if (reply->error() == QNetworkReply::NetworkError::NoError) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "widgets/accountpopup.hpp"
|
||||
#include "util/urlfetch.hpp"
|
||||
#include "accountmanager.hpp"
|
||||
#include "channel.hpp"
|
||||
#include "credentials.hpp"
|
||||
#include "settingsmanager.hpp"
|
||||
#include "ui_accountpopupform.h"
|
||||
#include "util/urlfetch.hpp"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
|
@ -32,20 +32,16 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
|||
SettingsManager &settings = SettingsManager::getInstance();
|
||||
|
||||
permission = permissions::User;
|
||||
for(auto button : this->_ui->profileLayout->findChildren<QPushButton*>())
|
||||
{
|
||||
for (auto button : this->_ui->profileLayout->findChildren<QPushButton *>()) {
|
||||
button->setFocusProxy(this);
|
||||
}
|
||||
for(auto button: this->_ui->userLayout->findChildren<QPushButton*>())
|
||||
{
|
||||
for (auto button : this->_ui->userLayout->findChildren<QPushButton *>()) {
|
||||
button->setFocusProxy(this);
|
||||
}
|
||||
for(auto button: this->_ui->modLayout->findChildren<QPushButton*>())
|
||||
{
|
||||
for (auto button : this->_ui->modLayout->findChildren<QPushButton *>()) {
|
||||
button->setFocusProxy(this);
|
||||
}
|
||||
for(auto button: this->_ui->ownerLayout->findChildren<QPushButton*>())
|
||||
{
|
||||
for (auto button : this->_ui->ownerLayout->findChildren<QPushButton *>()) {
|
||||
button->setFocusProxy(this);
|
||||
}
|
||||
|
||||
|
@ -60,41 +56,42 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
|||
sendCommand(this->_ui->mod, "/mod ");
|
||||
sendCommand(this->_ui->unMod, "/unmod ");
|
||||
|
||||
QObject::connect(this->_ui->profile, &QPushButton::clicked, this, [=](){
|
||||
QDesktopServices::openUrl(QUrl("https://twitch.tv/" +
|
||||
this->_ui->lblUsername->text()));
|
||||
auto &accountManager = AccountManager::getInstance();
|
||||
QString userId;
|
||||
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, [=](){
|
||||
QDesktopServices::openUrl(QUrl("https://www.twitch.tv/message/compose?to=" +
|
||||
this->_ui->lblUsername->text()));
|
||||
QObject::connect(this->_ui->sendMessage, &QPushButton::clicked, this, [=]() {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl("https://www.twitch.tv/message/compose?to=" + this->_ui->lblUsername->text()));
|
||||
});
|
||||
|
||||
QObject::connect(this->_ui->copy, &QPushButton::clicked, this, [=](){
|
||||
QApplication::clipboard()->setText(this->_ui->lblUsername->text());
|
||||
QObject::connect(this->_ui->copy, &QPushButton::clicked, this,
|
||||
[=]() { 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, [=](){
|
||||
QUrl requestUrl("https://api.twitch.tv/kraken/users/" +
|
||||
AccountManager::getInstance().getTwitchUser().getUserId() +
|
||||
"/follows/channels/" + this->userID);
|
||||
QObject::connect(this->_ui->ignore, &QPushButton::clicked, this, [=]() {
|
||||
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + userId + "/blocks/" + this->userID);
|
||||
|
||||
util::twitch::put(requestUrl,[](QJsonObject obj){
|
||||
qDebug() << "follows channel: " << obj;
|
||||
});
|
||||
util::twitch::put(requestUrl, [](QJsonObject obj) { qDebug() << "blocks user: " << obj; });
|
||||
});
|
||||
|
||||
QObject::connect(this->_ui->ignore, &QPushButton::clicked, this, [=](){
|
||||
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](){
|
||||
QObject::connect(this->_ui->disableHighlights, &QPushButton::clicked, this, [=, &settings]() {
|
||||
QString str = settings.highlightUserBlacklist.getnonConst();
|
||||
str.append(this->_ui->lblUsername->text() + "\n");
|
||||
settings.highlightUserBlacklist.set(str);
|
||||
|
@ -102,7 +99,7 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
|||
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();
|
||||
QStringList list = str.split("\n");
|
||||
list.removeAll(this->_ui->lblUsername->text());
|
||||
|
@ -111,20 +108,17 @@ AccountPopupWidget::AccountPopupWidget(std::shared_ptr<Channel> channel)
|
|||
this->_ui->disableHighlights->show();
|
||||
});
|
||||
|
||||
|
||||
updateButtons(this->_ui->userLayout,false);
|
||||
updateButtons(this->_ui->modLayout,false);
|
||||
updateButtons(this->_ui->ownerLayout,false);
|
||||
updateButtons(this->_ui->userLayout, false);
|
||||
updateButtons(this->_ui->modLayout, false);
|
||||
updateButtons(this->_ui->ownerLayout, false);
|
||||
|
||||
// Close button
|
||||
connect(_ui->btnClose, &QPushButton::clicked, [=]() {
|
||||
hide(); //
|
||||
});
|
||||
|
||||
util::twitch::getUserID(AccountManager::getInstance().getTwitchUser().getNickName(), this,
|
||||
[=](const QString &id){
|
||||
AccountManager::getInstance().getTwitchUser().setUserId(id);
|
||||
});
|
||||
util::twitch::getUserID(userNickname, this,
|
||||
[=](const QString &id) { currentTwitchUser->setUserId(id); });
|
||||
}
|
||||
|
||||
void AccountPopupWidget::setName(const QString &name)
|
||||
|
@ -140,7 +134,7 @@ void AccountPopupWidget::setChannel(std::shared_ptr<Channel> channel)
|
|||
|
||||
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;
|
||||
getUserData();
|
||||
});
|
||||
|
@ -148,13 +142,14 @@ void AccountPopupWidget::getUserId()
|
|||
|
||||
void AccountPopupWidget::getUserData()
|
||||
{
|
||||
util::twitch::get("https://api.twitch.tv/kraken/channels/" + userID, this, [=](const QJsonObject &obj){
|
||||
_ui->lblFollowers->setText(QString::number(obj.value("followers").toInt()));
|
||||
_ui->lblViews->setText(QString::number(obj.value("views").toInt()));
|
||||
_ui->lblAccountAge->setText(obj.value("created_at").toString().section("T", 0, 0));
|
||||
util::twitch::get(
|
||||
"https://api.twitch.tv/kraken/channels/" + userID, this, [=](const QJsonObject &obj) {
|
||||
_ui->lblFollowers->setText(QString::number(obj.value("followers").toInt()));
|
||||
_ui->lblViews->setText(QString::number(obj.value("views").toInt()));
|
||||
_ui->lblAccountAge->setText(obj.value("created_at").toString().section("T", 0, 0));
|
||||
|
||||
loadAvatar(QUrl(obj.value("logo").toString()));
|
||||
});
|
||||
loadAvatar(QUrl(obj.value("logo").toString()));
|
||||
});
|
||||
}
|
||||
|
||||
void AccountPopupWidget::loadAvatar(const QUrl &avatarUrl)
|
||||
|
@ -185,35 +180,40 @@ void AccountPopupWidget::loadAvatar(const QUrl &avatarUrl)
|
|||
|
||||
void AccountPopupWidget::updatePermissions()
|
||||
{
|
||||
if(this->_channel.get()->name == AccountManager::getInstance().getTwitchUser().getNickName())
|
||||
{
|
||||
permission = permissions::Owner;
|
||||
AccountManager &accountManager = AccountManager::getInstance();
|
||||
auto currentTwitchUser = accountManager.Twitch.getCurrent();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountPopupWidget::timeout(QPushButton *button, int time)
|
||||
{
|
||||
QObject::connect(button, &QPushButton::clicked, this, [=](){
|
||||
this->_channel->sendMessage("/timeout " + this->_ui->lblUsername->text() + " " + QString::number(time));
|
||||
QObject::connect(button, &QPushButton::clicked, this, [=]() {
|
||||
this->_channel->sendMessage("/timeout " + this->_ui->lblUsername->text() + " " +
|
||||
QString::number(time));
|
||||
});
|
||||
}
|
||||
|
||||
void AccountPopupWidget::sendCommand(QPushButton *button, QString command)
|
||||
{
|
||||
QObject::connect(button, &QPushButton::clicked, this, [=](){
|
||||
this->_channel->sendMessage(command + this->_ui->lblUsername->text());
|
||||
QObject::connect(button, &QPushButton::clicked, this, [=]() {
|
||||
this->_channel->sendMessage(command + this->_ui->lblUsername->text());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -229,42 +229,39 @@ void AccountPopupWidget::focusOutEvent(QFocusEvent *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);
|
||||
if(permission != permissions::User)
|
||||
{
|
||||
if(!this->_channel->modList.contains(this->_ui->lblUsername->text()))
|
||||
{
|
||||
if (permission != permissions::User) {
|
||||
if (!this->_channel->modList.contains(this->_ui->lblUsername->text())) {
|
||||
updateButtons(this->_ui->modLayout, true);
|
||||
}
|
||||
if(permission == permissions::Owner)
|
||||
{
|
||||
if (permission == permissions::Owner) {
|
||||
updateButtons(this->_ui->ownerLayout, true);
|
||||
updateButtons(this->_ui->modLayout, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
updateButtons(this->_ui->modLayout, false);
|
||||
updateButtons(this->_ui->userLayout, false);
|
||||
updateButtons(this->_ui->ownerLayout, false);
|
||||
}
|
||||
|
||||
QString blacklisted = SettingsManager::getInstance().highlightUserBlacklist.getnonConst();
|
||||
QStringList list = blacklisted.split("\n",QString::SkipEmptyParts);
|
||||
if(list.contains(this->_ui->lblUsername->text(),Qt::CaseInsensitive))
|
||||
{
|
||||
QStringList list = blacklisted.split("\n", QString::SkipEmptyParts);
|
||||
if (list.contains(this->_ui->lblUsername->text(), Qt::CaseInsensitive)) {
|
||||
this->_ui->disableHighlights->hide();
|
||||
this->_ui->enableHighlights->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this->_ui->disableHighlights->show();
|
||||
this->_ui->enableHighlights->hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace widgets
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "concurrentmap.hpp"
|
||||
#include "twitch/twitchchannel.hpp"
|
||||
|
||||
|
@ -35,9 +36,9 @@ private:
|
|||
void getUserData();
|
||||
void loadAvatar(const QUrl &avatarUrl);
|
||||
|
||||
void updateButtons(QWidget* layout, bool state);
|
||||
void timeout(QPushButton* button, int time);
|
||||
void sendCommand(QPushButton* button, QString command);
|
||||
void updateButtons(QWidget *layout, bool state);
|
||||
void timeout(QPushButton *button, int time);
|
||||
void sendCommand(QPushButton *button, QString command);
|
||||
|
||||
enum class permissions { User, Mod, Owner };
|
||||
permissions permission;
|
||||
|
|
|
@ -802,7 +802,7 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
|||
|
||||
float distance = util::distanceBetweenPoints(this->lastPressPosition, event->screenPos());
|
||||
|
||||
qDebug() << "Distance: " << distance;
|
||||
// qDebug() << "Distance: " << distance;
|
||||
|
||||
if (fabsf(distance) > 15.f) {
|
||||
// It wasn't a proper click, so we don't care about that here
|
||||
|
|
|
@ -129,13 +129,14 @@ QVBoxLayout *SettingsDialog::createAccountsTab()
|
|||
// listview
|
||||
auto listWidget = new QListWidget(this);
|
||||
|
||||
for (auto &user : AccountManager::getInstance().getTwitchUsers()) {
|
||||
listWidget->addItem(user.getUserName());
|
||||
for (const auto &userName : AccountManager::getInstance().Twitch.getUsernames()) {
|
||||
listWidget->addItem(userName);
|
||||
}
|
||||
|
||||
// Select the currently logged in user
|
||||
if (listWidget->count() > 0) {
|
||||
const auto ¤tUser = AccountManager::getInstance().getTwitchUser();
|
||||
QString currentUsername = currentUser.getUserName();
|
||||
const QString ¤tUsername =
|
||||
AccountManager::getInstance().Twitch.getCurrent()->getUserName();
|
||||
for (int i = 0; i < listWidget->count(); ++i) {
|
||||
QString itemText = listWidget->item(i)->text();
|
||||
if (itemText.compare(currentUsername, Qt::CaseInsensitive) == 0) {
|
||||
|
@ -147,7 +148,8 @@ QVBoxLayout *SettingsDialog::createAccountsTab()
|
|||
|
||||
QObject::connect(listWidget, &QListWidget::clicked, this, [&, listWidget] {
|
||||
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);
|
||||
|
||||
// xd
|
||||
//ezShortcut(this, "ALT+SHIFT+RIGHT", &Split::doIncFlexX);
|
||||
//ezShortcut(this, "ALT+SHIFT+LEFT", &Split::doDecFlexX);
|
||||
//ezShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY);
|
||||
//ezShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// F12: Toggle message spawning
|
||||
ezShortcut(this, "ALT+Q", &Split::doToggleMessageSpawning);
|
||||
#endif
|
||||
// ezShortcut(this, "ALT+SHIFT+RIGHT", &Split::doIncFlexX);
|
||||
// ezShortcut(this, "ALT+SHIFT+LEFT", &Split::doDecFlexX);
|
||||
// ezShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY);
|
||||
// ezShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY);
|
||||
|
||||
this->channelName.getValueChangedSignal().connect(
|
||||
std::bind(&Split::channelNameUpdated, this, std::placeholders::_1));
|
||||
|
@ -102,10 +97,6 @@ Split::Split(ChannelManager &_channelManager, SplitContainer *parent)
|
|||
this->input.clearSelection();
|
||||
}
|
||||
});
|
||||
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, &Split::test);
|
||||
timer->start(1000);
|
||||
}
|
||||
|
||||
Split::~Split()
|
||||
|
@ -462,30 +453,6 @@ void Split::doCopy()
|
|||
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>
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
this->setFlexSizeX(this->getFlexSizeX() * 1.2);
|
||||
|
|
|
@ -52,7 +52,6 @@ public:
|
|||
CompletionManager &completionManager;
|
||||
pajlada::Settings::Setting<std::string> channelName;
|
||||
boost::signals2::signal<void()> channelChanged;
|
||||
bool testEnabled = false;
|
||||
|
||||
std::shared_ptr<Channel> getChannel() const;
|
||||
std::shared_ptr<Channel> &getChannelRef();
|
||||
|
@ -122,8 +121,6 @@ public slots:
|
|||
// Open viewer list of the channel
|
||||
void doOpenViewerList();
|
||||
|
||||
void doToggleMessageSpawning();
|
||||
void test();
|
||||
void doIncFlexX();
|
||||
void doDecFlexX();
|
||||
void doIncFlexY();
|
||||
|
|
Loading…
Reference in a new issue