mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Add viewing logs to UserInfoPopup (#548)
* Add cbenni logviewer * Remove unneeded includes * Updated getLogs to check for logs on Overrustle will check logs on overrustle if none were found on cbenni * Formatting, fix some bugs * Fixes per PR comments * Should really take more time when pushing * Changes per PR, simplify code a lot * Style/formatting fixes
This commit is contained in:
parent
eeb514c444
commit
086ae010b1
6 changed files with 191 additions and 1 deletions
|
@ -166,6 +166,7 @@ SOURCES += \
|
||||||
src/widgets/dialogs/EmotePopup.cpp \
|
src/widgets/dialogs/EmotePopup.cpp \
|
||||||
src/widgets/dialogs/LastRunCrashDialog.cpp \
|
src/widgets/dialogs/LastRunCrashDialog.cpp \
|
||||||
src/widgets/dialogs/LoginDialog.cpp \
|
src/widgets/dialogs/LoginDialog.cpp \
|
||||||
|
src/widgets/dialogs/LogsPopup.cpp \
|
||||||
src/widgets/dialogs/NotificationPopup.cpp \
|
src/widgets/dialogs/NotificationPopup.cpp \
|
||||||
src/widgets/dialogs/QualityPopup.cpp \
|
src/widgets/dialogs/QualityPopup.cpp \
|
||||||
src/widgets/dialogs/SelectChannelDialog.cpp \
|
src/widgets/dialogs/SelectChannelDialog.cpp \
|
||||||
|
@ -223,6 +224,7 @@ SOURCES += \
|
||||||
src/singletons/Settings.cpp \
|
src/singletons/Settings.cpp \
|
||||||
src/singletons/Updates.cpp \
|
src/singletons/Updates.cpp \
|
||||||
src/singletons/Theme.cpp \
|
src/singletons/Theme.cpp \
|
||||||
|
src/widgets/dialogs/LogsPopup.cpp \
|
||||||
src/controllers/moderationactions/ModerationActionModel.cpp \
|
src/controllers/moderationactions/ModerationActionModel.cpp \
|
||||||
src/widgets/settingspages/LookPage.cpp \
|
src/widgets/settingspages/LookPage.cpp \
|
||||||
src/widgets/settingspages/FeelPage.cpp \
|
src/widgets/settingspages/FeelPage.cpp \
|
||||||
|
@ -335,6 +337,7 @@ HEADERS += \
|
||||||
src/widgets/dialogs/EmotePopup.hpp \
|
src/widgets/dialogs/EmotePopup.hpp \
|
||||||
src/widgets/dialogs/LastRunCrashDialog.hpp \
|
src/widgets/dialogs/LastRunCrashDialog.hpp \
|
||||||
src/widgets/dialogs/LoginDialog.hpp \
|
src/widgets/dialogs/LoginDialog.hpp \
|
||||||
|
src/widgets/dialogs/LogsPopup.hpp \
|
||||||
src/widgets/dialogs/NotificationPopup.hpp \
|
src/widgets/dialogs/NotificationPopup.hpp \
|
||||||
src/widgets/dialogs/QualityPopup.hpp \
|
src/widgets/dialogs/QualityPopup.hpp \
|
||||||
src/widgets/dialogs/SelectChannelDialog.hpp \
|
src/widgets/dialogs/SelectChannelDialog.hpp \
|
||||||
|
@ -398,6 +401,7 @@ HEADERS += \
|
||||||
src/singletons/Theme.hpp \
|
src/singletons/Theme.hpp \
|
||||||
src/common/SimpleSignalVector.hpp \
|
src/common/SimpleSignalVector.hpp \
|
||||||
src/common/SignalVector.hpp \
|
src/common/SignalVector.hpp \
|
||||||
|
src/widgets/dialogs/LogsPopup.hpp \
|
||||||
src/common/Singleton.hpp \
|
src/common/Singleton.hpp \
|
||||||
src/controllers/moderationactions/ModerationActionModel.hpp \
|
src/controllers/moderationactions/ModerationActionModel.hpp \
|
||||||
src/widgets/settingspages/LookPage.hpp \
|
src/widgets/settingspages/LookPage.hpp \
|
||||||
|
|
|
@ -217,7 +217,9 @@ public:
|
||||||
QObject::connect(worker, &NetworkWorker::doneUrl, this->data.caller,
|
QObject::connect(worker, &NetworkWorker::doneUrl, this->data.caller,
|
||||||
[ onFinished, data = this->data ](auto reply) mutable {
|
[ onFinished, data = this->data ](auto reply) mutable {
|
||||||
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
||||||
// TODO: We might want to call an onError callback here
|
if (data.onError) {
|
||||||
|
data.onError(reply->error());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
143
src/widgets/dialogs/LogsPopup.cpp
Normal file
143
src/widgets/dialogs/LogsPopup.cpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#include "LogsPopup.hpp"
|
||||||
|
|
||||||
|
#include "IrcMessage"
|
||||||
|
#include "common/NetworkRequest.hpp"
|
||||||
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
|
#include "providers/twitch/TwitchMessageBuilder.hpp"
|
||||||
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
LogsPopup::LogsPopup()
|
||||||
|
{
|
||||||
|
this->initLayout();
|
||||||
|
this->resize(400, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsPopup::initLayout()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
layout->setMargin(0);
|
||||||
|
|
||||||
|
this->channelView_ = new ChannelView(this);
|
||||||
|
layout->addWidget(this->channelView_);
|
||||||
|
|
||||||
|
this->setLayout(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsPopup::setInfo(ChannelPtr channel, QString userName)
|
||||||
|
{
|
||||||
|
this->channel_ = channel;
|
||||||
|
this->userName_ = userName;
|
||||||
|
this->setWindowTitle(this->userName_ + "'s logs in #" + this->channel_->name);
|
||||||
|
this->getLogviewerLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsPopup::setMessages(std::vector<MessagePtr> &messages)
|
||||||
|
{
|
||||||
|
ChannelPtr logsChannel(new Channel("logs", Channel::Misc));
|
||||||
|
|
||||||
|
logsChannel->addMessagesAtStart(messages);
|
||||||
|
this->channelView_->setChannel(logsChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsPopup::getLogviewerLogs()
|
||||||
|
{
|
||||||
|
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
|
||||||
|
if (twitchChannel == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString channelName = twitchChannel->name;
|
||||||
|
|
||||||
|
QString url = QString("https://cbenni.com/api/logs/%1/?nick=%2&before=500")
|
||||||
|
.arg(channelName, this->userName_);
|
||||||
|
|
||||||
|
NetworkRequest req(url);
|
||||||
|
req.setCaller(QThread::currentThread());
|
||||||
|
|
||||||
|
req.onError([this](int errorCode) {
|
||||||
|
this->getOverrustleLogs();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.getJSON([this, channelName](QJsonObject &data) {
|
||||||
|
|
||||||
|
std::vector<MessagePtr> messages;
|
||||||
|
ChannelPtr logsChannel(new Channel("logs", Channel::None));
|
||||||
|
|
||||||
|
QJsonValue before = data.value("before");
|
||||||
|
|
||||||
|
for (auto i : before.toArray()) {
|
||||||
|
auto messageObject = i.toObject();
|
||||||
|
QString message = messageObject.value("text").toString();
|
||||||
|
|
||||||
|
// Hacky way to fix the timestamp
|
||||||
|
message.insert(1, "historical=1;");
|
||||||
|
message.insert(1, QString("tmi-sent-ts=%10000;").arg(messageObject["time"].toInt()));
|
||||||
|
|
||||||
|
MessageParseArgs args;
|
||||||
|
auto ircMessage = Communi::IrcMessage::fromData(message.toUtf8(), nullptr);
|
||||||
|
auto privMsg = static_cast<Communi::IrcPrivateMessage *>(ircMessage);
|
||||||
|
TwitchMessageBuilder builder(logsChannel.get(), privMsg, args);
|
||||||
|
messages.push_back(builder.build());
|
||||||
|
};
|
||||||
|
this->setMessages(messages);
|
||||||
|
});
|
||||||
|
|
||||||
|
req.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsPopup::getOverrustleLogs()
|
||||||
|
{
|
||||||
|
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
|
||||||
|
if (twitchChannel == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString channelName = twitchChannel->name;
|
||||||
|
|
||||||
|
QString url = QString("https://overrustlelogs.net/api/v1/stalk/%1/%2.json?limit=500")
|
||||||
|
.arg(channelName, this->userName_);
|
||||||
|
|
||||||
|
NetworkRequest req(url);
|
||||||
|
req.setCaller(QThread::currentThread());
|
||||||
|
req.onError([this, channelName](int errorCode) {
|
||||||
|
this->close();
|
||||||
|
QMessageBox *box = new QMessageBox(QMessageBox::Information, "Error getting logs",
|
||||||
|
"No logs could be found for channel " + channelName);
|
||||||
|
box->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
box->show();
|
||||||
|
box->raise();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
req.getJSON([this, channelName](QJsonObject &data) {
|
||||||
|
std::vector<MessagePtr> messages;
|
||||||
|
if (data.contains("lines")) {
|
||||||
|
QJsonArray dataMessages = data.value("lines").toArray();
|
||||||
|
for (auto i : dataMessages) {
|
||||||
|
QJsonObject singleMessage = i.toObject();
|
||||||
|
QTime timeStamp =
|
||||||
|
QDateTime::fromSecsSinceEpoch(singleMessage.value("timestamp").toInt()).time();
|
||||||
|
|
||||||
|
MessagePtr message(new Message);
|
||||||
|
message->addElement(new TimestampElement(timeStamp));
|
||||||
|
message->addElement(new TextElement(this->userName_, MessageElement::Username,
|
||||||
|
MessageColor::System));
|
||||||
|
message->addElement(new TextElement(singleMessage.value("text").toString(),
|
||||||
|
MessageElement::Text, MessageColor::Text));
|
||||||
|
messages.push_back(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->setMessages(messages);
|
||||||
|
});
|
||||||
|
req.execute();
|
||||||
|
}
|
||||||
|
} // namespace chatterino
|
30
src/widgets/dialogs/LogsPopup.hpp
Normal file
30
src/widgets/dialogs/LogsPopup.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/Channel.hpp"
|
||||||
|
#include "widgets/BaseWindow.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
class Channel;
|
||||||
|
class ChannelView;
|
||||||
|
|
||||||
|
class LogsPopup : public BaseWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LogsPopup();
|
||||||
|
|
||||||
|
void setInfo(std::shared_ptr<Channel> channel, QString userName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChannelView *channelView_ = nullptr;
|
||||||
|
ChannelPtr channel_ = Channel::getEmpty();
|
||||||
|
|
||||||
|
QString userName_;
|
||||||
|
|
||||||
|
void initLayout();
|
||||||
|
void setMessages(std::vector<MessagePtr> &messages);
|
||||||
|
void getOverrustleLogs();
|
||||||
|
void getLogviewerLogs();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
|
@ -7,6 +7,7 @@
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "util/PostToThread.hpp"
|
#include "util/PostToThread.hpp"
|
||||||
#include "widgets/Label.hpp"
|
#include "widgets/Label.hpp"
|
||||||
|
#include "widgets/dialogs/LogsPopup.hpp"
|
||||||
#include "widgets/helper/Line.hpp"
|
#include "widgets/helper/Line.hpp"
|
||||||
#include "widgets/helper/RippleEffectLabel.hpp"
|
#include "widgets/helper/RippleEffectLabel.hpp"
|
||||||
|
|
||||||
|
@ -68,6 +69,8 @@ UserInfoPopup::UserInfoPopup()
|
||||||
user.emplace<QCheckBox>("Follow").assign(&this->ui_.follow);
|
user.emplace<QCheckBox>("Follow").assign(&this->ui_.follow);
|
||||||
user.emplace<QCheckBox>("Ignore").assign(&this->ui_.ignore);
|
user.emplace<QCheckBox>("Ignore").assign(&this->ui_.ignore);
|
||||||
user.emplace<QCheckBox>("Ignore highlights").assign(&this->ui_.ignoreHighlights);
|
user.emplace<QCheckBox>("Ignore highlights").assign(&this->ui_.ignoreHighlights);
|
||||||
|
auto viewLogs = user.emplace<RippleEffectLabel>(this).assign(&this->ui_.viewLogs);
|
||||||
|
this->ui_.viewLogs->getLabel().setText("Logs");
|
||||||
|
|
||||||
auto mod = user.emplace<RippleEffectButton>(this);
|
auto mod = user.emplace<RippleEffectButton>(this);
|
||||||
mod->setPixmap(app->resources->buttons.mod);
|
mod->setPixmap(app->resources->buttons.mod);
|
||||||
|
@ -78,6 +81,13 @@ UserInfoPopup::UserInfoPopup()
|
||||||
|
|
||||||
user->addStretch(1);
|
user->addStretch(1);
|
||||||
|
|
||||||
|
QObject::connect(viewLogs.getElement(), &RippleEffectLabel::clicked, [this] {
|
||||||
|
auto logs = new LogsPopup();
|
||||||
|
logs->setInfo(this->channel_, this->userName_);
|
||||||
|
logs->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
logs->show();
|
||||||
|
});
|
||||||
|
|
||||||
QObject::connect(mod.getElement(), &RippleEffectButton::clicked,
|
QObject::connect(mod.getElement(), &RippleEffectButton::clicked,
|
||||||
[this] { this->channel_->sendMessage("/mod " + this->userName_); });
|
[this] { this->channel_->sendMessage("/mod " + this->userName_); });
|
||||||
QObject::connect(unmod.getElement(), &RippleEffectButton::clicked,
|
QObject::connect(unmod.getElement(), &RippleEffectButton::clicked,
|
||||||
|
|
|
@ -42,6 +42,7 @@ private:
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
RippleEffectButton *avatarButton = nullptr;
|
RippleEffectButton *avatarButton = nullptr;
|
||||||
|
RippleEffectLabel *viewLogs = nullptr;
|
||||||
|
|
||||||
Label *nameLabel = nullptr;
|
Label *nameLabel = nullptr;
|
||||||
Label *viewCountLabel = nullptr;
|
Label *viewCountLabel = nullptr;
|
||||||
|
|
Loading…
Reference in a new issue