refactored the managers

This commit is contained in:
2017-12-31 00:50:07 +01:00
parent 258288bad9
commit bfa2f1637e
80 changed files with 1023 additions and 964 deletions
+190
View File
@@ -0,0 +1,190 @@
#include "twitchaccountmanager.hpp"
#include "common.hpp"
#include "const.hpp"
#include "debug/log.hpp"
namespace chatterino {
namespace twitch {
TwitchAccountManager::TwitchAccountManager()
{
this->anonymousUser.reset(new twitch::TwitchUser(twitch::ANONYMOUS_USERNAME, "", ""));
this->currentUsername.connect([this](const auto &newValue, auto) {
QString newUsername(QString::fromStdString(newValue));
auto user = this->findUserByUsername(newUsername);
if (user) {
debug::Log("[AccountManager:currentUsernameChanged] User successfully updated to {}",
newUsername);
this->currentUser = user;
} else {
debug::Log(
"[AccountManager:currentUsernameChanged] User successfully updated to anonymous");
this->currentUser = this->anonymousUser;
}
this->userChanged.invoke();
});
}
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;
}
void TwitchAccountManager::reloadUsers()
{
auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");
UserData userData;
bool listUpdated = false;
for (const auto &uid : keys) {
if (uid == "current") {
continue;
}
std::string username =
pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/username");
std::string userID =
pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/userID");
std::string clientID =
pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/clientID");
std::string oauthToken =
pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/oauthToken");
if (username.empty() || userID.empty() || clientID.empty() || oauthToken.empty()) {
continue;
}
userData.username = qS(username);
userData.userID = qS(userID);
userData.clientID = qS(clientID);
userData.oauthToken = qS(oauthToken);
switch (this->addUser(userData)) {
case AddUserResponse::UserAlreadyExists: {
debug::Log("User {} already exists", userData.username);
// Do nothing
} break;
case AddUserResponse::UserValuesUpdated: {
debug::Log("User {} already exists, and values updated!", userData.username);
if (userData.username == this->getCurrent()->getNickName()) {
debug::Log("It was the current user, so we need to reconnect stuff!");
this->userChanged.invoke();
}
} break;
case AddUserResponse::UserAdded: {
debug::Log("Added user {}", userData.username);
listUpdated = true;
} break;
}
}
if (listUpdated) {
this->userListUpdated.invoke();
}
}
bool TwitchAccountManager::removeUser(const QString &username)
{
if (!this->userExists(username)) {
return false;
}
this->mutex.lock();
this->users.erase(std::remove_if(this->users.begin(), this->users.end(), [username](auto user) {
if (user->getNickName() == username) {
std::string userID(user->getUserId().toStdString());
assert(!userID.empty());
pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + userID);
return true;
}
return false;
}));
this->mutex.unlock();
if (username == qS(this->currentUsername.getValue())) {
// The user that was removed is the current user, log into the anonymous user
this->currentUsername = "";
}
this->userListUpdated.invoke();
return true;
}
TwitchAccountManager::AddUserResponse TwitchAccountManager::addUser(
const TwitchAccountManager::UserData &userData)
{
auto previousUser = this->findUserByUsername(userData.username);
if (previousUser) {
bool userUpdated = false;
if (previousUser->setOAuthClient(userData.clientID)) {
userUpdated = true;
}
if (previousUser->setOAuthToken(userData.oauthToken)) {
userUpdated = true;
}
if (userUpdated) {
return AddUserResponse::UserValuesUpdated;
} else {
return AddUserResponse::UserAlreadyExists;
}
}
auto newUser = std::make_shared<twitch::TwitchUser>(userData.username, userData.oauthToken,
userData.clientID);
// Set users User ID without the uid prefix
newUser->setUserId(userData.userID);
std::lock_guard<std::mutex> lock(this->mutex);
this->users.push_back(newUser);
return AddUserResponse::UserAdded;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include "twitch/twitchuser.hpp"
#include <pajlada/settings/setting.hpp>
#include <mutex>
#include <vector>
//
// Warning: This class is not supposed to be created directly.
// Get yourself an instance from our friends over at AccountManager.hpp
//
namespace chatterino {
class AccountManager;
namespace twitch {
class TwitchAccountManager
{
TwitchAccountManager();
public:
struct UserData {
QString username;
QString userID;
QString clientID;
QString oauthToken;
};
// 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;
void reloadUsers();
bool removeUser(const QString &username);
pajlada::Settings::Setting<std::string> currentUsername = {"/accounts/current", ""};
pajlada::Signals::NoArgSignal userChanged;
pajlada::Signals::NoArgSignal userListUpdated;
private:
enum class AddUserResponse {
UserAlreadyExists,
UserValuesUpdated,
UserAdded,
};
AddUserResponse addUser(const UserData &data);
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 chatterino::AccountManager;
};
}
}
+7 -11
View File
@@ -1,6 +1,6 @@
#include "twitchchannel.hpp"
#include "debug/log.hpp"
#include "emotemanager.hpp"
#include "singletons/emotemanager.hpp"
#include "util/urlfetch.hpp"
#include <QThread>
@@ -9,24 +9,20 @@
namespace chatterino {
namespace twitch {
TwitchChannel::TwitchChannel(IrcManager &ircManager, const QString &channelName, bool _isSpecial)
TwitchChannel::TwitchChannel(const QString &channelName)
: Channel(channelName)
, ircManager(ircManager)
, bttvChannelEmotes(new EmoteMap)
, ffzChannelEmotes(new EmoteMap)
, subscriptionURL("https://www.twitch.tv/subs/" + name)
, channelURL("https://twitch.tv/" + name)
, popoutPlayerURL("https://player.twitch.tv/?channel=" + name)
, isLive(false)
, isSpecial(_isSpecial)
{
debug::Log("[TwitchChannel:{}] Opened", this->name);
this->dontAddMessages = true;
if (!this->isSpecial) {
this->reloadChannelEmotes();
}
this->reloadChannelEmotes();
this->liveStatusTimer = new QTimer;
QObject::connect(this->liveStatusTimer, &QTimer::timeout, [this]() {
@@ -56,7 +52,7 @@ bool TwitchChannel::isEmpty() const
bool TwitchChannel::canSendMessage() const
{
return !this->isEmpty() && !this->isSpecial;
return !this->isEmpty();
}
void TwitchChannel::setRoomID(const QString &_roomID)
@@ -85,7 +81,7 @@ void TwitchChannel::sendMessage(const QString &message)
// Do last message processing
QString parsedMessage = emoteManager.replaceShortCodes(message);
this->ircManager.sendMessage(this->name, parsedMessage);
IrcManager::getInstance().sendMessage(this->name, parsedMessage);
}
void TwitchChannel::setLive(bool newLiveStatus)
@@ -159,7 +155,7 @@ void TwitchChannel::fetchRecentMessages()
{
static QString genericURL =
"https://tmi.twitch.tv/api/rooms/%1/recent_messages?client_id=" + getDefaultClientID();
static auto readConnection = this->ircManager.getReadConnection();
static auto readConnection = IrcManager::getInstance().getReadConnection();
util::twitch::get(genericURL.arg(roomID), QThread::currentThread(), [=](QJsonObject obj) {
this->dontAddMessages = false;
@@ -169,7 +165,7 @@ void TwitchChannel::fetchRecentMessages()
QByteArray content = msgArray[i].toString().toUtf8();
auto msg = Communi::IrcMessage::fromData(content, readConnection);
auto privMsg = static_cast<Communi::IrcPrivateMessage *>(msg);
this->ircManager.privateMessageReceived(privMsg);
IrcManager::getInstance().privateMessageReceived(privMsg);
}
});
}
+5 -9
View File
@@ -2,7 +2,8 @@
#include "channel.hpp"
#include "concurrentmap.hpp"
#include "ircmanager.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/ircmanager.hpp"
namespace chatterino {
namespace twitch {
@@ -12,8 +13,7 @@ class TwitchChannel : public Channel
QTimer *liveStatusTimer;
public:
explicit TwitchChannel(IrcManager &ircManager, const QString &channelName,
bool _isSpecial = false);
explicit TwitchChannel(const QString &channelName);
~TwitchChannel();
void reloadChannelEmotes();
@@ -22,8 +22,8 @@ public:
bool canSendMessage() const override;
void sendMessage(const QString &message) override;
const std::shared_ptr<EmoteMap> bttvChannelEmotes;
const std::shared_ptr<EmoteMap> ffzChannelEmotes;
const std::shared_ptr<chatterino::EmoteMap> bttvChannelEmotes;
const std::shared_ptr<chatterino::EmoteMap> ffzChannelEmotes;
const QString subscriptionURL;
const QString channelURL;
@@ -47,10 +47,6 @@ private:
void refreshLiveStatus();
void fetchRecentMessages();
IrcManager &ircManager;
bool isSpecial;
};
} // namespace twitch
+48 -42
View File
@@ -1,11 +1,12 @@
#include "twitch/twitchmessagebuilder.hpp"
#include "colorscheme.hpp"
#include "twitchmessagebuilder.hpp"
#include "debug/log.hpp"
#include "emotemanager.hpp"
#include "ircmanager.hpp"
#include "resources.hpp"
#include "settingsmanager.hpp"
#include "windowmanager.hpp"
#include "singletons/emotemanager.hpp"
#include "singletons/ircmanager.hpp"
#include "singletons/settingsmanager.hpp"
#include "singletons/thememanager.hpp"
#include "singletons/windowmanager.hpp"
#include "twitch/twitchchannel.hpp"
#include <QApplication>
#include <QDebug>
@@ -16,19 +17,15 @@ using namespace chatterino::messages;
namespace chatterino {
namespace twitch {
TwitchMessageBuilder::TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
WindowManager &_windowManager,
TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel,
const Communi::IrcPrivateMessage *_ircMessage,
const messages::MessageParseArgs &_args)
: channel(_channel)
, twitchChannel(_channel)
, resources(_resources)
, windowManager(_windowManager)
, colorScheme(this->windowManager.colorScheme)
, twitchChannel(dynamic_cast<TwitchChannel *>(_channel))
, ircMessage(_ircMessage)
, args(_args)
, tags(this->ircMessage->tags())
, usernameColor(this->colorScheme.SystemMessageColor)
, usernameColor(ThemeManager::getInstance().SystemMessageColor)
{
}
@@ -42,7 +39,7 @@ SharedMessage TwitchMessageBuilder::parse()
this->parseUsername();
// this->message->setCollapsedDefault(true);
// this->appendWord(Word(this->resources.badgeCollapsed, Word::Collapsed, QString(),
// this->appendWord(Word(Resources::getInstance().badgeCollapsed, Word::Collapsed, QString(),
// QString()));
// The timestamp is always appended to the builder
@@ -268,6 +265,10 @@ void TwitchMessageBuilder::parseMessageID()
void TwitchMessageBuilder::parseRoomID()
{
if (this->twitchChannel == nullptr) {
return;
}
auto iterator = this->tags.find("room-id");
if (iterator != std::end(this->tags)) {
@@ -470,7 +471,7 @@ void TwitchMessageBuilder::parseHighlights()
}
if (doAlert) {
QApplication::alert(windowManager.getMainWindow().window(), 2500);
QApplication::alert(WindowManager::getInstance().getMainWindow().window(), 2500);
}
}
}
@@ -481,9 +482,9 @@ void TwitchMessageBuilder::appendModerationButtons()
static QString buttonBanTooltip("Ban user");
static QString buttonTimeoutTooltip("Timeout user");
this->appendWord(Word(this->resources.buttonBan, Word::ButtonBan, QString(), buttonBanTooltip,
Link(Link::UserBan, ircMessage->account())));
this->appendWord(Word(this->resources.buttonTimeout, Word::ButtonTimeout, QString(),
this->appendWord(Word(Resources::getInstance().buttonBan, Word::ButtonBan, QString(),
buttonBanTooltip, Link(Link::UserBan, ircMessage->account())));
this->appendWord(Word(Resources::getInstance().buttonTimeout, Word::ButtonTimeout, QString(),
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
}
@@ -535,13 +536,15 @@ bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString)
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) {
// BTTV Global Emote
return this->appendEmote(emoteData);
} else if (this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) {
} else if (this->twitchChannel != nullptr &&
this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) {
// BTTV Channel Emote
return this->appendEmote(emoteData);
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) {
// FFZ Global Emote
return this->appendEmote(emoteData);
} else if (this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) {
} else if (this->twitchChannel != nullptr &&
this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) {
// FFZ Channel Emote
return this->appendEmote(emoteData);
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) {
@@ -564,7 +567,7 @@ bool TwitchMessageBuilder::appendEmote(EmoteData &emoteData)
void TwitchMessageBuilder::parseTwitchBadges()
{
const auto &channelResources = this->resources.channels[this->roomID];
const auto &channelResources = Resources::getInstance().channels[this->roomID];
auto iterator = this->tags.find("badges");
@@ -581,7 +584,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
}
if (badge.startsWith("bits/")) {
if (!this->resources.dynamicBadgesLoaded) {
if (!Resources::getInstance().dynamicBadgesLoaded) {
// Do nothing
continue;
}
@@ -590,7 +593,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
std::string versionKey = cheerAmountQS.toStdString();
try {
auto &badgeSet = this->resources.badgeSets.at("bits");
auto &badgeSet = Resources::getInstance().badgeSets.at("bits");
try {
auto &badgeVersion = badgeSet.versions.at(versionKey);
@@ -606,34 +609,35 @@ void TwitchMessageBuilder::parseTwitchBadges()
debug::Log("No badge set with key bits. Exception: {}", e.what());
}
} else if (badge == "staff/1") {
appendWord(Word(this->resources.badgeStaff, Word::BadgeGlobalAuthority, QString(),
QString("Twitch Staff")));
appendWord(Word(Resources::getInstance().badgeStaff, Word::BadgeGlobalAuthority,
QString(), QString("Twitch Staff")));
} else if (badge == "admin/1") {
appendWord(Word(this->resources.badgeAdmin, Word::BadgeGlobalAuthority, QString(),
QString("Twitch Admin")));
appendWord(Word(Resources::getInstance().badgeAdmin, Word::BadgeGlobalAuthority,
QString(), QString("Twitch Admin")));
} else if (badge == "global_mod/1") {
appendWord(Word(this->resources.badgeGlobalModerator, Word::BadgeGlobalAuthority,
QString(), QString("Global Moderator")));
appendWord(Word(Resources::getInstance().badgeGlobalModerator,
Word::BadgeGlobalAuthority, QString(), QString("Global Moderator")));
} else if (badge == "moderator/1") {
// TODO: Implement custom FFZ moderator badge
appendWord(Word(this->resources.badgeModerator, Word::BadgeChannelAuthority, QString(),
appendWord(Word(Resources::getInstance().badgeModerator, Word::BadgeChannelAuthority,
QString(),
QString("Channel Moderator"))); // custom badge
} else if (badge == "turbo/1") {
appendWord(Word(this->resources.badgeTurbo, Word::BadgeVanity, QString(),
appendWord(Word(Resources::getInstance().badgeTurbo, Word::BadgeVanity, QString(),
QString("Turbo Subscriber")));
} else if (badge == "broadcaster/1") {
appendWord(Word(this->resources.badgeBroadcaster, Word::BadgeChannelAuthority,
appendWord(Word(Resources::getInstance().badgeBroadcaster, Word::BadgeChannelAuthority,
QString(), QString("Channel Broadcaster")));
} else if (badge == "premium/1") {
appendWord(Word(this->resources.badgePremium, Word::BadgeVanity, QString(),
appendWord(Word(Resources::getInstance().badgePremium, Word::BadgeVanity, QString(),
QString("Twitch Prime")));
} else if (badge.startsWith("partner/")) {
int index = badge.midRef(8).toInt();
switch (index) {
case 1: {
appendWord(Word(this->resources.badgeVerified, Word::BadgeVanity, QString(),
"Twitch Verified"));
appendWord(Word(Resources::getInstance().badgeVerified, Word::BadgeVanity,
QString(), "Twitch Verified"));
} break;
default: {
printf("[TwitchMessageBuilder] Unhandled partner badge index: %d\n", index);
@@ -648,8 +652,9 @@ void TwitchMessageBuilder::parseTwitchBadges()
auto badgeSetIt = channelResources.badgeSets.find("subscriber");
if (badgeSetIt == channelResources.badgeSets.end()) {
// Fall back to default badge
appendWord(Word(this->resources.badgeSubscriber, Word::Flags::BadgeSubscription,
QString(), QString("Twitch Subscriber")));
appendWord(Word(Resources::getInstance().badgeSubscriber,
Word::Flags::BadgeSubscription, QString(),
QString("Twitch Subscriber")));
continue;
}
@@ -661,8 +666,9 @@ void TwitchMessageBuilder::parseTwitchBadges()
if (badgeVersionIt == badgeSet.versions.end()) {
// Fall back to default badge
appendWord(Word(this->resources.badgeSubscriber, Word::Flags::BadgeSubscription,
QString(), QString("Twitch Subscriber")));
appendWord(Word(Resources::getInstance().badgeSubscriber,
Word::Flags::BadgeSubscription, QString(),
QString("Twitch Subscriber")));
continue;
}
@@ -671,7 +677,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
appendWord(Word(badgeVersion.badgeImage1x, Word::Flags::BadgeSubscription, QString(),
QString("Twitch " + QString::fromStdString(badgeVersion.title))));
} else {
if (!this->resources.dynamicBadgesLoaded) {
if (!Resources::getInstance().dynamicBadgesLoaded) {
// Do nothing
continue;
}
@@ -689,7 +695,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
std::string versionKey = parts[1].toStdString();
try {
auto &badgeSet = this->resources.badgeSets.at(badgeSetKey);
auto &badgeSet = Resources::getInstance().badgeSets.at(badgeSetKey);
try {
auto &badgeVersion = badgeSet.versions.at(versionKey);
@@ -711,7 +717,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
void TwitchMessageBuilder::parseChatterinoBadges()
{
auto &badges = this->resources.chatterinoBadges;
auto &badges = Resources::getInstance().chatterinoBadges;
auto it = badges.find(this->userName.toStdString());
if (it == badges.end()) {
+6 -9
View File
@@ -2,8 +2,9 @@
#include "messages/messagebuilder.hpp"
#include "messages/messageparseargs.hpp"
#include "resources.hpp"
#include "twitch/twitchchannel.hpp"
#include "singletons/emotemanager.hpp"
#include <IrcMessage>
#include <QString>
#include <QVariant>
@@ -12,9 +13,10 @@ namespace chatterino {
class WindowManager;
class Channel;
class ColorScheme;
class ThemeManager;
namespace twitch {
class TwitchChannel;
class TwitchMessageBuilder : public messages::MessageBuilder
{
@@ -27,16 +29,11 @@ public:
TwitchMessageBuilder() = delete;
explicit TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
WindowManager &_windowManager,
const Communi::IrcPrivateMessage *_ircMessage,
explicit TwitchMessageBuilder(Channel *_channel, const Communi::IrcPrivateMessage *_ircMessage,
const messages::MessageParseArgs &_args);
Channel *channel;
TwitchChannel *twitchChannel;
Resources &resources;
WindowManager &windowManager;
ColorScheme &colorScheme;
const Communi::IrcPrivateMessage *ircMessage;
messages::MessageParseArgs args;
const QVariantMap tags;
+2 -2
View File
@@ -1,8 +1,8 @@
//#include "twitchparsemessage.hpp"
//#include "colorscheme.hpp"
//#include "emojis.hpp"
//#include "emotemanager.hpp"
//#include "ircmanager.hpp"
//#include "singletons/emotemanager.hpp"
//#include "singletons/ircmanager.hpp"
//#include "resources.hpp"
//#include "twitch/twitchmessagebuilder.hpp"
//