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
+212 -78
View File
@@ -177,80 +177,213 @@ 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",
{ [](const auto &altText, const auto &channel, const auto *message) {
"channel.name", (void)(altText); //unused
[](const auto &altText, const auto &channel) { (void)(message); //unused
(void)(altText); //unused return channel->getName();
return channel->getName();
},
}, },
{ },
"channel.id", {
[](const auto &altText, const auto &channel) { "channel.id",
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); [](const auto &altText, const auto &channel, const auto *message) {
if (tc == nullptr) (void)(message); //unused
{ auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
return altText; if (tc == nullptr)
} {
return altText;
}
return tc->roomId(); return tc->roomId();
},
}, },
{ },
"stream.game", {
[](const auto &altText, const auto &channel) { // NOTE: The use of {channel} is deprecated and support for it will drop at some point
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); // Users should be encouraged to use {channel.name} instead.
if (tc == nullptr) "channel",
{ [](const auto &altText, const auto &channel, const auto *message) {
return altText; (void)(altText); //unused
} (void)(message); //unused
const auto &status = tc->accessStreamStatus(); return channel->getName();
return status->live ? status->game : altText;
},
}, },
{ },
"stream.title", {
[](const auto &altText, const auto &channel) { "stream.game",
auto *tc = dynamic_cast<TwitchChannel *>(channel.get()); [](const auto &altText, const auto &channel, const auto *message) {
if (tc == nullptr) (void)(message); //unused
{ auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
return altText; if (tc == nullptr)
} {
const auto &status = tc->accessStreamStatus(); return altText;
return status->live ? status->title : altText; }
}, const auto &status = tc->accessStreamStatus();
return status->live ? status->game : altText;
}, },
{ },
"my.id", {
[](const auto &altText, const auto &channel) { "stream.title",
(void)(channel); //unused [](const auto &altText, const auto &channel, const auto *message) {
auto uid = getApp()->accounts->twitch.getCurrent()->getUserId(); (void)(message); //unused
return uid.isEmpty() ? altText : uid; auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
}, if (tc == nullptr)
{
return altText;
}
const auto &status = tc->accessStreamStatus();
return status->live ? status->title : altText;
}, },
{ },
"my.name", {
[](const auto &altText, const auto &channel) { "my.id",
(void)(channel); //unused [](const auto &altText, const auto &channel, const auto *message) {
auto name = (void)(channel); //unused
getApp()->accounts->twitch.getCurrent()->getUserName(); (void)(message); //unused
return name.isEmpty() ? altText : name; auto uid = getApp()->accounts->twitch.getCurrent()->getUserId();
}, return uid.isEmpty() ? altText : uid;
}, },
// variables used in mod buttons and the like, these make no sense in normal commands, so they are left empty },
{"input.text", noOpPlaceholder}, {
{"msg.id", noOpPlaceholder}, "my.name",
{"user.name", noOpPlaceholder}, [](const auto &altText, const auto &channel, const auto *message) {
{"msg.text", noOpPlaceholder}, (void)(channel); //unused
}; (void)(message); //unused
auto name = getApp()->accounts->twitch.getCurrent()->getUserName();
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
{"input.text", NO_OP_PLACEHOLDER},
};
} // 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);
if (it != COMMAND_VARS.end())
{ {
auto it = COMMAND_VARS.find(varName); // Found variable in `COMMAND_VARS`
if (it != COMMAND_VARS.end()) result += it->second(altText, channel, message);
{ continue;
result += it->second(altText, channel);
}
else
{
result += "{" + match.captured(3) + "}";
}
} }
// Fall back to replacing it with the actual matched string
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);