diff --git a/src/controllers/commands/CommandController.cpp b/src/controllers/commands/CommandController.cpp index d7ea1693..a4cd22a4 100644 --- a/src/controllers/commands/CommandController.cpp +++ b/src/controllers/commands/CommandController.cpp @@ -15,6 +15,7 @@ #include "singletons/Emotes.hpp" #include "singletons/Paths.hpp" #include "singletons/Settings.hpp" +#include "singletons/Theme.hpp" #include "util/CombinePath.hpp" #include "widgets/dialogs/LogsPopup.hpp" @@ -31,6 +32,136 @@ "/followersoff" \ } +namespace { +using namespace chatterino; + +void sendWhisperMessage(const QString &text) +{ + auto app = getApp(); + app->twitch.server->sendMessage("jtv", text); +} + +bool appendWhisperMessageLocally(const QStringList &words) +{ + auto app = getApp(); + + MessageBuilder b; + + b.emplace(); + b.emplace(app->accounts->twitch.getCurrent()->getUserName(), + MessageElementFlag::Text, MessageColor::Text, + FontStyle::ChatMediumBold); + b.emplace("->", MessageElementFlag::Text, + getApp()->themes->messages.textColors.system); + b.emplace(words[1] + ":", MessageElementFlag::Text, + MessageColor::Text, FontStyle::ChatMediumBold); + + const auto &acc = app->accounts->twitch.getCurrent(); + const auto &accemotes = *acc->accessEmotes(); + const auto &bttvemotes = app->twitch.server->getBttvEmotes(); + const auto &ffzemotes = app->twitch.server->getFfzEmotes(); + auto flags = MessageElementFlags(); + auto emote = boost::optional{}; + for (int i = 2; i < words.length(); i++) + { + { // twitch emote + auto it = accemotes.emotes.find({words[i]}); + if (it != accemotes.emotes.end()) + { + b.emplace(it->second, + MessageElementFlag::TwitchEmote); + continue; + } + } // twitch emote + + { // bttv/ffz emote + if ((emote = bttvemotes.emote({words[i]}))) + { + flags = MessageElementFlag::BttvEmote; + } + else if ((emote = ffzemotes.emote({words[i]}))) + { + flags = MessageElementFlag::FfzEmote; + } + if (emote) + { + b.emplace(emote.get(), flags); + continue; + } + } // bttv/ffz emote + { // emoji/text + for (auto &variant : app->emotes->emojis.parse(words[i])) + { + constexpr const static struct { + void operator()(EmotePtr emote, MessageBuilder &b) const + { + b.emplace(emote, + MessageElementFlag::EmojiAll); + } + void operator()(const QString &string, + MessageBuilder &b) const + { + auto linkString = b.matchLink(string); + if (linkString.isEmpty()) + { + b.emplace(string, + MessageElementFlag::Text); + } + else + { + b.addLink(string, linkString); + } + } + } visitor; + boost::apply_visitor([&b](auto &&arg) { visitor(arg, b); }, + variant); + } // emoji/text + } + } + + b->flags.set(MessageFlag::DoNotTriggerNotification); + b->flags.set(MessageFlag::Whisper); + auto messagexD = b.release(); + + app->twitch.server->whispersChannel->addMessage(messagexD); + + auto overrideFlags = boost::optional(messagexD->flags); + overrideFlags->set(MessageFlag::DoNotLog); + + if (getSettings()->inlineWhispers) + { + app->twitch.server->forEachChannel( + [&messagexD, overrideFlags](ChannelPtr _channel) { + _channel->addMessage(messagexD, overrideFlags); + }); + } + + return true; +} + +bool appendWhisperMessageLocally(const QString &textNoEmoji) +{ + QString text = getApp()->emotes->emojis.replaceShortCodes(textNoEmoji); + QStringList words = text.split(' ', QString::SkipEmptyParts); + + if (words.length() == 0) + { + return false; + } + + QString commandName = words[0]; + + if (commandName == "/w") + { + if (words.length() > 2) + { + return appendWhisperMessageLocally(words); + } + } + return false; +} +} // namespace + namespace chatterino { void CommandController::initialize(Settings &, Paths &paths) @@ -124,106 +255,10 @@ QString CommandController::execCommand(const QString &textNoEmoji, { if (commandName == "/w") { - if (words.length() <= 2) + if (words.length() > 2) { - return ""; - } - - auto app = getApp(); - - MessageBuilder b; - - b.emplace(); - b.emplace( - app->accounts->twitch.getCurrent()->getUserName(), - MessageElementFlag::Text, MessageColor::Text, - FontStyle::ChatMediumBold); - b.emplace("->", MessageElementFlag::Text); - b.emplace(words[1] + ":", MessageElementFlag::Text, - MessageColor::Text, - FontStyle::ChatMediumBold); - - const auto &acc = app->accounts->twitch.getCurrent(); - const auto &accemotes = *acc->accessEmotes(); - const auto &bttvemotes = app->twitch.server->getBttvEmotes(); - const auto &ffzemotes = app->twitch.server->getFfzEmotes(); - auto flags = MessageElementFlags(); - auto emote = boost::optional{}; - for (int i = 2; i < words.length(); i++) - { - { // twitch emote - auto it = accemotes.emotes.find({words[i]}); - if (it != accemotes.emotes.end()) - { - b.emplace( - it->second, MessageElementFlag::TwitchEmote); - continue; - } - } // twitch emote - - { // bttv/ffz emote - if ((emote = bttvemotes.emote({words[i]}))) - { - flags = MessageElementFlag::BttvEmote; - } - else if ((emote = ffzemotes.emote({words[i]}))) - { - flags = MessageElementFlag::FfzEmote; - } - if (emote) - { - b.emplace(emote.get(), flags); - continue; - } - } // bttv/ffz emote - { // emoji/text - for (auto &variant : app->emotes->emojis.parse(words[i])) - { - constexpr const static struct { - void operator()(EmotePtr emote, - MessageBuilder &b) const - { - b.emplace( - emote, MessageElementFlag::EmojiAll); - } - void operator()(const QString &string, - MessageBuilder &b) const - { - auto linkString = b.matchLink(string); - if (linkString.isEmpty()) - { - b.emplace( - string, MessageElementFlag::Text); - } - else - { - b.addLink(string, linkString); - } - } - } visitor; - boost::apply_visitor( - [&b](auto &&arg) { visitor(arg, b); }, variant); - } // emoji/text - } - } - - b->flags.set(MessageFlag::DoNotTriggerNotification); - b->flags.set(MessageFlag::Whisper); - auto messagexD = b.release(); - - app->twitch.server->whispersChannel->addMessage(messagexD); - - app->twitch.server->sendMessage("jtv", text); - - auto overrideFlags = boost::optional(messagexD->flags); - overrideFlags->set(MessageFlag::DoNotLog); - - if (getSettings()->inlineWhispers) - { - app->twitch.server->forEachChannel( - [&messagexD, overrideFlags](ChannelPtr _channel) { - _channel->addMessage(messagexD, overrideFlags); - }); + appendWhisperMessageLocally(words); + sendWhisperMessage(text); } return ""; @@ -428,7 +463,7 @@ QString CommandController::execCommand(const QString &textNoEmoji, auto it = this->commandsMap_.find(commandName); if (it != this->commandsMap_.end()) { - return this->execCustomCommand(words, it.value()); + return this->execCustomCommand(words, it.value(), dryRun); } auto maxSpaces = std::min(this->maxSpaces_, words.length() - 1); @@ -439,7 +474,7 @@ QString CommandController::execCommand(const QString &textNoEmoji, auto it = this->commandsMap_.find(commandName); if (it != this->commandsMap_.end()) { - return this->execCustomCommand(words, it.value()); + return this->execCustomCommand(words, it.value(), dryRun); } } @@ -447,7 +482,8 @@ QString CommandController::execCommand(const QString &textNoEmoji, } QString CommandController::execCustomCommand(const QStringList &words, - const Command &command) + const Command &command, + bool dryRun) { QString result; @@ -518,7 +554,15 @@ QString CommandController::execCustomCommand(const QStringList &words, result = result.mid(1); } - return result.replace("{{", "{"); + auto res = result.replace("{{", "{"); + + if (dryRun) + { + return res; + } + + return appendWhisperMessageLocally(res) ? (sendWhisperMessage(res), "") + : res; } QStringList CommandController::getDefaultTwitchCommandList() diff --git a/src/controllers/commands/CommandController.hpp b/src/controllers/commands/CommandController.hpp index fb6f9d89..e29ee25a 100644 --- a/src/controllers/commands/CommandController.hpp +++ b/src/controllers/commands/CommandController.hpp @@ -49,7 +49,8 @@ private: std::unique_ptr>> commandsSetting_; - QString execCustomCommand(const QStringList &words, const Command &command); + QString execCustomCommand(const QStringList &words, const Command &command, + bool dryRun); }; } // namespace chatterino