Do not do any of the migration crap

This diff is horrendous I am sorry.
This commit is contained in:
Mm2PL 2024-05-14 14:45:40 +02:00
parent 847a300e36
commit fb8584a51d
No known key found for this signature in database
GPG key ID: 94AC9B80EFA15ED9
4 changed files with 127 additions and 204 deletions

View file

@ -446,7 +446,6 @@ set(SOURCE_FILES
singletons/Fonts.hpp
singletons/imageuploader/ImageUploader.cpp
singletons/imageuploader/ImageUploader.hpp
singletons/imageuploader/UploadedImage.hpp
singletons/imageuploader/UploadedImageModel.cpp
singletons/imageuploader/UploadedImageModel.hpp
singletons/Logging.cpp

View file

@ -13,6 +13,7 @@
#include "singletons/Settings.hpp"
#include "util/CombinePath.hpp"
#include "util/RapidjsonHelpers.hpp"
#include "util/Result.hpp"
#include "widgets/helper/ResizingTextEdit.hpp"
#include <QBuffer>
@ -28,6 +29,7 @@
#include <rapidjson/document.h>
#include <memory>
#include <vector>
#include <utility>
@ -50,6 +52,48 @@ std::optional<QByteArray> convertToPng(const QImage &image)
return std::nullopt;
}
using namespace chatterino;
Result<std::vector<UploadedImage>, QString> loadLogFile(
const QString &logFileName)
{
//reading existing logs
QFile logReadFile(logFileName);
bool isLogFileOkay =
logReadFile.open(QIODevice::ReadWrite | QIODevice::Text);
if (!isLogFileOkay)
{
return QString("Failed to open log file with links at ") + logFileName;
}
auto logs = logReadFile.readAll();
if (logs.isEmpty())
{
logs = QJsonDocument(QJsonArray()).toJson();
}
logReadFile.close();
QJsonArray entries = QJsonDocument::fromJson(logs).array();
std::vector<UploadedImage> images;
for (const auto &entry : entries)
{
if (!entry.isObject())
{
qCWarning(chatterinoImageuploader)
<< "History file contains non-Object JSON data!";
continue;
}
auto obj = entry.toObject();
images.emplace_back(obj);
}
return images;
}
QString getLogFilePath()
{
return combinePath((getSettings()->logPath.getValue().isEmpty()
? getIApp()->getPaths().messageLogDirectory
: getSettings()->logPath),
"ImageUploader.json");
}
} // namespace
namespace chatterino {
@ -59,51 +103,36 @@ void ImageUploader::logToFile(const QString &originalFilePath,
const QString &imageLink,
const QString &deletionLink, ChannelPtr channel)
{
const QString logFileName =
combinePath((getSettings()->logPath.getValue().isEmpty()
? getIApp()->getPaths().messageLogDirectory
: getSettings()->logPath),
"ImageUploader.json");
//reading existing logs
QFile logReadFile(logFileName);
bool isLogFileOkay =
logReadFile.open(QIODevice::ReadWrite | QIODevice::Text);
if (!isLogFileOkay)
const QString logFileName = getLogFilePath();
auto res = loadLogFile(logFileName);
if (!res.isOk())
{
channel->addMessage(makeSystemMessage(
QString("Failed to open log file with links at ") + logFileName));
channel->addMessage(makeSystemMessage(res.error()));
return;
}
auto logs = logReadFile.readAll();
if (logs.isEmpty())
{
logs = QJsonDocument(QJsonArray()).toJson();
}
logReadFile.close();
auto entries = res.value();
//writing new data to logs
QJsonObject newLogEntry;
newLogEntry["channelName"] = channel->getName();
newLogEntry["deletionLink"] =
deletionLink.isEmpty() ? QJsonValue(QJsonValue::Null) : deletionLink;
newLogEntry["imageLink"] = imageLink;
newLogEntry["localPath"] = originalFilePath.isEmpty()
? QJsonValue(QJsonValue::Null)
: originalFilePath;
newLogEntry["timestamp"] = QDateTime::currentSecsSinceEpoch();
UploadedImage img;
img.channelName = channel->getName();
img.deletionLink = deletionLink;
img.imageLink = imageLink;
img.localPath = originalFilePath;
img.timestamp = QDateTime::currentSecsSinceEpoch();
entries.push_back(img);
// channel name
// deletion link (can be empty)
// image link
// local path to an image (can be empty)
// timestamp
QJsonArray arr;
for (auto &entry : entries)
{
arr.append(entry.toJson());
}
QSaveFile logSaveFile(logFileName);
logSaveFile.open(QIODevice::WriteOnly | QIODevice::Text);
QJsonArray entries = QJsonDocument::fromJson(logs).array();
entries.push_back(newLogEntry);
logSaveFile.write(QJsonDocument(entries).toJson());
logSaveFile.write(QJsonDocument(arr).toJson());
logSaveFile.commit();
//>>>>>>> e7508332ff1399a89424bfdc0997f979fd0c9acc:src/singletons/ImageUploader.cpp
}
// extracting link to either image or its deletion from response body
@ -133,86 +162,30 @@ QString getLinkFromResponse(NetworkResult response, QString pattern)
void ImageUploader::save()
{
this->sm_->save();
}
UploadedImageModel *ImageUploader::createModel(QObject *parent)
{
auto *model = new UploadedImageModel(parent);
auto res = loadLogFile(getLogFilePath());
// Replace content of images_
auto len = this->images_.raw().size();
for (int i = 0; i < len; i++)
{
this->images_.removeAt(0);
}
std::vector<UploadedImage> vec = res.valueOr({});
for (const auto &img : vec)
{
this->images_.append(img);
}
model->initialize(&this->images_);
return model;
}
void ImageUploader::initialize(Settings &settings, const Paths &paths)
{
auto logPath = (getSettings()->logPath.getValue().isEmpty()
? paths.messageLogDirectory
: getSettings()->logPath);
const QString oldLogName = combinePath(logPath, "ImageUploader.json");
// read/write new one
const QString path = combinePath(logPath, "ImageUploader2.json");
this->sm_ = std::make_shared<pajlada::Settings::SettingManager>();
this->sm_->setPath(qPrintable(path));
this->sm_->setBackupEnabled(true);
this->sm_->setBackupSlots(9);
this->uploadedImagesSetting_ = std::make_unique<
pajlada::Settings::Setting<std::vector<UploadedImage>>>(
"/uploadedImages", this->sm_);
this->sm_->load();
// try to read old log
QFile oldLogFile(oldLogName);
bool isOldLogFileOkay =
oldLogFile.open(QIODevice::ReadOnly | QIODevice::Text);
if (isOldLogFileOkay)
{
auto data = oldLogFile.readAll();
rapidjson::Document doc;
doc.Parse(data.data(), data.size());
if (doc.HasParseError())
{
qCWarning(chatterinoCommon) << "Unable to read ImageUploader.json";
return;
}
std::vector<UploadedImage> temporary;
if (!doc.IsArray())
{
qCWarning(chatterinoCommon)
<< "Unable to parse ImageUploader.json: not an array";
return;
}
if (!rj::getSafe(doc, temporary))
{
qCWarning(chatterinoCommon)
<< "Unable to parse ImageUploader.json: getSafe failed";
return;
}
for (const auto &t : temporary)
{
this->images_.append(t);
}
oldLogFile.close();
oldLogFile.rename(combinePath(logPath, "ImageUploader.old.json"));
}
for (const auto &item : this->uploadedImagesSetting_->getValue())
{
this->images_.append(item);
}
this->signals_.addConnection(
this->images_.delayedItemsChanged.connect([this]() {
this->uploadedImagesSetting_->setValue(this->images_.raw());
}));
if (isOldLogFileOkay)
{
this->uploadedImagesSetting_->setValue(this->images_.raw());
this->sm_->save();
}
}
void ImageUploader::sendImageUploadRequest(RawImageData imageData,
ChannelPtr channel,
QPointer<ResizingTextEdit> textEdit)

View file

@ -2,19 +2,17 @@
#include "common/SignalVector.hpp"
#include "common/Singleton.hpp"
#include "pajlada/settings/setting.hpp"
#include "pajlada/settings/settingmanager.hpp"
#include "singletons/imageuploader/UploadedImage.hpp"
#include "singletons/imageuploader/UploadedImageModel.hpp"
#include <pajlada/signals/signalholder.hpp>
#include <QJsonObject>
#include <QMimeData>
#include <QMutex>
#include <qobject.h>
#include <QObject>
#include <QString>
#include <memory>
#include <queue>
#include <vector>
namespace chatterino {
@ -23,12 +21,58 @@ class Channel;
class NetworkResult;
using ChannelPtr = std::shared_ptr<Channel>;
struct UploadedImage {
QString channelName;
QString deletionLink;
QString imageLink;
QString localPath;
int64_t timestamp{};
UploadedImage() = default;
UploadedImage(QJsonObject obj)
: channelName(obj["channelName"].toString())
, imageLink(obj["imageLink"].toString())
, timestamp(obj["timestamp"].toInt())
{
auto del = obj["deletionLink"];
if (!del.isNull())
{
this->deletionLink = del.toString();
}
auto path = obj["localPath"];
if (!path.isNull())
{
this->localPath = path.toString();
}
}
QJsonObject toJson() const
{
QJsonObject out;
out["channelName"] = this->channelName;
out["deletionLink"] = this->deletionLink.isEmpty()
? QJsonValue(QJsonValue::Null)
: this->deletionLink;
out["imageLink"] = this->imageLink;
out["localPath"] = this->localPath.isEmpty()
? QJsonValue(QJsonValue::Null)
: this->localPath;
// without cast, this is ambiguous
out["timestamp"] = (qint64)this->timestamp;
return out;
}
};
class UploadedImageModel;
struct RawImageData {
QByteArray data;
QString format;
QString filePath;
};
class UploadedImageModel;
class ImageUploader final : public Singleton
{
public:
@ -43,7 +87,6 @@ public:
void save() override;
void upload(std::queue<RawImageData> images, ChannelPtr channel,
QPointer<ResizingTextEdit> outputTextEdit);
void initialize(Settings &settings, const Paths &paths) override;
UploadedImageModel *createModel(QObject *parent);
private:
@ -58,15 +101,11 @@ private:
void logToFile(const QString &originalFilePath, const QString &imageLink,
const QString &deletionLink, ChannelPtr channel);
// These variables are only used from the main thread.
QMutex uploadMutex_;
std::queue<RawImageData> uploadQueue_;
std::shared_ptr<pajlada::Settings::SettingManager> sm_;
SignalVector<UploadedImage> images_;
std::unique_ptr<pajlada::Settings::Setting<std::vector<UploadedImage>>>
uploadedImagesSetting_;
pajlada::Signals::SignalHolder signals_;
};
} // namespace chatterino

View file

@ -1,88 +0,0 @@
#pragma once
#include "util/RapidjsonHelpers.hpp"
#include <QString>
#include <Qt>
#include <cstdint>
namespace chatterino {
struct UploadedImage {
QString channelName;
QString deletionLink;
QString imageLink;
QString localPath;
int64_t timestamp{};
};
} // namespace chatterino
namespace pajlada {
template <>
struct Serialize<chatterino::UploadedImage> {
static rapidjson::Value get(const chatterino::UploadedImage &value,
rapidjson::Document::AllocatorType &a)
{
rapidjson::Value ret(rapidjson::kObjectType);
chatterino::rj::set(ret, "channelName", value.channelName, a);
chatterino::rj::set(ret, "imageLink", value.imageLink, a);
chatterino::rj::set(ret, "timestamp", value.timestamp, a);
chatterino::rj::set(ret, "localPath", value.localPath, a);
chatterino::rj::set(ret, "deletionLink", value.deletionLink, a);
return ret;
}
};
template <>
struct Deserialize<chatterino::UploadedImage> {
static chatterino::UploadedImage get(const rapidjson::Value &value,
bool *error = nullptr)
{
chatterino::UploadedImage img;
if (!value.IsObject())
{
PAJLADA_REPORT_ERROR(error);
return img;
}
if (value["localPath"].IsNull())
{
img.localPath = QString();
}
else if (!chatterino::rj::getSafe(value, "localPath", img.localPath))
{
PAJLADA_REPORT_ERROR(error);
return img;
}
if (!chatterino::rj::getSafe(value, "imageLink", img.imageLink))
{
PAJLADA_REPORT_ERROR(error);
return img;
}
if (value["deletionLink"].IsNull())
{
img.deletionLink = QString();
}
else if (!chatterino::rj::getSafe(value, "deletionLink",
img.deletionLink))
{
PAJLADA_REPORT_ERROR(error);
return img;
}
if (!chatterino::rj::getSafe(value, "channelName", img.channelName))
{
PAJLADA_REPORT_ERROR(error);
return img;
}
if (!chatterino::rj::getSafe(value, "timestamp", img.timestamp))
{
PAJLADA_REPORT_ERROR(error);
return img;
}
return img;
}
};
} // namespace pajlada