146 lines
5.8 KiB
C++
146 lines
5.8 KiB
C++
// For license of this file, see <project-root-folder>/LICENSE.md.
|
|
|
|
#include "network-web/readability.h"
|
|
|
|
#include "3rd-party/boolinq/boolinq.h"
|
|
#include "exceptions/applicationexception.h"
|
|
#include "miscellaneous/application.h"
|
|
|
|
#include <QDir>
|
|
|
|
#define READABILITY_PACKAGE "@mozilla/readability"
|
|
#define READABILITY_VERSION "0.5.0"
|
|
|
|
#define JSDOM_PACKAGE "jsdom"
|
|
#define JSDOM_VERSION "24.0.0"
|
|
|
|
Readability::Readability(QObject* parent) : QObject{parent}, m_modulesInstalling(false), m_modulesInstalled(false) {
|
|
connect(qApp->nodejs(), &NodeJs::packageInstalledUpdated, this, &Readability::onPackageReady);
|
|
connect(qApp->nodejs(), &NodeJs::packageError, this, &Readability::onPackageError);
|
|
}
|
|
|
|
void Readability::onPackageReady(const QObject* sndr,
|
|
const QList<NodeJs::PackageMetadata>& pkgs,
|
|
bool already_up_to_date) {
|
|
Q_UNUSED(already_up_to_date)
|
|
|
|
bool concerns_readability = boolinq::from(pkgs).any([](const NodeJs::PackageMetadata& pkg) {
|
|
return pkg.m_name == QSL(READABILITY_PACKAGE);
|
|
});
|
|
|
|
if (!concerns_readability) {
|
|
return;
|
|
}
|
|
|
|
m_modulesInstalled = true;
|
|
m_modulesInstalling = false;
|
|
|
|
qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
|
|
{tr("Packages for reader mode are installed"),
|
|
tr("Reload your webpage and then you can use reader mode!"),
|
|
QSystemTrayIcon::MessageIcon::Information},
|
|
{true, true, false});
|
|
|
|
// Emit this just to allow readability again for user.
|
|
emit errorOnHtmlReadabiliting(sndr, tr("Packages for reader mode are installed. You can now use reader mode!"));
|
|
}
|
|
|
|
void Readability::onPackageError(const QObject* sndr,
|
|
const QList<NodeJs::PackageMetadata>& pkgs,
|
|
const QString& error) {
|
|
bool concerns_readability = boolinq::from(pkgs).any([](const NodeJs::PackageMetadata& pkg) {
|
|
return pkg.m_name == QSL(READABILITY_PACKAGE);
|
|
});
|
|
|
|
if (!concerns_readability) {
|
|
return;
|
|
}
|
|
|
|
m_modulesInstalled = m_modulesInstalling = false;
|
|
|
|
qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
|
|
{tr("Packages for reader mode are NOT installed"),
|
|
tr("There is error: %1").arg(error),
|
|
QSystemTrayIcon::MessageIcon::Critical},
|
|
{true, true, false});
|
|
|
|
// Emit this just to allow readability again for user.
|
|
emit errorOnHtmlReadabiliting(sndr, tr("Packages for reader mode are NOT installed. There is error: %1").arg(error));
|
|
}
|
|
|
|
void Readability::makeHtmlReadable(QObject* sndr, const QString& html, const QString& base_url) {
|
|
if (!m_modulesInstalled) {
|
|
try {
|
|
NodeJs::PackageStatus st_readability =
|
|
qApp->nodejs()->packageStatus({QSL(READABILITY_PACKAGE), QSL(READABILITY_VERSION)});
|
|
NodeJs::PackageStatus st_jsdom = qApp->nodejs()->packageStatus({QSL(JSDOM_PACKAGE), QSL(JSDOM_VERSION)});
|
|
|
|
if (st_readability != NodeJs::PackageStatus::UpToDate || st_jsdom != NodeJs::PackageStatus::UpToDate) {
|
|
if (!m_modulesInstalling) {
|
|
// We make sure to update modules.
|
|
m_modulesInstalling = true;
|
|
qApp->nodejs()->installUpdatePackages(sndr,
|
|
{{QSL(READABILITY_PACKAGE), QSL(READABILITY_VERSION)},
|
|
{QSL(JSDOM_PACKAGE), QSL(JSDOM_VERSION)}});
|
|
}
|
|
|
|
return;
|
|
}
|
|
else {
|
|
m_modulesInstalled = true;
|
|
}
|
|
}
|
|
catch (const ApplicationException& ex) {
|
|
qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
|
|
{tr("Node.js libraries not installed"),
|
|
tr("Node.js is not configured properly. Go to \"Settings\" -> \"Node.js\" and check "
|
|
"if your Node.js is properly configured."),
|
|
QSystemTrayIcon::MessageIcon::Critical},
|
|
{true, true, false});
|
|
|
|
qCriticalNN << LOGSEC_CORE << "Failed to check for Node.js package status:" << QUOTE_W_SPACE_DOT(ex.message());
|
|
|
|
// Emit this just to allow readability again for user.
|
|
emit
|
|
errorOnHtmlReadabiliting(sndr,
|
|
tr("Node.js is not configured properly. Go to \"Settings\" -> \"Node.js\" and check "
|
|
"if your Node.js is properly configured."));
|
|
}
|
|
}
|
|
|
|
QString temp_script =
|
|
QDir::toNativeSeparators(IOFactory::getSystemFolder(QStandardPaths::StandardLocation::TempLocation)) +
|
|
QDir::separator() + QSL("readabilize-article.js");
|
|
|
|
if (!IOFactory::copyFile(QSL(":/scripts/readability/readabilize-article.js"), temp_script)) {
|
|
qWarningNN << LOGSEC_ADBLOCK << "Failed to copy Readability script to TEMP.";
|
|
}
|
|
|
|
QProcess* proc = new QProcess(this);
|
|
|
|
connect(proc,
|
|
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this,
|
|
[=](int exit_code, QProcess::ExitStatus exit_status) {
|
|
onReadabilityFinished(sndr, exit_code, exit_status);
|
|
});
|
|
|
|
qApp->nodejs()->runScript(proc, temp_script, {base_url});
|
|
|
|
proc->write(html.toUtf8());
|
|
proc->closeWriteChannel();
|
|
}
|
|
|
|
void Readability::onReadabilityFinished(QObject* sndr, int exit_code, QProcess::ExitStatus exit_status) {
|
|
QProcess* proc = qobject_cast<QProcess*>(sender());
|
|
|
|
if (exit_status == QProcess::ExitStatus::NormalExit && exit_code == EXIT_SUCCESS) {
|
|
emit htmlReadabled(sndr, QString::fromUtf8(proc->readAllStandardOutput()));
|
|
}
|
|
else {
|
|
QString err = QString::fromUtf8(proc->readAllStandardError());
|
|
emit errorOnHtmlReadabiliting(sndr, err);
|
|
}
|
|
|
|
proc->deleteLater();
|
|
}
|