fix broken ovh bill urls
now with much more pain, you can login manually and we will hijack that session to download the bills. huge yay to OVH for a great idea
This commit is contained in:
parent
53ed1462b1
commit
eb62fd694f
|
@ -26,6 +26,9 @@ set(PROJECT_SOURCES
|
|||
dedicatedserverinfowidget.cpp
|
||||
dedicatedserverinfowidget.h
|
||||
dedicatedserverinfowidget.ui
|
||||
ovhwebauthentication.h
|
||||
ovhwebauthentication.cpp
|
||||
ovhwebauthentication.ui
|
||||
ovhapi.cpp
|
||||
ovhapi.h
|
||||
resources.qrc
|
||||
|
|
|
@ -200,82 +200,110 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="141"/>
|
||||
<location filename="mainwindow.cpp" line="142"/>
|
||||
<source>Validate credential</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="141"/>
|
||||
<location filename="mainwindow.cpp" line="142"/>
|
||||
<source>Have you validated the OVH credential request?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="183"/>
|
||||
<location filename="mainwindow.cpp" line="184"/>
|
||||
<source>Info %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="198"/>
|
||||
<location filename="mainwindow.cpp" line="199"/>
|
||||
<source>IPMI not activated</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="198"/>
|
||||
<location filename="mainwindow.cpp" line="199"/>
|
||||
<source>IPMI is not activated on this server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="207"/>
|
||||
<location filename="mainwindow.cpp" line="208"/>
|
||||
<source>IPMI KVM not available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="207"/>
|
||||
<location filename="mainwindow.cpp" line="208"/>
|
||||
<source>IPMI KVM is not available on this server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="231"/>
|
||||
<location filename="mainwindow.cpp" line="232"/>
|
||||
<source>Waiting for task... %1</source>
|
||||
<oldsource>Waiting for task...</oldsource>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="251"/>
|
||||
<location filename="mainwindow.cpp" line="252"/>
|
||||
<source>KVM %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="260"/>
|
||||
<location filename="mainwindow.cpp" line="262"/>
|
||||
<location filename="mainwindow.cpp" line="261"/>
|
||||
<location filename="mainwindow.cpp" line="263"/>
|
||||
<source>JNLP KVM</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="260"/>
|
||||
<location filename="mainwindow.cpp" line="261"/>
|
||||
<source>This server only supports a Java WebStart KVM, it will thus not be embedded in this window.
|
||||
Java WebStart should be starting right now, wait until it finishes loading to close this dialog.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="262"/>
|
||||
<location filename="mainwindow.cpp" line="263"/>
|
||||
<source>Failed to launch javaws. Make sure it is properly installed.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="361"/>
|
||||
<location filename="mainwindow.cpp" line="362"/>
|
||||
<source>Target archive</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="370"/>
|
||||
<location filename="mainwindow.cpp" line="362"/>
|
||||
<source>Zip files (*.zip)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="366"/>
|
||||
<source>OVH...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="366"/>
|
||||
<source>OVH decided that getting a bill require a 'true' login. I'm going to show you a web browser for that.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="377"/>
|
||||
<source>Failed to open archive</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="mainwindow.cpp" line="370"/>
|
||||
<location filename="mainwindow.cpp" line="377"/>
|
||||
<source>Failed to open archive...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OvhWebAuthentication</name>
|
||||
<message>
|
||||
<location filename="ovhwebauthentication.ui" line="14"/>
|
||||
<source>OVH Web authentication</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="ovhwebauthentication.ui" line="29"/>
|
||||
<source>Please login on OVH website...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <KArchive>
|
||||
#include <KZip>
|
||||
#include "dedicatedserverinfowidget.h"
|
||||
#include "ovhwebauthentication.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
@ -358,10 +359,16 @@ QCoro::Task<> MainWindow::on_actionGraphPerMonth_triggered()
|
|||
QCoro::Task<> MainWindow::on_actionBillsOfLastMonth_triggered()
|
||||
{
|
||||
// todo filters
|
||||
auto fileName = QFileDialog::getSaveFileName(this, tr("Target archive"), QString());
|
||||
auto fileName = QFileDialog::getSaveFileName(this, tr("Target archive"), QString(), tr("Zip files (*.zip)"));
|
||||
if (fileName.isEmpty())
|
||||
co_return;
|
||||
|
||||
QMessageBox::information(this, tr("OVH..."), tr("OVH decided that getting a bill require a 'true' login. I'm going to show you a web browser for that."));
|
||||
auto ovhAuth = new OvhWebAuthentication(this);
|
||||
if (ovhAuth->exec() != QDialog::Accepted) {
|
||||
qDebug() << "Rejected login, ok, bye bye";
|
||||
co_return;
|
||||
}
|
||||
|
||||
auto start = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
|
@ -383,8 +390,6 @@ QCoro::Task<> MainWindow::on_actionBillsOfLastMonth_triggered()
|
|||
|
||||
QString path = QString("/me/bill?date.to=%1&date.from=%2").arg(firstDayOfMonth.toString(Qt::ISODate))
|
||||
.arg(oneMonthAgo.toString(Qt::ISODate));
|
||||
double totalCost = 0;
|
||||
QString currency;
|
||||
auto billList = (co_await api->get(path, ten_years)).array();
|
||||
|
||||
// Ok, we can set the progress based on that list
|
||||
|
@ -400,14 +405,13 @@ QCoro::Task<> MainWindow::on_actionBillsOfLastMonth_triggered()
|
|||
auto billTime = QDateTime::fromString(billInfo["date"].toString(), Qt::ISODate);
|
||||
|
||||
qDebug() << "Downloading bill at " << billPdfUrl;
|
||||
QByteArray pdfData = co_await api->download(QUrl{billPdfUrl});
|
||||
QByteArray pdfData = co_await ovhAuth->download(QUrl{billPdfUrl});
|
||||
targetArchive.writeFile(QString("%1.pdf").arg(billId), pdfData, 0100644, QString(), QString(), billTime, billTime, billTime);
|
||||
|
||||
// update progress dialog...
|
||||
progressDialog->setValue(progressDialog->value() + 1);
|
||||
}
|
||||
|
||||
|
||||
targetArchive.close();
|
||||
|
||||
progressDialog->close();
|
||||
|
@ -416,7 +420,7 @@ QCoro::Task<> MainWindow::on_actionBillsOfLastMonth_triggered()
|
|||
auto end = QDateTime::currentMSecsSinceEpoch();
|
||||
qDebug() << "Took ..." << end - start;
|
||||
|
||||
ovhAuth->deleteLater();
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(fileName));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#include "ovhwebauthentication.h"
|
||||
#include "ui_ovhwebauthentication.h"
|
||||
#include <QTemporaryFile>
|
||||
#include <QWebEngineProfile>
|
||||
#include <QCoroSignal>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
OvhWebAuthentication::OvhWebAuthentication(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::OvhWebAuthentication)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// Ok, why this fake url ? because OVH limited the target urls, but did not document it in any way...
|
||||
ui->webView->setUrl(QUrl{"https://www.ovh.com/auth/?onsuccess=https%3A%2F%2Fwww.ovh.com%2Ffake_url"});
|
||||
connect(ui->webView, &QWebEngineView::urlChanged, [this](const QUrl &url) {
|
||||
qDebug() << "Started loading url " << url;
|
||||
if (url == QUrl("https://www.ovh.com/fake_url")) {
|
||||
// SUCCESS !!!!
|
||||
ui->webView->setUrl(QUrl{"about:blank"});
|
||||
ui->webView->setHtml("<html><body><h1>SUCCESS !</h1></body></html>");
|
||||
emit accept();
|
||||
}
|
||||
});
|
||||
connect(ui->webView, &QWebEngineView::loadStarted, [this]() {
|
||||
qDebug() << "Started loading";
|
||||
});
|
||||
connect(ui->webView, &QWebEngineView::loadFinished, [this]() {
|
||||
qDebug() << "Finished loading";
|
||||
});
|
||||
}
|
||||
|
||||
OvhWebAuthentication::~OvhWebAuthentication()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QCoro::Task<QByteArray> OvhWebAuthentication::download(const QUrl &url)
|
||||
{
|
||||
QTemporaryFile tempFile;
|
||||
if (tempFile.open()) {
|
||||
ui->webView->page()->download(url, tempFile.fileName());
|
||||
tempFile.close();
|
||||
auto webProfile = ui->webView->page()->profile();
|
||||
auto dlConn = connect(webProfile, &QWebEngineProfile::downloadRequested, this, [this](QWebEngineDownloadItem *download) {
|
||||
qDebug() << "Accepting download";
|
||||
download->accept();
|
||||
QObject::connect(download, &QWebEngineDownloadItem::finished, this, [this, download]() {
|
||||
qDebug() << "Download finished" << download->downloadFileName();
|
||||
QDir dlDir{download->downloadDirectory()};
|
||||
emit webEngineDownloadFinished(dlDir.absoluteFilePath(download->downloadFileName()));
|
||||
});
|
||||
});
|
||||
|
||||
const QString dlFileName = co_await qCoro(this, &OvhWebAuthentication::webEngineDownloadFinished);
|
||||
qDebug() << "Ok, download finished, understood.";
|
||||
disconnect(dlConn);
|
||||
QFile dataFile(dlFileName);
|
||||
dataFile.open(QIODevice::ReadOnly);
|
||||
QByteArray data = dataFile.readAll();
|
||||
dataFile.remove();
|
||||
co_return data;
|
||||
}
|
||||
co_return "";
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef OVHWEBAUTHENTICATION_H
|
||||
#define OVHWEBAUTHENTICATION_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QCoroTask>
|
||||
|
||||
namespace Ui {
|
||||
class OvhWebAuthentication;
|
||||
}
|
||||
|
||||
class OvhWebAuthentication : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OvhWebAuthentication(QWidget *parent = nullptr);
|
||||
~OvhWebAuthentication();
|
||||
|
||||
QCoro::Task<QByteArray> download(const QUrl &url);
|
||||
|
||||
signals:
|
||||
void authenticated();
|
||||
void webEngineDownloadFinished(const QString &dlFileName);
|
||||
|
||||
private:
|
||||
Ui::OvhWebAuthentication *ui;
|
||||
};
|
||||
|
||||
#endif // OVHWEBAUTHENTICATION_H
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OvhWebAuthentication</class>
|
||||
<widget class="QDialog" name="OvhWebAuthentication">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>OVH Web authentication</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QWebEngineView" name="webView" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Please login on OVH website...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QWebEngineView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">qwebengineview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue