Move most Command variables into the CommandController shared variables (#3824)

This commit is contained in:
pajlada
2022-06-25 14:06:16 +02:00
committed by GitHub
parent 6a58ce1273
commit 34ea303607
4 changed files with 223 additions and 105 deletions
+1
View File
@@ -41,6 +41,7 @@
- Dev: Overhaul highlight system by moving all checks into a Controller allowing for easier tests. (#3399, #3801) - Dev: Overhaul highlight system by moving all checks into a Controller allowing for easier tests. (#3399, #3801)
- Dev: Use Game Name returned by Get Streams instead of querying it from the Get Games API. (#3662) - Dev: Use Game Name returned by Get Streams instead of querying it from the Get Games API. (#3662)
- Dev: Batch checking live status for all channels after startup. (#3757, #3762, #3767) - Dev: Batch checking live status for all channels after startup. (#3757, #3762, #3767)
- Dev: Move most command context into the command controller. (#3824)
## 2.3.5 ## 2.3.5
+162 -28
View File
@@ -177,24 +177,27 @@ bool appendWhisperMessageStringLocally(const QString &textNoEmoji)
return false; return false;
} }
const std::function<QString(const QString &, const ChannelPtr &)> using VariableReplacer = std::function<QString(
noOpPlaceholder = [](const auto &altText, const auto &channel) { const QString &, const ChannelPtr &, const Message *)>;
const VariableReplacer NO_OP_PLACEHOLDER =
[](const auto &altText, const auto &channel, const auto *message) {
return altText; return altText;
}; };
const std::map<QString, const std::unordered_map<QString, VariableReplacer> COMMAND_VARS{
std::function<QString(const QString &, const ChannelPtr &)>>
COMMAND_VARS{
{ {
"channel.name", "channel.name",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(altText); //unused (void)(altText); //unused
(void)(message); //unused
return channel->getName(); return channel->getName();
}, },
}, },
{ {
"channel.id", "channel.id",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(message); //unused
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
if (tc == nullptr) if (tc == nullptr)
{ {
@@ -204,9 +207,20 @@ const std::map<QString,
return tc->roomId(); return tc->roomId();
}, },
}, },
{
// NOTE: The use of {channel} is deprecated and support for it will drop at some point
// Users should be encouraged to use {channel.name} instead.
"channel",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(altText); //unused
(void)(message); //unused
return channel->getName();
},
},
{ {
"stream.game", "stream.game",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(message); //unused
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
if (tc == nullptr) if (tc == nullptr)
{ {
@@ -218,7 +232,8 @@ const std::map<QString,
}, },
{ {
"stream.title", "stream.title",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(message); //unused
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
if (tc == nullptr) if (tc == nullptr)
{ {
@@ -230,26 +245,144 @@ const std::map<QString,
}, },
{ {
"my.id", "my.id",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused (void)(channel); //unused
(void)(message); //unused
auto uid = getApp()->accounts->twitch.getCurrent()->getUserId(); auto uid = getApp()->accounts->twitch.getCurrent()->getUserId();
return uid.isEmpty() ? altText : uid; return uid.isEmpty() ? altText : uid;
}, },
}, },
{ {
"my.name", "my.name",
[](const auto &altText, const auto &channel) { [](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused (void)(channel); //unused
auto name = (void)(message); //unused
getApp()->accounts->twitch.getCurrent()->getUserName(); auto name = getApp()->accounts->twitch.getCurrent()->getUserName();
return name.isEmpty() ? altText : name; return name.isEmpty() ? altText : name;
}, },
}, },
{
"user.name",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->loginName;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
{
// NOTE: The use of {user} is deprecated and support for it will drop at some point
// Users should be encouraged to use {user.name} instead.
"user",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->loginName;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
{
"msg.id",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->id;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
{
// NOTE: The use of {msg-id} is deprecated and support for it will drop at some point
// Users should be encouraged to use {msg.id} instead.
"msg-id",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->id;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
{
"msg.text",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->messageText;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
{
// NOTE: The use of {message} is deprecated and support for it will drop at some point
// Users should be encouraged to use {msg.text} instead.
"message",
[](const auto &altText, const auto &channel, const auto *message) {
(void)(channel); //unused
if (message == nullptr)
{
return altText;
}
const auto &v = message->messageText;
if (v.isEmpty())
{
return altText;
}
return v;
},
},
// variables used in mod buttons and the like, these make no sense in normal commands, so they are left empty // variables used in mod buttons and the like, these make no sense in normal commands, so they are left empty
{"input.text", noOpPlaceholder}, {"input.text", NO_OP_PLACEHOLDER},
{"msg.id", noOpPlaceholder},
{"user.name", noOpPlaceholder},
{"msg.text", noOpPlaceholder},
}; };
} // namespace } // namespace
@@ -1120,10 +1253,10 @@ void CommandController::registerCommand(QString commandName,
this->defaultChatterinoCommandAutoCompletions_.append(commandName); this->defaultChatterinoCommandAutoCompletions_.append(commandName);
} }
QString CommandController::execCustomCommand(const QStringList &words, QString CommandController::execCustomCommand(
const Command &command, const QStringList &words, const Command &command, bool dryRun,
bool dryRun, ChannelPtr channel, ChannelPtr channel, const Message *message,
std::map<QString, QString> context) std::unordered_map<QString, QString> context)
{ {
QString result; QString result;
@@ -1167,20 +1300,21 @@ QString CommandController::execCustomCommand(const QStringList &words,
if (var != context.end()) if (var != context.end())
{ {
// Found variable in `context`
result += var->second.isEmpty() ? altText : var->second; result += var->second.isEmpty() ? altText : var->second;
continue;
} }
else
{
auto it = COMMAND_VARS.find(varName); auto it = COMMAND_VARS.find(varName);
if (it != COMMAND_VARS.end()) if (it != COMMAND_VARS.end())
{ {
result += it->second(altText, channel); // Found variable in `COMMAND_VARS`
result += it->second(altText, channel, message);
continue;
} }
else
{ // Fall back to replacing it with the actual matched string
result += "{" + match.captured(3) + "}"; result += "{" + match.captured(3) + "}";
}
}
continue; continue;
} }
@@ -11,6 +11,7 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <unordered_map>
namespace chatterino { namespace chatterino {
@@ -34,9 +35,10 @@ public:
CommandModel *createModel(QObject *parent); CommandModel *createModel(QObject *parent);
QString execCustomCommand(const QStringList &words, const Command &command, QString execCustomCommand(
bool dryRun, ChannelPtr channel, const QStringList &words, const Command &command, bool dryRun,
std::map<QString, QString> context = {}); ChannelPtr channel, const Message *message = nullptr,
std::unordered_map<QString, QString> context = {});
private: private:
void load(Paths &paths); void load(Paths &paths);
+5 -24
View File
@@ -2125,20 +2125,12 @@ void ChannelView::addCommandExecutionContextMenuItems(
{ {
userText = split->getInput().getInputText(); userText = split->getInput().getInputText();
} }
// Execute command through right-clicking a message -> Execute command
QString value = getApp()->commands->execCustomCommand( QString value = getApp()->commands->execCustomCommand(
inputText.split(' '), cmd, true, channel, inputText.split(' '), cmd, true, channel, layout->getMessage(),
{ {
{"user.name", layout->getMessage()->loginName},
{"msg.id", layout->getMessage()->id},
{"msg.text", layout->getMessage()->messageText},
{"input.text", userText}, {"input.text", userText},
// old placeholders
{"user", layout->getMessage()->loginName},
{"msg-id", layout->getMessage()->id},
{"message", layout->getMessage()->messageText},
{"channel", this->channel()->getName()},
}); });
value = getApp()->commands->execCommand(value, channel, false); value = getApp()->commands->execCommand(value, channel, false);
@@ -2283,21 +2275,10 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link,
} }
} }
// Execute command clicking a moderator button
value = getApp()->commands->execCustomCommand( value = getApp()->commands->execCustomCommand(
QStringList(), Command{"(modaction)", value}, true, channel, QStringList(), Command{"(modaction)", value}, true, channel,
{ layout->getMessage());
{"user.name", layout->getMessage()->loginName},
{"msg.id", layout->getMessage()->id},
{"msg.text", layout->getMessage()->messageText},
// old placeholders
{"user", layout->getMessage()->loginName},
{"msg-id", layout->getMessage()->id},
{"message", layout->getMessage()->messageText},
// new version of this is inside execCustomCommand
{"channel", this->channel()->getName()},
});
value = getApp()->commands->execCommand(value, channel, false); value = getApp()->commands->execCommand(value, channel, false);