mirror-chatterino2/src/singletons/commandmanager.cpp

283 lines
8.2 KiB
C++
Raw Normal View History

2017-12-31 00:50:07 +01:00
#include "singletons/commandmanager.hpp"
#include "application.hpp"
#include "debug/log.hpp"
#include "messages/messagebuilder.hpp"
#include "providers/twitch/twitchserver.hpp"
#include "singletons/accountmanager.hpp"
#include "singletons/pathmanager.hpp"
2017-12-27 19:50:05 +01:00
2018-04-09 22:59:19 +02:00
#include <QApplication>
2018-01-04 02:50:36 +01:00
#include <QFile>
2017-12-27 19:50:05 +01:00
#include <QRegularExpression>
2017-11-12 17:21:50 +01:00
2018-01-05 02:05:59 +01:00
#include "channel.hpp"
2018-02-05 15:11:50 +01:00
#include "providers/twitch/twitchchannel.hpp"
using namespace chatterino::providers::twitch;
2018-01-05 02:05:59 +01:00
2017-11-12 17:21:50 +01:00
namespace chatterino {
2017-12-31 22:58:35 +01:00
namespace singletons {
CommandManager::CommandManager()
{
auto addFirstMatchToMap = [this](auto args) {
this->commandsMap.remove(args.item.name);
for (const Command &cmd : this->commands.getVector()) {
if (cmd.name == args.item.name) {
this->commandsMap[cmd.name] = cmd;
break;
}
}
};
this->commands.itemInserted.connect(addFirstMatchToMap);
this->commands.itemRemoved.connect(addFirstMatchToMap);
}
void CommandManager::load()
2018-01-04 02:50:36 +01:00
{
auto app = getApp();
this->filePath = app->paths->customFolderPath + "/Commands.txt";
QFile textFile(this->filePath);
if (!textFile.open(QIODevice::ReadOnly)) {
// No commands file created yet
return;
}
QList<QByteArray> test = textFile.readAll().split('\n');
for (const auto &command : test) {
this->commands.appendItem(Command(command));
}
2018-01-04 02:50:36 +01:00
textFile.close();
2018-01-04 02:50:36 +01:00
}
void CommandManager::save()
2018-01-04 02:50:36 +01:00
{
QFile textFile(this->filePath);
if (!textFile.open(QIODevice::WriteOnly)) {
debug::Log("[CommandManager::saveCommands] Unable to open {} for writing", this->filePath);
return;
}
for (const Command &cmd : this->commands.getVector()) {
textFile.write((cmd.toString() + "\n").toUtf8());
2018-01-04 02:50:36 +01:00
}
textFile.close();
2018-01-04 02:50:36 +01:00
}
CommandModel *CommandManager::createModel(QObject *parent)
2018-01-04 02:50:36 +01:00
{
return new CommandModel(&this->commands, parent);
2018-01-04 02:50:36 +01:00
}
2018-02-05 15:11:50 +01:00
QString CommandManager::execCommand(const QString &text, ChannelPtr channel, bool dryRun)
2018-01-04 02:50:36 +01:00
{
QStringList words = text.split(' ', QString::SkipEmptyParts);
2018-01-05 02:05:59 +01:00
Command command;
2018-01-04 02:50:36 +01:00
{
std::lock_guard<std::mutex> lock(this->mutex);
if (words.length() == 0) {
return text;
}
QString commandName = words[0];
2018-01-05 02:05:59 +01:00
// check if default command exists
2018-02-05 15:11:50 +01:00
auto *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
2018-01-05 02:05:59 +01:00
if (!dryRun && twitchChannel != nullptr) {
2018-04-09 22:59:19 +02:00
if (commandName == "/debug-args") {
QString msg = QApplication::instance()->arguments().join(' ');
channel->addMessage(messages::Message::createSystemMessage(msg));
return "";
} else if (commandName == "/uptime") {
const auto &streamStatus = twitchChannel->GetStreamStatus();
2018-01-05 02:05:59 +01:00
QString messageText =
streamStatus.live ? streamStatus.uptime : "Channel is not live.";
channel->addMessage(messages::Message::createSystemMessage(messageText));
2018-01-05 02:05:59 +01:00
return "";
} else if (commandName == "/ignore" && words.size() >= 2) {
2018-02-05 15:11:50 +01:00
// fourtf: ignore user
// QString messageText;
2018-01-05 02:05:59 +01:00
2018-02-05 15:11:50 +01:00
// if (IrcManager::getInstance().tryAddIgnoredUser(words.at(1),
// messageText)) {
// messageText = "Ignored user \"" + words.at(1) + "\".";
// }
2018-01-05 02:05:59 +01:00
2018-02-05 15:11:50 +01:00
// channel->addMessage(messages::Message::createSystemMessage(messageText));
2018-01-05 02:05:59 +01:00
return "";
} else if (commandName == "/unignore") {
2018-02-05 15:11:50 +01:00
// fourtf: ignore user
// QString messageText;
2018-01-05 02:05:59 +01:00
2018-02-05 15:11:50 +01:00
// if (IrcManager::getInstance().tryRemoveIgnoredUser(words.at(1),
// messageText)) {
// messageText = "Ignored user \"" + words.at(1) + "\".";
// }
2018-01-05 02:05:59 +01:00
2018-02-05 15:11:50 +01:00
// channel->addMessage(messages::Message::createSystemMessage(messageText));
2018-01-05 02:05:59 +01:00
return "";
} else if (commandName == "/w") {
if (words.length() <= 2) {
return "";
}
auto app = getApp();
messages::MessageBuilder b;
b.emplace<messages::TextElement>(app->accounts->Twitch.getCurrent()->getUserName(),
messages::MessageElement::Text);
b.emplace<messages::TextElement>("->", messages::MessageElement::Text);
b.emplace<messages::TextElement>(words[1], messages::MessageElement::Text);
QString rest = "";
for (int i = 2; i < words.length(); i++) {
rest += words[i];
}
b.emplace<messages::TextElement>(rest, messages::MessageElement::Text);
app->twitch.server->whispersChannel->addMessage(b.getMessage());
2018-01-05 02:05:59 +01:00
}
}
// check if custom command exists
auto it = this->commandsMap.find(commandName);
if (it == this->commandsMap.end()) {
2018-01-04 02:50:36 +01:00
return text;
}
command = it.value();
}
2018-01-05 02:05:59 +01:00
return this->execCustomCommand(words, command);
}
QString CommandManager::execCustomCommand(const QStringList &words, const Command &command)
{
2018-01-04 02:50:36 +01:00
QString result;
static QRegularExpression parseCommand("(^|[^{])({{)*{(\\d+\\+?)}");
int lastCaptureEnd = 0;
auto globalMatch = parseCommand.globalMatch(command.func);
2018-01-04 02:50:36 +01:00
int matchOffset = 0;
while (true) {
QRegularExpressionMatch match = parseCommand.match(command.func, matchOffset);
2018-01-04 02:50:36 +01:00
if (!match.hasMatch()) {
break;
}
result += command.func.mid(lastCaptureEnd, match.capturedStart() - lastCaptureEnd + 1);
2018-01-04 02:50:36 +01:00
lastCaptureEnd = match.capturedEnd();
matchOffset = lastCaptureEnd - 1;
QString wordIndexMatch = match.captured(3);
bool plus = wordIndexMatch.at(wordIndexMatch.size() - 1) == '+';
wordIndexMatch = wordIndexMatch.replace("+", "");
bool ok;
int wordIndex = wordIndexMatch.replace("=", "").toInt(&ok);
if (!ok || wordIndex == 0) {
result += "{" + match.captured(3) + "}";
continue;
}
if (words.length() <= wordIndex) {
continue;
}
if (plus) {
bool first = true;
for (int i = wordIndex; i < words.length(); i++) {
if (!first) {
result += " ";
}
result += words[i];
first = false;
}
} else {
result += words[wordIndex];
}
}
result += command.func.mid(lastCaptureEnd);
2018-01-04 02:50:36 +01:00
if (result.size() > 0 && result.at(0) == '{') {
result = result.mid(1);
}
return result.replace("{{", "{");
}
// commandmodel
CommandModel::CommandModel(util::BaseSignalVector<Command> *vec, QObject *parent)
: util::SignalVectorModel<Command>(vec, 2, parent)
{
}
int CommandModel::prepareInsert(const Command &item, int index,
std::vector<QStandardItem *> &rowToAdd)
{
rowToAdd[0]->setData(item.name, Qt::EditRole);
rowToAdd[1]->setData(item.func, Qt::EditRole);
return index;
}
int CommandModel::prepareRemove(const Command &item, int index)
{
UNUSED(item);
return index;
}
// command
Command::Command(const QString &_text)
2018-01-04 02:50:36 +01:00
{
int index = _text.indexOf(' ');
if (index == -1) {
this->name = _text;
2018-01-04 02:50:36 +01:00
return;
}
this->name = _text.mid(0, index);
this->func = _text.mid(index + 1);
}
Command::Command(const QString &_name, const QString &_func)
: name(_name)
, func(_func)
{
}
QString Command::toString() const
{
return this->name + " " + this->func;
2018-01-04 02:50:36 +01:00
}
2018-01-05 02:05:38 +01:00
} // namespace singletons
} // namespace chatterino