mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Move most Command variables into the CommandController
shared variables (#3824)
This commit is contained in:
parent
6a58ce1273
commit
34ea303607
|
@ -41,6 +41,7 @@
|
|||
- 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: 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
|
||||
|
||||
|
|
|
@ -177,80 +177,213 @@ bool appendWhisperMessageStringLocally(const QString &textNoEmoji)
|
|||
return false;
|
||||
}
|
||||
|
||||
const std::function<QString(const QString &, const ChannelPtr &)>
|
||||
noOpPlaceholder = [](const auto &altText, const auto &channel) {
|
||||
using VariableReplacer = std::function<QString(
|
||||
const QString &, const ChannelPtr &, const Message *)>;
|
||||
|
||||
const VariableReplacer NO_OP_PLACEHOLDER =
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
return altText;
|
||||
};
|
||||
|
||||
const std::map<QString,
|
||||
std::function<QString(const QString &, const ChannelPtr &)>>
|
||||
COMMAND_VARS{
|
||||
{
|
||||
"channel.name",
|
||||
[](const auto &altText, const auto &channel) {
|
||||
(void)(altText); //unused
|
||||
return channel->getName();
|
||||
},
|
||||
const std::unordered_map<QString, VariableReplacer> COMMAND_VARS{
|
||||
{
|
||||
"channel.name",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(void)(altText); //unused
|
||||
(void)(message); //unused
|
||||
return channel->getName();
|
||||
},
|
||||
{
|
||||
"channel.id",
|
||||
[](const auto &altText, const auto &channel) {
|
||||
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||
if (tc == nullptr)
|
||||
{
|
||||
return altText;
|
||||
}
|
||||
},
|
||||
{
|
||||
"channel.id",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(void)(message); //unused
|
||||
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||
if (tc == nullptr)
|
||||
{
|
||||
return altText;
|
||||
}
|
||||
|
||||
return tc->roomId();
|
||||
},
|
||||
return tc->roomId();
|
||||
},
|
||||
{
|
||||
"stream.game",
|
||||
[](const auto &altText, const auto &channel) {
|
||||
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||
if (tc == nullptr)
|
||||
{
|
||||
return altText;
|
||||
}
|
||||
const auto &status = tc->accessStreamStatus();
|
||||
return status->live ? status->game : altText;
|
||||
},
|
||||
},
|
||||
{
|
||||
// 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.title",
|
||||
[](const auto &altText, const auto &channel) {
|
||||
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||
if (tc == nullptr)
|
||||
{
|
||||
return altText;
|
||||
}
|
||||
const auto &status = tc->accessStreamStatus();
|
||||
return status->live ? status->title : altText;
|
||||
},
|
||||
},
|
||||
{
|
||||
"stream.game",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(void)(message); //unused
|
||||
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||
if (tc == nullptr)
|
||||
{
|
||||
return altText;
|
||||
}
|
||||
const auto &status = tc->accessStreamStatus();
|
||||
return status->live ? status->game : altText;
|
||||
},
|
||||
{
|
||||
"my.id",
|
||||
[](const auto &altText, const auto &channel) {
|
||||
(void)(channel); //unused
|
||||
auto uid = getApp()->accounts->twitch.getCurrent()->getUserId();
|
||||
return uid.isEmpty() ? altText : uid;
|
||||
},
|
||||
},
|
||||
{
|
||||
"stream.title",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(void)(message); //unused
|
||||
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) {
|
||||
(void)(channel); //unused
|
||||
auto name =
|
||||
getApp()->accounts->twitch.getCurrent()->getUserName();
|
||||
return name.isEmpty() ? altText : name;
|
||||
},
|
||||
},
|
||||
{
|
||||
"my.id",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(void)(channel); //unused
|
||||
(void)(message); //unused
|
||||
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},
|
||||
{"user.name", noOpPlaceholder},
|
||||
{"msg.text", noOpPlaceholder},
|
||||
};
|
||||
},
|
||||
{
|
||||
"my.name",
|
||||
[](const auto &altText, const auto &channel, const auto *message) {
|
||||
(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
|
||||
|
||||
|
@ -1120,10 +1253,10 @@ void CommandController::registerCommand(QString commandName,
|
|||
this->defaultChatterinoCommandAutoCompletions_.append(commandName);
|
||||
}
|
||||
|
||||
QString CommandController::execCustomCommand(const QStringList &words,
|
||||
const Command &command,
|
||||
bool dryRun, ChannelPtr channel,
|
||||
std::map<QString, QString> context)
|
||||
QString CommandController::execCustomCommand(
|
||||
const QStringList &words, const Command &command, bool dryRun,
|
||||
ChannelPtr channel, const Message *message,
|
||||
std::unordered_map<QString, QString> context)
|
||||
{
|
||||
QString result;
|
||||
|
||||
|
@ -1167,20 +1300,21 @@ QString CommandController::execCustomCommand(const QStringList &words,
|
|||
|
||||
if (var != context.end())
|
||||
{
|
||||
// Found variable in `context`
|
||||
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);
|
||||
if (it != COMMAND_VARS.end())
|
||||
{
|
||||
result += it->second(altText, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "{" + match.captured(3) + "}";
|
||||
}
|
||||
// Found variable in `COMMAND_VARS`
|
||||
result += it->second(altText, channel, message);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fall back to replacing it with the actual matched string
|
||||
result += "{" + match.captured(3) + "}";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
|
@ -34,9 +35,10 @@ public:
|
|||
|
||||
CommandModel *createModel(QObject *parent);
|
||||
|
||||
QString execCustomCommand(const QStringList &words, const Command &command,
|
||||
bool dryRun, ChannelPtr channel,
|
||||
std::map<QString, QString> context = {});
|
||||
QString execCustomCommand(
|
||||
const QStringList &words, const Command &command, bool dryRun,
|
||||
ChannelPtr channel, const Message *message = nullptr,
|
||||
std::unordered_map<QString, QString> context = {});
|
||||
|
||||
private:
|
||||
void load(Paths &paths);
|
||||
|
|
|
@ -2125,20 +2125,12 @@ void ChannelView::addCommandExecutionContextMenuItems(
|
|||
{
|
||||
userText = split->getInput().getInputText();
|
||||
}
|
||||
|
||||
// Execute command through right-clicking a message -> Execute command
|
||||
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},
|
||||
|
||||
// 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);
|
||||
|
@ -2283,21 +2275,10 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link,
|
|||
}
|
||||
}
|
||||
|
||||
// Execute command clicking a moderator button
|
||||
value = getApp()->commands->execCustomCommand(
|
||||
QStringList(), Command{"(modaction)", value}, true, channel,
|
||||
{
|
||||
{"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()},
|
||||
});
|
||||
layout->getMessage());
|
||||
|
||||
value = getApp()->commands->execCommand(value, channel, false);
|
||||
|
||||
|
|
Loading…
Reference in a new issue