diff --git a/src/channel.hpp b/src/channel.hpp index 7b6f17156..784eb2b4b 100644 --- a/src/channel.hpp +++ b/src/channel.hpp @@ -35,7 +35,7 @@ public: explicit Channel(const QString &_name, Type type); virtual ~Channel(); - pajlada::Signals::Signal sendMessageSignal; + pajlada::Signals::Signal sendMessageSignal; pajlada::Signals::Signal messageRemovedFromStart; pajlada::Signals::Signal messageAppended; diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 1d8e2c3d4..2feba3c49 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -162,14 +162,16 @@ void TwitchChannel::sendMessage(const QString &message) if (app->settings->allowDuplicateMessages) { if (parsedMessage == this->lastSentMessage) { parsedMessage.append(this->messageSuffix); - - this->lastSentMessage = ""; } } - this->lastSentMessage = parsedMessage; + bool messageSent = false; + this->sendMessageSignal.invoke(this->name, parsedMessage, messageSent); - this->sendMessageSignal.invoke(this->name, parsedMessage); + if (messageSent) { + qDebug() << "sent"; + this->lastSentMessage = parsedMessage; + } } bool TwitchChannel::isMod() const diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index bcb028fd1..7641ad749 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -71,8 +71,52 @@ std::shared_ptr TwitchServer::createChannel(const QString &channelName) { TwitchChannel *channel = new TwitchChannel(channelName, this->getReadConnection()); - channel->sendMessageSignal.connect( - [this](auto chan, auto msg) { this->sendMessage(chan, msg); }); + channel->sendMessageSignal.connect([this, channel](auto chan, auto msg, bool &sent) { + + { + std::lock_guard guard(this->lastMessageMutex); + + std::queue &lastMessage = + channel->hasModRights() ? this->lastMessageMod : this->lastMessagePleb; + size_t maxMessageCount = channel->hasModRights() ? 99 : 19; + + QTime now = QTime::currentTime(); + + if (lastMessage.size() > 0 && + lastMessage.back().addMSecs(channel->hasModRights() ? 100 : 1100) > now) { + if (lastErrorTimeSpeed.addSecs(30) < now) { + auto errorMessage = + messages::Message::createSystemMessage("sending messages too fast"); + + channel->addMessage(errorMessage); + + lastErrorTimeSpeed = now; + } + return; + } + + while (lastMessage.size() > 0 && lastMessage.front().addSecs(32) < now) { + lastMessage.pop(); + } + + if (lastMessage.size() >= maxMessageCount) { + if (lastErrorTimeAmount.addSecs(30) < now) { + auto errorMessage = + messages::Message::createSystemMessage("sending too many messages"); + + channel->addMessage(errorMessage); + + lastErrorTimeAmount = now; + } + return; + } + + lastMessage.push(now); + } + + this->sendMessage(chan, msg); + sent = true; + }); return std::shared_ptr(channel); } diff --git a/src/providers/twitch/twitchserver.hpp b/src/providers/twitch/twitchserver.hpp index caa93fe29..d03f0b2b5 100644 --- a/src/providers/twitch/twitchserver.hpp +++ b/src/providers/twitch/twitchserver.hpp @@ -6,6 +6,7 @@ #include "util/mutexvalue.hpp" #include +#include namespace chatterino { namespace providers { @@ -46,8 +47,11 @@ protected: QString cleanChannelName(const QString &dirtyChannelName) override; private: - // mutable std::mutex lastWhisperedPersonMutex; - // QString lastWhisperedPerson; + std::mutex lastMessageMutex; + std::queue lastMessagePleb; + std::queue lastMessageMod; + QTime lastErrorTimeSpeed; + QTime lastErrorTimeAmount; }; } // namespace twitch diff --git a/src/util/serialize-custom.hpp b/src/util/serialize-custom.hpp index e698e9a7c..decb44875 100644 --- a/src/util/serialize-custom.hpp +++ b/src/util/serialize-custom.hpp @@ -30,9 +30,9 @@ struct Deserialize { return QString::fromUtf8(str, strLen); } catch (const std::exception &e) { - int x = 5; + // int x = 5; } catch (...) { - int y = 5; + // int y = 5; } return QString(); diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 5b949dd12..1588c6cba 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -21,16 +21,16 @@ namespace widgets { SplitInput::SplitInput(Split *_chatWidget) : BaseWidget(_chatWidget) - , split(_chatWidget) + , split_(_chatWidget) { this->initLayout(); - auto completer = new QCompleter(&this->split->getChannel().get()->completionModel); - this->ui.textEdit->setCompleter(completer); + auto completer = new QCompleter(&this->split_->getChannel().get()->completionModel); + this->ui_.textEdit->setCompleter(completer); - this->split->channelChanged.connect([this] { - auto completer = new QCompleter(&this->split->getChannel()->completionModel); - this->ui.textEdit->setCompleter(completer); + this->split_->channelChanged.connect([this] { + auto completer = new QCompleter(&this->split_->getChannel()->completionModel); + this->ui_.textEdit->setCompleter(completer); }); // misc @@ -43,10 +43,11 @@ void SplitInput::initLayout() auto app = getApp(); util::LayoutCreator layoutCreator(this); - auto layout = layoutCreator.setLayoutType().withoutMargin().assign(&this->ui.hbox); + auto layout = + layoutCreator.setLayoutType().withoutMargin().assign(&this->ui_.hbox); // input - auto textEdit = layout.emplace().assign(&this->ui.textEdit); + auto textEdit = layout.emplace().assign(&this->ui_.textEdit); connect(textEdit.getElement(), &ResizingTextEdit::textChanged, this, &SplitInput::editTextChanged); @@ -54,54 +55,54 @@ void SplitInput::initLayout() auto box = layout.emplace().withoutMargin(); box->setSpacing(0); { - auto textEditLength = box.emplace().assign(&this->ui.textEditLength); + auto textEditLength = box.emplace().assign(&this->ui_.textEditLength); textEditLength->setAlignment(Qt::AlignRight); box->addStretch(1); - box.emplace().assign(&this->ui.emoteButton); + box.emplace().assign(&this->ui_.emoteButton); } - this->ui.emoteButton->getLabel().setTextFormat(Qt::RichText); + this->ui_.emoteButton->getLabel().setTextFormat(Qt::RichText); // ---- misc // set edit font - this->ui.textEdit->setFont( + this->ui_.textEdit->setFont( app->fonts->getFont(singletons::FontManager::Type::ChatMedium, this->getScale())); - this->managedConnections.emplace_back(app->fonts->fontChanged.connect([=]() { - this->ui.textEdit->setFont( + this->managedConnections_.emplace_back(app->fonts->fontChanged.connect([=]() { + this->ui_.textEdit->setFont( app->fonts->getFont(singletons::FontManager::Type::ChatMedium, this->getScale())); })); // open emote popup - QObject::connect(this->ui.emoteButton, &RippleEffectLabel::clicked, [this] { - if (!this->emotePopup) { - this->emotePopup = std::make_unique(); - this->emotePopup->linkClicked.connect([this](const messages::Link &link) { + QObject::connect(this->ui_.emoteButton, &RippleEffectLabel::clicked, [this] { + if (!this->emotePopup_) { + this->emotePopup_ = std::make_unique(); + this->emotePopup_->linkClicked.connect([this](const messages::Link &link) { if (link.type == messages::Link::InsertText) { this->insertText(link.value + " "); } }); } - this->emotePopup->resize(int(300 * this->emotePopup->getScale()), - int(500 * this->emotePopup->getScale())); - this->emotePopup->loadChannel(this->split->getChannel()); - this->emotePopup->show(); + this->emotePopup_->resize(int(300 * this->emotePopup_->getScale()), + int(500 * this->emotePopup_->getScale())); + this->emotePopup_->loadChannel(this->split_->getChannel()); + this->emotePopup_->show(); }); // clear channelview selection when selecting in the input - QObject::connect(this->ui.textEdit, &QTextEdit::copyAvailable, [this](bool available) { + QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable, [this](bool available) { if (available) { - this->split->view.clearSelection(); + this->split_->view.clearSelection(); } }); // textEditLength visibility app->settings->showMessageLength.connect( - [this](const bool &value, auto) { this->ui.textEditLength->setHidden(!value); }, - this->managedConnections); + [this](const bool &value, auto) { this->ui_.textEditLength->setHidden(!value); }, + this->managedConnections_); } void SplitInput::scaleChangedEvent(float scale) @@ -110,8 +111,8 @@ void SplitInput::scaleChangedEvent(float scale) QString text = ""; text.replace("xD", QString::number(int(12 * scale))); - this->ui.emoteButton->getLabel().setText(text); - this->ui.emoteButton->setFixedHeight(int(18 * scale)); + this->ui_.emoteButton->getLabel().setText(text); + this->ui_.emoteButton->setFixedHeight(int(18 * scale)); // set maximum height this->setMaximumHeight(int(150 * this->getScale())); @@ -123,65 +124,66 @@ void SplitInput::themeRefreshEvent() palette.setColor(QPalette::Foreground, this->themeManager->splits.input.text); - this->ui.textEditLength->setPalette(palette); + this->ui_.textEditLength->setPalette(palette); - this->ui.textEdit->setStyleSheet(this->themeManager->splits.input.styleSheet); + this->ui_.textEdit->setStyleSheet(this->themeManager->splits.input.styleSheet); - this->ui.hbox->setMargin(int((this->themeManager->isLightTheme() ? 4 : 2) * this->getScale())); + this->ui_.hbox->setMargin(int((this->themeManager->isLightTheme() ? 4 : 2) * this->getScale())); } void SplitInput::installKeyPressedEvent() { auto app = getApp(); - this->ui.textEdit->keyPressed.connect([this, app](QKeyEvent *event) { + this->ui_.textEdit->keyPressed.connect([this, app](QKeyEvent *event) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - auto c = this->split->getChannel(); + auto c = this->split_->getChannel(); if (c == nullptr) { return; } - QString message = ui.textEdit->toPlainText(); + + QString message = ui_.textEdit->toPlainText(); QString sendMessage = app->commands->execCommand(message, c, false); sendMessage = sendMessage.replace('\n', ' '); c->sendMessage(sendMessage); // don't add duplicate messages to message history - if (this->prevMsg.isEmpty() || !this->prevMsg.endsWith(message)) - this->prevMsg.append(message); + if (this->prevMsg_.isEmpty() || !this->prevMsg_.endsWith(message)) + this->prevMsg_.append(message); event->accept(); if (!(event->modifiers() == Qt::ControlModifier)) { - this->currMsg = QString(); - this->ui.textEdit->setText(QString()); - this->prevIndex = 0; - } else if (this->ui.textEdit->toPlainText() == - this->prevMsg.at(this->prevMsg.size() - 1)) { - this->prevMsg.removeLast(); + this->currMsg_ = QString(); + this->ui_.textEdit->setText(QString()); + this->prevIndex_ = 0; + } else if (this->ui_.textEdit->toPlainText() == + this->prevMsg_.at(this->prevMsg_.size() - 1)) { + this->prevMsg_.removeLast(); } - this->prevIndex = this->prevMsg.size(); + this->prevIndex_ = this->prevMsg_.size(); } else if (event->key() == Qt::Key_Up) { if ((event->modifiers() & Qt::ShiftModifier) != 0) { return; } if (event->modifiers() == Qt::AltModifier) { - SplitContainer *page = this->split->getContainer(); + SplitContainer *page = this->split_->getContainer(); if (page != nullptr) { page->selectNextSplit(SplitContainer::Above); } } else { - if (this->prevMsg.size() && this->prevIndex) { - if (this->prevIndex == (this->prevMsg.size())) { - this->currMsg = ui.textEdit->toPlainText(); + if (this->prevMsg_.size() && this->prevIndex_) { + if (this->prevIndex_ == (this->prevMsg_.size())) { + this->currMsg_ = ui_.textEdit->toPlainText(); } - this->prevIndex--; - this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex)); + this->prevIndex_--; + this->ui_.textEdit->setText(this->prevMsg_.at(this->prevIndex_)); - QTextCursor cursor = this->ui.textEdit->textCursor(); + QTextCursor cursor = this->ui_.textEdit->textCursor(); cursor.movePosition(QTextCursor::End); - this->ui.textEdit->setTextCursor(cursor); + this->ui_.textEdit->setTextCursor(cursor); } } } else if (event->key() == Qt::Key_Down) { @@ -189,28 +191,28 @@ void SplitInput::installKeyPressedEvent() return; } if (event->modifiers() == Qt::AltModifier) { - SplitContainer *page = this->split->getContainer(); + SplitContainer *page = this->split_->getContainer(); if (page != nullptr) { page->selectNextSplit(SplitContainer::Below); } } else { - if (this->prevIndex != (this->prevMsg.size() - 1) && - this->prevIndex != this->prevMsg.size()) { - this->prevIndex++; - this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex)); + if (this->prevIndex_ != (this->prevMsg_.size() - 1) && + this->prevIndex_ != this->prevMsg_.size()) { + this->prevIndex_++; + this->ui_.textEdit->setText(this->prevMsg_.at(this->prevIndex_)); } else { - this->prevIndex = this->prevMsg.size(); - this->ui.textEdit->setText(this->currMsg); + this->prevIndex_ = this->prevMsg_.size(); + this->ui_.textEdit->setText(this->currMsg_); } - QTextCursor cursor = this->ui.textEdit->textCursor(); + QTextCursor cursor = this->ui_.textEdit->textCursor(); cursor.movePosition(QTextCursor::End); - this->ui.textEdit->setTextCursor(cursor); + this->ui_.textEdit->setTextCursor(cursor); } } else if (event->key() == Qt::Key_Left) { if (event->modifiers() == Qt::AltModifier) { - SplitContainer *page = this->split->getContainer(); + SplitContainer *page = this->split_->getContainer(); if (page != nullptr) { page->selectNextSplit(SplitContainer::Left); @@ -218,7 +220,7 @@ void SplitInput::installKeyPressedEvent() } } else if (event->key() == Qt::Key_Right) { if (event->modifiers() == Qt::AltModifier) { - SplitContainer *page = this->split->getContainer(); + SplitContainer *page = this->split_->getContainer(); if (page != nullptr) { page->selectNextSplit(SplitContainer::Right); @@ -226,7 +228,7 @@ void SplitInput::installKeyPressedEvent() } } else if (event->key() == Qt::Key_Tab) { if (event->modifiers() == Qt::ControlModifier) { - SplitContainer *page = static_cast(this->split->parentWidget()); + SplitContainer *page = static_cast(this->split_->parentWidget()); Notebook *notebook = static_cast(page->parentWidget()); @@ -234,15 +236,15 @@ void SplitInput::installKeyPressedEvent() } } else if (event->key() == Qt::Key_Backtab) { if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { - SplitContainer *page = static_cast(this->split->parentWidget()); + SplitContainer *page = static_cast(this->split_->parentWidget()); Notebook *notebook = static_cast(page->parentWidget()); notebook->selectPreviousTab(); } } else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) { - if (this->split->view.hasSelection()) { - this->split->doCopy(); + if (this->split_->view.hasSelection()) { + this->split_->doCopy(); event->accept(); } } @@ -251,22 +253,22 @@ void SplitInput::installKeyPressedEvent() void SplitInput::clearSelection() { - QTextCursor c = this->ui.textEdit->textCursor(); + QTextCursor c = this->ui_.textEdit->textCursor(); c.setPosition(c.position()); c.setPosition(c.position(), QTextCursor::KeepAnchor); - this->ui.textEdit->setTextCursor(c); + this->ui_.textEdit->setTextCursor(c); } QString SplitInput::getInputText() const { - return this->ui.textEdit->toPlainText(); + return this->ui_.textEdit->toPlainText(); } void SplitInput::insertText(const QString &text) { - this->ui.textEdit->insertPlainText(text); + this->ui_.textEdit->insertPlainText(text); } void SplitInput::editTextChanged() @@ -274,15 +276,15 @@ void SplitInput::editTextChanged() auto app = getApp(); // set textLengthLabel value - QString text = this->ui.textEdit->toPlainText(); + QString text = this->ui_.textEdit->toPlainText(); if (text.startsWith("/r ", Qt::CaseInsensitive) && - this->split->getChannel()->isTwitchChannel()) // + this->split_->getChannel()->isTwitchChannel()) // { QString lastUser = app->twitch.server->lastUserThatWhisperedMe.get(); if (!lastUser.isEmpty()) { - this->ui.textEdit->setPlainText("/w " + lastUser + text.mid(2)); - this->ui.textEdit->moveCursor(QTextCursor::EndOfBlock); + this->ui_.textEdit->setPlainText("/w " + lastUser + text.mid(2)); + this->ui_.textEdit->moveCursor(QTextCursor::EndOfBlock); } } else { this->textChanged.invoke(text); @@ -291,7 +293,7 @@ void SplitInput::editTextChanged() static QRegularExpression spaceRegex("\\s\\s+"); text = text.replace(spaceRegex, " "); - text = app->commands->execCommand(text, this->split->getChannel(), true); + text = app->commands->execCommand(text, this->split_->getChannel(), true); } QString labelText; @@ -302,7 +304,7 @@ void SplitInput::editTextChanged() labelText = QString::number(text.length()); } - this->ui.textEditLength->setText(labelText); + this->ui_.textEditLength->setText(labelText); } void SplitInput::paintEvent(QPaintEvent *) @@ -335,15 +337,15 @@ void SplitInput::paintEvent(QPaintEvent *) void SplitInput::resizeEvent(QResizeEvent *) { if (this->height() == this->maximumHeight()) { - this->ui.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + this->ui_.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } else { - this->ui.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + this->ui_.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } } void SplitInput::mousePressEvent(QMouseEvent *) { - this->split->giveFocus(Qt::MouseFocusReason); + this->split_->giveFocus(Qt::MouseFocusReason); } } // namespace widgets diff --git a/src/widgets/helper/splitinput.hpp b/src/widgets/helper/splitinput.hpp index 9f7d7fdbb..05c9b74b6 100644 --- a/src/widgets/helper/splitinput.hpp +++ b/src/widgets/helper/splitinput.hpp @@ -40,8 +40,8 @@ protected: virtual void mousePressEvent(QMouseEvent *event) override; private: - Split *const split; - std::unique_ptr emotePopup; + Split *const split_; + std::unique_ptr emotePopup_; struct { ResizingTextEdit *textEdit; @@ -49,12 +49,12 @@ private: RippleEffectLabel *emoteButton; QHBoxLayout *hbox; - } ui; + } ui_; - std::vector managedConnections; - QStringList prevMsg; - QString currMsg; - int prevIndex = 0; + std::vector managedConnections_; + QStringList prevMsg_; + QString currMsg_; + int prevIndex_ = 0; void initLayout(); void installKeyPressedEvent(); diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 74265bef0..f4ea1ae5b 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -94,7 +94,7 @@ Split::Split(QWidget *parent) // CreateShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY); // CreateShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY); - this->input.ui.textEdit->installEventFilter(parent); + this->input.ui_.textEdit->installEventFilter(parent); this->view.mouseDown.connect([this](QMouseEvent *) { // @@ -142,7 +142,7 @@ Split::Split(QWidget *parent) } }); - this->input.ui.textEdit->focused.connect([this] { this->focused.invoke(); }); + this->input.ui_.textEdit->focused.connect([this] { this->focused.invoke(); }); } Split::~Split() @@ -266,12 +266,12 @@ void Split::updateLastReadMessage() void Split::giveFocus(Qt::FocusReason reason) { - this->input.ui.textEdit->setFocus(reason); + this->input.ui_.textEdit->setFocus(reason); } bool Split::hasFocus() const { - return this->input.ui.textEdit->hasFocus(); + return this->input.ui_.textEdit->hasFocus(); } void Split::paintEvent(QPaintEvent *)