Merge branch 'master' into irc-support

This commit is contained in:
fourtf
2019-09-18 13:03:16 +02:00
204 changed files with 17026 additions and 16467 deletions
+7 -7
View File
@@ -1,7 +1,7 @@
#include "DebugCount.hpp"
namespace chatterino {
UniqueAccess<QMap<QString, int64_t>> DebugCount::counts_;
} // namespace chatterino
#include "DebugCount.hpp"
namespace chatterino {
UniqueAccess<QMap<QString, int64_t>> DebugCount::counts_;
} // namespace chatterino
+67 -67
View File
@@ -1,67 +1,67 @@
#pragma once
#include <common/UniqueAccess.hpp>
#include <mutex>
#include <typeinfo>
#include <QMap>
#include <QString>
namespace chatterino {
class DebugCount
{
public:
static void increase(const QString &name)
{
auto counts = counts_.access();
auto it = counts->find(name);
if (it == counts->end())
{
counts->insert(name, 1);
}
else
{
reinterpret_cast<int64_t &>(it.value())++;
}
}
static void decrease(const QString &name)
{
auto counts = counts_.access();
auto it = counts->find(name);
if (it == counts->end())
{
counts->insert(name, -1);
}
else
{
reinterpret_cast<int64_t &>(it.value())--;
}
}
static QString getDebugText()
{
auto counts = counts_.access();
QString text;
for (auto it = counts->begin(); it != counts->end(); it++)
{
text += it.key() + ": " + QString::number(it.value()) + "\n";
}
return text;
}
QString toString()
{
return "";
}
private:
static UniqueAccess<QMap<QString, int64_t>> counts_;
};
} // namespace chatterino
#pragma once
#include <common/UniqueAccess.hpp>
#include <mutex>
#include <typeinfo>
#include <QMap>
#include <QString>
namespace chatterino {
class DebugCount
{
public:
static void increase(const QString &name)
{
auto counts = counts_.access();
auto it = counts->find(name);
if (it == counts->end())
{
counts->insert(name, 1);
}
else
{
reinterpret_cast<int64_t &>(it.value())++;
}
}
static void decrease(const QString &name)
{
auto counts = counts_.access();
auto it = counts->find(name);
if (it == counts->end())
{
counts->insert(name, -1);
}
else
{
reinterpret_cast<int64_t &>(it.value())--;
}
}
static QString getDebugText()
{
auto counts = counts_.access();
QString text;
for (auto it = counts->begin(); it != counts->end(); it++)
{
text += it.key() + ": " + QString::number(it.value()) + "\n";
}
return text;
}
QString toString()
{
return "";
}
private:
static UniqueAccess<QMap<QString, int64_t>> counts_;
};
} // namespace chatterino
+53 -53
View File
@@ -1,53 +1,53 @@
#include "FormatTime.hpp"
namespace chatterino {
namespace {
void appendDuration(int count, QChar &&order, QString &outString)
{
outString.append(QString::number(count));
outString.append(order);
}
} // namespace
QString formatTime(int totalSeconds)
{
QString res;
int seconds = totalSeconds % 60;
int timeoutMinutes = totalSeconds / 60;
int minutes = timeoutMinutes % 60;
int timeoutHours = timeoutMinutes / 60;
int hours = timeoutHours % 24;
int days = timeoutHours / 24;
if (days > 0)
{
appendDuration(days, 'd', res);
}
if (hours > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(hours, 'h', res);
}
if (minutes > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(minutes, 'm', res);
}
if (seconds > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(seconds, 's', res);
}
return res;
}
} // namespace chatterino
#include "FormatTime.hpp"
namespace chatterino {
namespace {
void appendDuration(int count, QChar &&order, QString &outString)
{
outString.append(QString::number(count));
outString.append(order);
}
} // namespace
QString formatTime(int totalSeconds)
{
QString res;
int seconds = totalSeconds % 60;
int timeoutMinutes = totalSeconds / 60;
int minutes = timeoutMinutes % 60;
int timeoutHours = timeoutMinutes / 60;
int hours = timeoutHours % 24;
int days = timeoutHours / 24;
if (days > 0)
{
appendDuration(days, 'd', res);
}
if (hours > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(hours, 'h', res);
}
if (minutes > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(minutes, 'm', res);
}
if (seconds > 0)
{
if (!res.isEmpty())
{
res.append(" ");
}
appendDuration(seconds, 's', res);
}
return res;
}
} // namespace chatterino
+10 -10
View File
@@ -1,10 +1,10 @@
#pragma once
#include <QString>
namespace chatterino {
// format: 1h 23m 42s
QString formatTime(int totalSeconds);
} // namespace chatterino
#pragma once
#include <QString>
namespace chatterino {
// format: 1h 23m 42s
QString formatTime(int totalSeconds);
} // namespace chatterino
+99 -99
View File
@@ -1,99 +1,99 @@
#include "IncognitoBrowser.hpp"
#include <QProcess>
#include <QRegularExpression>
#include <QSettings>
#include <QVariant>
#include "debug/Log.hpp"
namespace chatterino {
namespace {
#ifdef Q_OS_WIN
QString injectPrivateSwitch(QString command)
{
// list of command line switches to turn on private browsing in browsers
static auto switches = std::vector<std::pair<QString, QString>>{
{"firefox", "-private-window"}, {"chrome", "-incognito"},
{"vivaldi", "-incognito"}, {"opera", "-newprivatetab"},
{"opera\\\\launcher", "--private"}, {"iexplore", "-private"},
};
// transform into regex and replacement string
std::vector<std::pair<QRegularExpression, QString>> replacers;
for (const auto &switch_ : switches)
{
replacers.emplace_back(
QRegularExpression("(" + switch_.first + "\\.exe\"?).*",
QRegularExpression::CaseInsensitiveOption),
"\\1 " + switch_.second);
}
// try to find matching regex and apply it
for (const auto &replacement : replacers)
{
if (replacement.first.match(command).hasMatch())
{
command.replace(replacement.first, replacement.second);
return command;
}
}
// couldn't match any browser -> unknown browser
return QString();
}
QString getCommand(const QString &link)
{
// get default browser prog id
auto browserId = QSettings("HKEY_CURRENT_"
"USER\\Software\\Microsoft\\Windows\\Shell\\"
"Associations\\UrlAssociatio"
"ns\\http\\UserChoice",
QSettings::NativeFormat)
.value("Progid")
.toString();
// get default browser start command
auto command = QSettings("HKEY_CLASSES_ROOT\\" + browserId +
"\\shell\\open\\command",
QSettings::NativeFormat)
.value("Default")
.toString();
if (command.isNull())
return QString();
log(command);
// inject switch to enable private browsing
command = injectPrivateSwitch(command);
if (command.isNull())
return QString();
// link
command += " " + link;
return command;
}
#endif
} // namespace
bool supportsIncognitoLinks()
{
#ifdef Q_OS_WIN
return !getCommand("").isNull();
#else
return false;
#endif
}
void openLinkIncognito(const QString &link)
{
#ifdef Q_OS_WIN
auto command = getCommand(link);
QProcess::startDetached(command);
#endif
}
} // namespace chatterino
#include "IncognitoBrowser.hpp"
#include <QProcess>
#include <QRegularExpression>
#include <QSettings>
#include <QVariant>
#include "debug/Log.hpp"
namespace chatterino {
namespace {
#ifdef Q_OS_WIN
QString injectPrivateSwitch(QString command)
{
// list of command line switches to turn on private browsing in browsers
static auto switches = std::vector<std::pair<QString, QString>>{
{"firefox", "-private-window"}, {"chrome", "-incognito"},
{"vivaldi", "-incognito"}, {"opera", "-newprivatetab"},
{"opera\\\\launcher", "--private"}, {"iexplore", "-private"},
};
// transform into regex and replacement string
std::vector<std::pair<QRegularExpression, QString>> replacers;
for (const auto &switch_ : switches)
{
replacers.emplace_back(
QRegularExpression("(" + switch_.first + "\\.exe\"?).*",
QRegularExpression::CaseInsensitiveOption),
"\\1 " + switch_.second);
}
// try to find matching regex and apply it
for (const auto &replacement : replacers)
{
if (replacement.first.match(command).hasMatch())
{
command.replace(replacement.first, replacement.second);
return command;
}
}
// couldn't match any browser -> unknown browser
return QString();
}
QString getCommand(const QString &link)
{
// get default browser prog id
auto browserId = QSettings("HKEY_CURRENT_"
"USER\\Software\\Microsoft\\Windows\\Shell\\"
"Associations\\UrlAssociatio"
"ns\\http\\UserChoice",
QSettings::NativeFormat)
.value("Progid")
.toString();
// get default browser start command
auto command = QSettings("HKEY_CLASSES_ROOT\\" + browserId +
"\\shell\\open\\command",
QSettings::NativeFormat)
.value("Default")
.toString();
if (command.isNull())
return QString();
log(command);
// inject switch to enable private browsing
command = injectPrivateSwitch(command);
if (command.isNull())
return QString();
// link
command += " " + link;
return command;
}
#endif
} // namespace
bool supportsIncognitoLinks()
{
#ifdef Q_OS_WIN
return !getCommand("").isNull();
#else
return false;
#endif
}
void openLinkIncognito(const QString &link)
{
#ifdef Q_OS_WIN
auto command = getCommand(link);
QProcess::startDetached(command);
#endif
}
} // namespace chatterino
+10 -10
View File
@@ -1,10 +1,10 @@
#pragma once
#include <QtGlobal>
namespace chatterino {
bool supportsIncognitoLinks();
void openLinkIncognito(const QString &link);
} // namespace chatterino
#pragma once
#include <QtGlobal>
namespace chatterino {
bool supportsIncognitoLinks();
void openLinkIncognito(const QString &link);
} // namespace chatterino
+59 -59
View File
@@ -1,59 +1,59 @@
#include "InitUpdateButton.hpp"
#include "widgets/dialogs/UpdateDialog.hpp"
#include "widgets/helper/Button.hpp"
namespace chatterino {
void initUpdateButton(Button &button,
pajlada::Signals::SignalHolder &signalHolder)
{
button.hide();
// show update prompt when clicking the button
QObject::connect(&button, &Button::leftClicked, [&button] {
auto dialog = new UpdateDialog();
dialog->setActionOnFocusLoss(BaseWindow::Delete);
dialog->move(button.mapToGlobal(
QPoint(int(-100 * button.scale()), button.height())));
dialog->show();
dialog->raise();
dialog->buttonClicked.connect([&button](auto buttonType) {
switch (buttonType)
{
case UpdateDialog::Dismiss:
{
button.hide();
}
break;
case UpdateDialog::Install:
{
Updates::getInstance().installUpdates();
}
break;
}
});
// handle.reset(dialog);
// dialog->closing.connect([&handle] { handle.release(); });
});
// update image when state changes
auto updateChange = [&button](auto) {
button.setVisible(Updates::getInstance().shouldShowUpdateButton());
auto imageUrl = Updates::getInstance().isError()
? ":/buttons/updateError.png"
: ":/buttons/update.png";
button.setPixmap(QPixmap(imageUrl));
};
updateChange(Updates::getInstance().getStatus());
signalHolder.managedConnect(
Updates::getInstance().statusUpdated,
[updateChange](auto status) { updateChange(status); });
}
} // namespace chatterino
#include "InitUpdateButton.hpp"
#include "widgets/dialogs/UpdateDialog.hpp"
#include "widgets/helper/Button.hpp"
namespace chatterino {
void initUpdateButton(Button &button,
pajlada::Signals::SignalHolder &signalHolder)
{
button.hide();
// show update prompt when clicking the button
QObject::connect(&button, &Button::leftClicked, [&button] {
auto dialog = new UpdateDialog();
dialog->setActionOnFocusLoss(BaseWindow::Delete);
dialog->move(button.mapToGlobal(
QPoint(int(-100 * button.scale()), button.height())));
dialog->show();
dialog->raise();
dialog->buttonClicked.connect([&button](auto buttonType) {
switch (buttonType)
{
case UpdateDialog::Dismiss:
{
button.hide();
}
break;
case UpdateDialog::Install:
{
Updates::getInstance().installUpdates();
}
break;
}
});
// handle.reset(dialog);
// dialog->closing.connect([&handle] { handle.release(); });
});
// update image when state changes
auto updateChange = [&button](auto) {
button.setVisible(Updates::getInstance().shouldShowUpdateButton());
auto imageUrl = Updates::getInstance().isError()
? ":/buttons/updateError.png"
: ":/buttons/update.png";
button.setPixmap(QPixmap(imageUrl));
};
updateChange(Updates::getInstance().getStatus());
signalHolder.managedConnect(
Updates::getInstance().statusUpdated,
[updateChange](auto status) { updateChange(status); });
}
} // namespace chatterino
+19 -19
View File
@@ -1,19 +1,19 @@
#pragma once
#include <memory>
namespace pajlada {
namespace Signals {
class SignalHolder;
}
} // namespace pajlada
namespace chatterino {
class Button;
class UpdateDialog;
void initUpdateButton(Button &button,
pajlada::Signals::SignalHolder &signalHolder);
} // namespace chatterino
#pragma once
#include <memory>
namespace pajlada {
namespace Signals {
class SignalHolder;
}
} // namespace pajlada
namespace chatterino {
class Button;
class UpdateDialog;
void initUpdateButton(Button &button,
pajlada::Signals::SignalHolder &signalHolder);
} // namespace chatterino
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once
namespace chatterino {
bool isBigEndian()
{
int test = 1;
char *p = reinterpret_cast<char *>(&test);
return p[0] == 0;
}
} // namespace chatterino
#pragma once
namespace chatterino {
bool isBigEndian()
{
int test = 1;
char *p = reinterpret_cast<char *>(&test);
return p[0] == 0;
}
} // namespace chatterino
+194 -194
View File
@@ -1,194 +1,194 @@
#pragma once
#include <QHBoxLayout>
#include <QScrollArea>
#include <QTabWidget>
#include <QWidget>
#include <cassert>
#include <type_traits>
namespace chatterino {
template <class T>
class LayoutCreator
{
public:
LayoutCreator(T *_item)
: item_(_item)
{
}
T *operator->()
{
return this->item_;
}
T &operator*()
{
return *this->item_;
}
T *getElement()
{
return this->item_;
}
template <typename T2>
LayoutCreator<T2> append(T2 *_item)
{
this->addItem(this->getOrCreateLayout(), _item);
return LayoutCreator<T2>(_item);
}
template <typename T2, typename... Args>
LayoutCreator<T2> emplace(Args &&... args)
{
T2 *t = new T2(std::forward<Args>(args)...);
this->addItem(this->getOrCreateLayout(), t);
return LayoutCreator<T2>(t);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QScrollArea, Q>::value,
int>::type = 0>
LayoutCreator<QWidget> emplaceScrollAreaWidget()
{
QWidget *widget = new QWidget;
this->item_->setWidget(widget);
return LayoutCreator<QWidget>(widget);
}
template <typename T2, typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
LayoutCreator<T2> setLayoutType()
{
T2 *layout = new T2;
this->item_->setLayout(layout);
return LayoutCreator<T2>(layout);
}
LayoutCreator<T> assign(T **ptr)
{
*ptr = this->item_;
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
LayoutCreator<T> withoutMargin()
{
this->item_->setContentsMargins(0, 0, 0, 0);
return *this;
}
LayoutCreator<T> withoutSpacing()
{
this->item_->setSpacing(0);
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
LayoutCreator<T> hidden()
{
this->item_->setVisible(false);
return *this;
}
template <typename Q = T, typename T2,
typename std::enable_if<std::is_same<QTabWidget, Q>::value,
int>::type = 0>
LayoutCreator<T2> appendTab(T2 *item, const QString &title)
{
static_assert(std::is_base_of<QLayout, T2>::value,
"needs to be QLayout");
QWidget *widget = new QWidget;
widget->setLayout(item);
this->item_->addTab(widget, title);
return LayoutCreator<T2>(item);
}
template <typename Slot, typename Func>
LayoutCreator<T> connect(Slot slot, QObject *receiver, Func func)
{
QObject::connect(this->getElement(), slot, receiver, func);
return *this;
}
template <typename Func>
LayoutCreator<T> onClick(QObject *receiver, Func func)
{
QObject::connect(this->getElement(), &T::clicked, receiver, func);
return *this;
}
private:
T *item_;
template <typename T2,
typename std::enable_if<std::is_base_of<QWidget, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
{
layout->addWidget(item);
}
template <typename T2,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
{
QWidget *widget = new QWidget();
widget->setLayout(item);
layout->addWidget(widget);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
{
return this->item_;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
{
if (!this->item_->layout())
{
this->item_->setLayout(new QHBoxLayout());
}
return this->item_->layout();
}
};
template <typename T, typename... Args>
LayoutCreator<T> makeDialog(Args &&... args)
{
T *t = new T(std::forward<Args>(args)...);
t->setAttribute(Qt::WA_DeleteOnClose);
return LayoutCreator<T>(t);
}
} // namespace chatterino
#pragma once
#include <QHBoxLayout>
#include <QScrollArea>
#include <QTabWidget>
#include <QWidget>
#include <cassert>
#include <type_traits>
namespace chatterino {
template <class T>
class LayoutCreator
{
public:
LayoutCreator(T *_item)
: item_(_item)
{
}
T *operator->()
{
return this->item_;
}
T &operator*()
{
return *this->item_;
}
T *getElement()
{
return this->item_;
}
template <typename T2>
LayoutCreator<T2> append(T2 *_item)
{
this->addItem(this->getOrCreateLayout(), _item);
return LayoutCreator<T2>(_item);
}
template <typename T2, typename... Args>
LayoutCreator<T2> emplace(Args &&... args)
{
T2 *t = new T2(std::forward<Args>(args)...);
this->addItem(this->getOrCreateLayout(), t);
return LayoutCreator<T2>(t);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QScrollArea, Q>::value,
int>::type = 0>
LayoutCreator<QWidget> emplaceScrollAreaWidget()
{
QWidget *widget = new QWidget;
this->item_->setWidget(widget);
return LayoutCreator<QWidget>(widget);
}
template <typename T2, typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
LayoutCreator<T2> setLayoutType()
{
T2 *layout = new T2;
this->item_->setLayout(layout);
return LayoutCreator<T2>(layout);
}
LayoutCreator<T> assign(T **ptr)
{
*ptr = this->item_;
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
LayoutCreator<T> withoutMargin()
{
this->item_->setContentsMargins(0, 0, 0, 0);
return *this;
}
LayoutCreator<T> withoutSpacing()
{
this->item_->setSpacing(0);
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
LayoutCreator<T> hidden()
{
this->item_->setVisible(false);
return *this;
}
template <typename Q = T, typename T2,
typename std::enable_if<std::is_same<QTabWidget, Q>::value,
int>::type = 0>
LayoutCreator<T2> appendTab(T2 *item, const QString &title)
{
static_assert(std::is_base_of<QLayout, T2>::value,
"needs to be QLayout");
QWidget *widget = new QWidget;
widget->setLayout(item);
this->item_->addTab(widget, title);
return LayoutCreator<T2>(item);
}
template <typename Slot, typename Func>
LayoutCreator<T> connect(Slot slot, QObject *receiver, Func func)
{
QObject::connect(this->getElement(), slot, receiver, func);
return *this;
}
template <typename Func>
LayoutCreator<T> onClick(QObject *receiver, Func func)
{
QObject::connect(this->getElement(), &T::clicked, receiver, func);
return *this;
}
private:
T *item_;
template <typename T2,
typename std::enable_if<std::is_base_of<QWidget, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
{
layout->addWidget(item);
}
template <typename T2,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
{
QWidget *widget = new QWidget();
widget->setLayout(item);
layout->addWidget(widget);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
{
return this->item_;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
{
if (!this->item_->layout())
{
this->item_->setLayout(new QHBoxLayout());
}
return this->item_->layout();
}
};
template <typename T, typename... Args>
LayoutCreator<T> makeDialog(Args &&... args)
{
T *t = new T(std::forward<Args>(args)...);
t->setAttribute(Qt::WA_DeleteOnClose);
return LayoutCreator<T>(t);
}
} // namespace chatterino
+16 -16
View File
@@ -1,16 +1,16 @@
#pragma once
#include <QHash>
#include <QString>
namespace std {
template <>
struct hash<QString> {
std::size_t operator()(const QString &s) const
{
return qHash(s);
}
};
} // namespace std
#pragma once
#include <QHash>
#include <QString>
namespace std {
template <>
struct hash<QString> {
std::size_t operator()(const QString &s) const
{
return qHash(s);
}
};
} // namespace std
+19 -19
View File
@@ -1,19 +1,19 @@
#pragma once
#include <QScrollArea>
namespace chatterino {
static void removeScrollAreaBackground(QScrollArea *scrollArea,
QWidget *childWidget)
{
scrollArea->setWidgetResizable(true);
scrollArea->setFrameStyle(0);
QPalette p;
p.setColor(QPalette::Background, QColor(0, 0, 0, 0));
scrollArea->setPalette(p);
childWidget->setPalette(p);
}
} // namespace chatterino
#pragma once
#include <QScrollArea>
namespace chatterino {
static void removeScrollAreaBackground(QScrollArea *scrollArea,
QWidget *childWidget)
{
scrollArea->setWidgetResizable(true);
scrollArea->setFrameStyle(0);
QPalette p;
p.setColor(QPalette::Background, QColor(0, 0, 0, 0));
scrollArea->setPalette(p);
childWidget->setPalette(p);
}
} // namespace chatterino
+64
View File
@@ -0,0 +1,64 @@
#pragma once
namespace chatterino {
std::vector<QString> getSampleCheerMessage()
{
// clang-format off
std::vector<QString> cheerMessageVector;
cheerMessageVector.push_back(R"(@badge-info=subscriber/4;badges=moderator/1,subscriber/3,sub-gifter/5;bits=2;color=#FF0000;display-name=69_faith_420;emotes=;flags=;id=c5fd49c7-ecbc-46dd-a790-c9f10fdaaa67;mod=1;room-id=111448817;subscriber=1;tmi-sent-ts=1567282184553;turbo=0;user-id=125608098;user-type=mod :69_faith_420!69_faith_420@69_faith_420.tmi.twitch.tv PRIVMSG #pajlada :cheer2 Stop what? I'm not doing anything.)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/4;badges=moderator/1,subscriber/3,sub-gifter/5;bits=2;color=#FF0000;display-name=69_faith_420;emotes=;flags=;id=397f4d2e-cac8-4689-922a-32709b9e8b4f;mod=1;room-id=111448817;subscriber=1;tmi-sent-ts=1567282159076;turbo=0;user-id=125608098;user-type=mod :69_faith_420!69_faith_420@69_faith_420.tmi.twitch.tv PRIVMSG #pajlada :cheer2 Who keeps getting their bits out now?)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/1;badges=subscriber/0,bits/1;bits=2;color=#FF0000;display-name=FlameGodFlann;emotes=;flags=;id=664ddc92-649d-4889-9641-208a6e62ef1e;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567282066199;turbo=0;user-id=56442185;user-type= :flamegodflann!flamegodflann@flamegodflann.tmi.twitch.tv PRIVMSG #pajlada :Cheer2 I'm saving my only can of Stella for your upcoming win, lets go!)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/3;badges=moderator/1,subscriber/3,bits/100;bits=10;color=#008000;display-name=k4izn;emotes=;flags=;id=3919af0b-93e0-412c-b238-d152f92ffea7;mod=1;room-id=111448817;subscriber=1;tmi-sent-ts=1567811485257;turbo=0;user-id=207114672;user-type=mod :k4izn!k4izn@k4izn.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Kleiner Cheer(s) !)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/12;badges=subscriber/12,bits/1000;bits=20;color=#00CCFF;display-name=YaBoiBurnsy;emotes=;flags=;id=5b53975d-b339-484f-a2a0-3ffbedde0df2;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567529634584;turbo=0;user-id=45258137;user-type= :yaboiburnsy!yaboiburnsy@yaboiburnsy.tmi.twitch.tv PRIVMSG #pajlada :ShowLove20)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/1;badges=moderator/1,subscriber/0,bits-leader/2;bits=1;color=;display-name=jdfellie;emotes=;flags=18-22:A.3/P.5;id=28c8f4b7-b1e3-4404-b0f8-5cfe46411ef9;mod=1;room-id=111448817;subscriber=1;tmi-sent-ts=1567668177856;turbo=0;user-id=137619637;user-type=mod :jdfellie!jdfellie@jdfellie.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 take a bit bitch)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/2;bits=30;color=#EC3B83;display-name=Sammay;emotes=;flags=;id=ccf058a6-c1f1-45de-a764-fc8f96f21449;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1566719874294;turbo=0;user-id=58283830;user-type= :sammay!sammay@sammay.tmi.twitch.tv PRIVMSG #pajlada :ShowLove30 @Emperor_Zhang)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/2;bits=6;color=#97E7FF;display-name=Emperor_Zhang;emotes=;flags=;id=53bab01b-9f6c-4123-a852-9916ab371cf9;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1566719803345;turbo=0;user-id=105292882;user-type= :emperor_zhang!emperor_zhang@emperor_zhang.tmi.twitch.tv PRIVMSG #pajlada :uni6)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=5;color=#97E7FF;display-name=Emperor_Zhang;emotes=;flags=;id=545caec6-8b5f-460a-8b4b-3e407e179689;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1566704926380;turbo=0;user-id=105292882;user-type= :emperor_zhang!emperor_zhang@emperor_zhang.tmi.twitch.tv PRIVMSG #pajlada :VoHiYo5)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/100;bits=50;color=;display-name=Schmiddi55;emotes=;flags=;id=777f1018-941d-48aa-bf4e-ed8053d556c8;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567708393343;turbo=0;user-id=101444120;user-type= :schmiddi55!schmiddi55@schmiddi55.tmi.twitch.tv PRIVMSG #pajlada :cheer50 sere ihr radlertrinker)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/3;badges=subscriber/3,sub-gifter/10;bits=100;color=#0000FF;display-name=MLPTheChad;emotes=;flags=87-91:P.5;id=ed7db31e-884b-4761-9c88-b1676caa8814;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567681752733;turbo=0;user-id=63179867;user-type= :mlpthechad!mlpthechad@mlpthechad.tmi.twitch.tv PRIVMSG #pajlada :Subway100 bonus10 Statistically speaking, 10 out of 10 constipated people don't give a shit.)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/3;badges=subscriber/3,sub-gifter/10;bits=100;color=#0000FF;display-name=MLPTheChad;emotes=;flags=;id=506b482a-515a-4914-a694-2c69d2add23a;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567681618814;turbo=0;user-id=63179867;user-type= :mlpthechad!mlpthechad@mlpthechad.tmi.twitch.tv PRIVMSG #pajlada :Subway100 bonus10 That's some SUB par gameplay, Dabier.)");
cheerMessageVector.push_back(R"(@badge-info=;badges=premium/1;bits=100;color=;display-name=AkiraKurusu__;emotes=;flags=;id=6e343f5d-0e0e-47f7-bf6d-d5d7bf18b95a;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567765732657;turbo=0;user-id=151679027;user-type= :akirakurusu__!akirakurusu__@akirakurusu__.tmi.twitch.tv PRIVMSG #pajlada :TriHard100)");
cheerMessageVector.push_back(R"(@badge-info=;badges=premium/1;bits=1;color=;display-name=AkiraKurusu__;emotes=;flags=;id=dfdf6c2f-abee-4a4b-99fe-0d0b221f07de;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567765295301;turbo=0;user-id=151679027;user-type= :akirakurusu__!akirakurusu__@akirakurusu__.tmi.twitch.tv PRIVMSG #pajlada :TriHard1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/100;bits=500;color=#0000FF;display-name=Stabbr;emotes=;flags=;id=e28b384e-fb6a-4da5-9a36-1b6153c6089d;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567648284623;turbo=0;user-id=183081176;user-type= :stabbr!stabbr@stabbr.tmi.twitch.tv PRIVMSG #pajlada :cheer500 Gotta be on top)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/1;badges=subscriber/0,bits-leader/1;bits=100;color=;display-name=dbf_sub;emotes=;flags=;id=7cf317b8-6e28-4615-a0ba-e0bbaa0d4b29;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567646349560;turbo=0;user-id=450101746;user-type= :dbf_sub!dbf_sub@dbf_sub.tmi.twitch.tv PRIVMSG #pajlada :EleGiggle100)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/1;badges=subscriber/0,bits/1;bits=1;color=;display-name=dbf_sub;emotes=;flags=;id=43b5fc97-e7cc-4ac1-8d7e-7504c435c3f1;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567643510222;turbo=0;user-id=450101746;user-type= :dbf_sub!dbf_sub@dbf_sub.tmi.twitch.tv PRIVMSG #pajlada :SeemsGood1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/2;bits=100;color=;display-name=RobertsonRobotics;emotes=;flags=;id=598dfa14-23e9-4e45-a2fe-7a0263828817;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567873463820;turbo=0;user-id=117177721;user-type= :robertsonrobotics!robertsonrobotics@robertsonrobotics.tmi.twitch.tv PRIVMSG #pajlada :firstCheer100 This is so cool! Cant wait for the competition!)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/100;bits=18;color=#1E90FF;display-name=Vipacman11;emotes=;flags=;id=07f59664-0c75-459e-b137-26c8d03e44be;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567873210379;turbo=0;user-id=89634839;user-type= :vipacman11!vipacman11@vipacman11.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=sub-gifter/5;bits=100;color=#FF7F50;display-name=darkside_sinner;emotes=;flags=;id=090102b3-369d-4ce4-ad1f-283849b10de0;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567822075293;turbo=0;user-id=104942909;user-type= :darkside_sinner!darkside_sinner@darkside_sinner.tmi.twitch.tv PRIVMSG #pajlada :Subway100 bonus10)");
cheerMessageVector.push_back(R"(@badge-info=;badges=sub-gifter/5;bits=200;color=#FF7F50;display-name=darkside_sinner;emotes=;flags=;id=2bdf7846-5ffa-4798-a397-997e7209a6d0;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567821695287;turbo=0;user-id=104942909;user-type= :darkside_sinner!darkside_sinner@darkside_sinner.tmi.twitch.tv PRIVMSG #pajlada :Subway200 bonus20)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=50;color=#0000FF;display-name=SincereBC;emotes=;flags=;id=b8c9236b-aeb9-4c72-a191-593e33c6c3f1;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567818308913;turbo=0;user-id=146097597;user-type= :sincerebc!sincerebc@sincerebc.tmi.twitch.tv PRIVMSG #pajlada :cheer50)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=1;color=#FF0000;display-name=AngryCh33s3puff;emotes=;flags=;id=6ab62185-ac1b-4ee5-bd93-165009917078;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567474810480;turbo=0;user-id=55399500;user-type= :angrych33s3puff!angrych33s3puff@angrych33s3puff.tmi.twitch.tv PRIVMSG #pajlada :cheer1 for the chair!)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/3;badges=moderator/1,subscriber/0,bits/1000;bits=1500;color=#5F9EA0;display-name=LaurenJW28;emotes=;flags=;id=2403678c-6109-43ac-b3b5-1f5230f91729;mod=1;room-id=111448817;subscriber=1;tmi-sent-ts=1567746107991;turbo=0;user-id=244354979;user-type=mod :laurenjw28!laurenjw28@laurenjw28.tmi.twitch.tv PRIVMSG #pajlada :Cheer1000 Cheer100 Cheer100 Cheer100 Cheer100 Cheer100)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=5;color=#5F9EA0;display-name=drkwings;emotes=;flags=;id=ad45dae5-b985-4526-9b9e-0bdba2d23289;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567742106689;turbo=0;user-id=440230526;user-type= :drkwings!drkwings@drkwings.tmi.twitch.tv PRIVMSG #pajlada :SeemsGood1 SeemsGood1 SeemsGood1 SeemsGood1 SeemsGood1)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/16;badges=subscriber/12,bits/1000;bits=1;color=;display-name=mustangbugatti;emotes=;flags=;id=ee987ee9-46a4-4c06-bf66-2cafff5d4cdd;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567883658780;turbo=0;user-id=115948494;user-type= :mustangbugatti!mustangbugatti@mustangbugatti.tmi.twitch.tv PRIVMSG #pajlada :(In clarkson accent) Some say...the only number in his contacts is himself..... And...that he is the international butt-dial champion... All we know is.... HES CALLED THE STIG Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/2;badges=subscriber/0,bits/1000;bits=1;color=;display-name=derpysaurus1;emotes=;flags=;id=c41c3d8b-c591-4db0-87e7-a78c5536de82;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567883655116;turbo=0;user-id=419221818;user-type= :derpysaurus1!derpysaurus1@derpysaurus1.tmi.twitch.tv PRIVMSG #pajlada :cheer1 OMG ur back yaaaaaaaaaaaaaaaaaaaaayyyyyyyyy)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/5;badges=subscriber/0,premium/1;bits=1;color=#8A2BE2;display-name=sirlordstallion;emotes=;flags=;id=61a87aeb-88b1-42f9-90f5-74429d8bf387;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567882978939;turbo=0;user-id=92145441;user-type= :sirlordstallion!sirlordstallion@sirlordstallion.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Alex is definetly not putting his eggs in Narreths basket)");
cheerMessageVector.push_back(R"(@badge-info=subscriber/1;badges=subscriber/0,bits/1;bits=1;color=;display-name=xplosivegingerx;emotes=;flags=;id=f8aac1e0-050a-44bf-abcc-c0cf12cbedfc;mod=0;room-id=111448817;subscriber=1;tmi-sent-ts=1567882249072;turbo=0;user-id=151265906;user-type= :xplosivegingerx!xplosivegingerx@xplosivegingerx.tmi.twitch.tv PRIVMSG #pajlada :Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/100;bits=500;color=;display-name=AlexJohanning;emotes=;flags=;id=4e4229a3-e7f2-4082-8c55-47d42db3b09c;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567881969862;turbo=0;user-id=190390930;user-type= :alexjohanning!alexjohanning@alexjohanning.tmi.twitch.tv PRIVMSG #pajlada :cheer500)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=245;color=;display-name=undonebunion6;emotes=;flags=;id=331ec583-0a80-4299-9206-0efd9e33d934;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567881553759;turbo=0;user-id=452974274;user-type= :undonebunion6!undonebunion6@undonebunion6.tmi.twitch.tv PRIVMSG #pajlada :cheer245 can I join?)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/100;bits=100;color=;display-name=therealruffnix;emotes=;flags=61-67:S.6;id=25f567ad-ac95-45ab-b12e-4d647f6a2345;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567524218162;turbo=0;user-id=55059620;user-type= :therealruffnix!therealruffnix@therealruffnix.tmi.twitch.tv PRIVMSG #pajlada :cheer100 This is the kind of ASMR I'm missing on YouTube and PornHub)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=1;color=;display-name=BeamMeUpSnotty;emotes=;flags=;id=8022f41f-dcb8-42f2-b46a-04d4a99180bd;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567270037926;turbo=0;user-id=261679182;user-type= :beammeupsnotty!beammeupsnotty@beammeupsnotty.tmi.twitch.tv PRIVMSG #pajlada :SeemsGood1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=10;color=#00FF7F;display-name=EXDE_HUN;emotes=;flags=;id=60d8835b-23fa-418c-96ca-5874e5d5e8ba;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1566654664248;turbo=0;user-id=129793695;user-type= :exde_hun!exde_hun@exde_hun.tmi.twitch.tv PRIVMSG #pajlada :PogChamp10)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/3;bits=5;color=;display-name=slyckity;emotes=;flags=;id=fd6c5507-3a4e-4d24-8f6e-fadf07f520d3;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567824273752;turbo=0;user-id=143114011;user-type= :slyckity!slyckity@slyckity.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/3;bits=5;color=;display-name=slyckity;emotes=;flags=;id=7003f119-b9a6-4319-a1e8-8e99f96ab01a;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567824186437;turbo=0;user-id=143114011;user-type= :slyckity!slyckity@slyckity.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/3;bits=10;color=;display-name=slyckity;emotes=;flags=;id=3f7de686-77f6-46d2-919e-404312c6676f;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567824128736;turbo=0;user-id=143114011;user-type= :slyckity!slyckity@slyckity.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/3;bits=10;color=;display-name=slyckity;emotes=;flags=;id=9e830ed3-8735-4ccb-9a8b-80466598ca19;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567824118921;turbo=0;user-id=143114011;user-type= :slyckity!slyckity@slyckity.tmi.twitch.tv PRIVMSG #pajlada :Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1 Cheer1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=377;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=262f4d54-9b21-4f13-aac3-6d3b1051282f;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440897074;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :NotLikeThis377)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=144;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=3556e0ad-b5f8-4190-9c4c-e39c1940d191;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440861545;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :bday144)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=89;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=96e380a5-786d-44b8-819a-529b6adb06ac;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440848361;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :SwiftRage89)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=34;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=76239011-65fa-4f6a-a6d6-dc5d5dcbd674;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440816630;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :MrDestructoid34)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=21;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=4c05c97c-7b6c-4ae9-bc91-04e98240c1d5;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440806389;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :TriHard21)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=8;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=3b2ecce7-842e-429e-b6c8-9456c4646362;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440774009;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :EleGiggle8)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=5;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=3b8736d1-832d-4152-832a-50c526714fd1;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440762580;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :uni5)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=3;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=c13a1540-2a03-4c7d-af50-cb20ed88cefd;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440750103;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :Party3)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/1;bits=2;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=5d889eeb-b6b9-4a4e-91ff-0aecdf297edd;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440738337;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :ShowLove2)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=1;color=#00FF7F;display-name=Baekjoon;emotes=;flags=;id=da47f91a-40d3-4209-ba1c-0219d8b8ecaf;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567440720363;turbo=0;user-id=73587716;user-type= :baekjoon!baekjoon@baekjoon.tmi.twitch.tv PRIVMSG #pajlada :Scoops1)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits/1;bits=10;color=#8A2BE2;display-name=EkimSky;emotes=;flags=;id=8adea5b4-7430-44ea-a666-5ebaceb69441;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567833047623;turbo=0;user-id=42132818;user-type= :ekimsky!ekimsky@ekimsky.tmi.twitch.tv PRIVMSG #pajlada :Hi Cheer10)");
cheerMessageVector.push_back(R"(@badge-info=;badges=bits-leader/2;bits=500;color=;display-name=godkiller76;emotes=;flags=;id=80e86bcc-d048-44f3-8073-9a1014568e0c;mod=0;room-id=111448817;subscriber=0;tmi-sent-ts=1567753685704;turbo=0;user-id=258838478;user-type= :godkiller76!godkiller76@godkiller76.tmi.twitch.tv PRIVMSG #pajlada :Party100 Party100 Party100 Party100 Party100)");
return cheerMessageVector;
// clang-format on
};
} // namespace chatterino
+16 -16
View File
@@ -1,16 +1,16 @@
#pragma once
#include <memory>
namespace chatterino {
template <typename T>
struct SharedPtrElementLess {
bool operator()(const std::shared_ptr<T> &a,
const std::shared_ptr<T> &b) const
{
return a->operator<(*b);
}
};
} // namespace chatterino
#pragma once
#include <memory>
namespace chatterino {
template <typename T>
struct SharedPtrElementLess {
bool operator()(const std::shared_ptr<T> &a,
const std::shared_ptr<T> &b) const
{
return a->operator<(*b);
}
};
} // namespace chatterino
+32 -32
View File
@@ -1,32 +1,32 @@
#pragma once
#include <QStandardItem>
namespace chatterino {
static void setBoolItem(QStandardItem *item, bool value,
bool userCheckable = true, bool selectable = true)
{
item->setFlags(Qt::ItemFlags(
Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
(userCheckable ? Qt::ItemIsUserCheckable : 0)));
item->setCheckState(value ? Qt::Checked : Qt::Unchecked);
}
static void setStringItem(QStandardItem *item, const QString &value,
bool editable = true, bool selectable = true)
{
item->setData(value, Qt::EditRole);
item->setFlags(Qt::ItemFlags(Qt::ItemIsEnabled |
(selectable ? Qt::ItemIsSelectable : 0) |
(editable ? (Qt::ItemIsEditable) : 0)));
}
static QStandardItem *emptyItem()
{
auto *item = new QStandardItem();
item->setFlags(Qt::ItemFlags(0));
return item;
}
} // namespace chatterino
#pragma once
#include <QStandardItem>
namespace chatterino {
static void setBoolItem(QStandardItem *item, bool value,
bool userCheckable = true, bool selectable = true)
{
item->setFlags(Qt::ItemFlags(
Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
(userCheckable ? Qt::ItemIsUserCheckable : 0)));
item->setCheckState(value ? Qt::Checked : Qt::Unchecked);
}
static void setStringItem(QStandardItem *item, const QString &value,
bool editable = true, bool selectable = true)
{
item->setData(value, Qt::EditRole);
item->setFlags(Qt::ItemFlags(Qt::ItemIsEnabled |
(selectable ? Qt::ItemIsSelectable : 0) |
(editable ? (Qt::ItemIsEditable) : 0)));
}
static QStandardItem *emptyItem()
{
auto *item = new QStandardItem();
item->setFlags(Qt::ItemFlags(0));
return item;
}
} // namespace chatterino
+22 -22
View File
@@ -1,22 +1,22 @@
#pragma once
#include <algorithm>
namespace chatterino {
namespace util {
template <typename Container, typename UnaryPredicate>
typename Container::iterator find_if(Container &container,
UnaryPredicate pred)
{
return std::find_if(container.begin(), container.end(), pred);
}
template <typename Container, typename UnaryPredicate>
bool any_of(Container &container, UnaryPredicate pred)
{
return std::any_of(container.begin(), container.end(), pred);
}
} // namespace util
} // namespace chatterino
#pragma once
#include <algorithm>
namespace chatterino {
namespace util {
template <typename Container, typename UnaryPredicate>
typename Container::iterator find_if(Container &container,
UnaryPredicate pred)
{
return std::find_if(container.begin(), container.end(), pred);
}
template <typename Container, typename UnaryPredicate>
bool any_of(Container &container, UnaryPredicate pred)
{
return std::any_of(container.begin(), container.end(), pred);
}
} // namespace util
} // namespace chatterino