ping server

This commit is contained in:
2026-01-03 16:19:26 +01:00
parent 7673bb28fd
commit b41d35744e
2 changed files with 118 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
#include "ApiClient.h"
#include <QCryptographicHash>
#include <QNetworkReply>
#include <QRandomGenerator>
#include <QRegularExpression>
#include <QUrl>
#include <QUrlQuery>
ApiClient::ApiClient(QObject* parent) : QObject(parent) {}
static QString md5Hex(const QByteArray& data) {
return QString(
QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex());
}
// Subsonic/OpenSubsonic Token-Auth: t = md5(password + salt), s = salt
// :contentReference[oaicite:5]{index=5}
QString ApiClient::buildAuthQuery(const QString& user,
const QString& password) const {
const QString salt =
QString::number(QRandomGenerator::global()->generate(), 16);
const QString token = md5Hex((password + salt).toUtf8());
QUrlQuery q;
q.addQueryItem("u", user);
q.addQueryItem("t", token);
q.addQueryItem("s", salt);
q.addQueryItem("v", "1.16.1"); // Navidrome ist kompatibel zu 1.16.1
// :contentReference[oaicite:6]{index=6}
q.addQueryItem("c", "myQtClient");
q.addQueryItem("f", "json");
return q.toString(QUrl::FullyEncoded);
}
void ApiClient::setLastStatus(const QString& s) {
if (m_lastStatus == s) return;
m_lastStatus = s;
emit lastStatusChanged();
}
void ApiClient::ping(const QString& host, const QString& user,
const QString& password) {
if (host.trimmed().isEmpty()) {
emit pingFinished(false, "Host ist leer.");
return;
}
QUrl base(host);
if (!base.isValid()) {
emit pingFinished(false, "Host-URL ist ungültig.");
return;
}
// Sauber zusammensetzen, egal ob host mit/ohne trailing slash kommt
QUrl url(base.toString().remove(QRegularExpression("/+$")) +
"/rest/ping.view");
QUrlQuery q(buildAuthQuery(user, password));
url.setQuery(q);
setLastStatus("Sende Ping…");
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::UserAgentHeader, "navidrome_client/0.1");
QNetworkReply* reply = m_manager.get(req);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
const auto err = reply->error();
const QByteArray body = reply->readAll();
reply->deleteLater();
if (err != QNetworkReply::NoError) {
const QString msg = "Netzwerkfehler: " + reply->errorString();
setLastStatus(msg);
emit pingFinished(false, msg);
return;
}
// Fürs Erste: “kommt was zurück?” reicht. Später kannst du JSON parsen und
// "status":"ok" prüfen.
const QString msg =
"Ping OK, Antwort: " + QString::fromUtf8(body.left(300));
setLastStatus("Ping OK");
emit pingFinished(true, msg);
});
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef APICLIENT_H
#define APICLIENT_H
#include <QNetworkAccessManager>
#include <QObject>
class ApiClient : public QObject {
Q_OBJECT
Q_PROPERTY(QString lastStatus READ lastStatus NOTIFY lastStatusChanged)
public:
explicit ApiClient(QObject* parent = nullptr);
Q_INVOKABLE void ping(const QString& host, const QString& user,
const QString& password);
QString lastStatus() const { return m_lastStatus; }
signals:
void pingFinished(bool ok, QString message);
void lastStatusChanged();
private:
QString buildAuthQuery(const QString& user, const QString& password) const;
void setLastStatus(const QString& s);
QNetworkAccessManager m_manager;
QString m_lastStatus;
};
#endif