2021-03-05 14:34:10 +00:00
|
|
|
#ifndef JELLYFIN_SUPPORT_LOADER_H
|
|
|
|
#define JELLYFIN_SUPPORT_LOADER_H
|
|
|
|
|
|
|
|
#include <exception>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
#include <QJsonDocument>
|
|
|
|
#include <QUrlQuery>
|
|
|
|
#include <QString>
|
|
|
|
|
|
|
|
#include <JellyfinQt/apiclient.h>
|
|
|
|
|
|
|
|
namespace Jellfyin {
|
|
|
|
namespace Support {
|
|
|
|
|
|
|
|
|
|
|
|
class LoadException : public std::runtime_error {
|
|
|
|
public:
|
|
|
|
explicit LoadException(const char *message)
|
|
|
|
: std::runtime_error(message) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int HTTP_TIMEOUT = 30000; // 30 seconds;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface describing a way to load items. Used to abstract away
|
|
|
|
* the difference between loading from a cache or loading over the network.
|
|
|
|
*
|
|
|
|
* @tparam R the type of data that should be fetched, R for result.
|
|
|
|
* @tparam P the type of paramaters given, to determine which resource should
|
|
|
|
* be loaded.
|
|
|
|
*/
|
|
|
|
template <typename R, typename P>
|
|
|
|
class Loader {
|
|
|
|
public:
|
2021-03-20 02:30:50 +00:00
|
|
|
explicit Loader(Jellyfin::ApiClient *apiClient)
|
|
|
|
: m_apiClient(apiClient) {}
|
2021-03-05 14:34:10 +00:00
|
|
|
/**
|
|
|
|
* @brief load Loads the given resource.
|
|
|
|
* @param parameters Parameters to determine which resource should be loaded.
|
|
|
|
* @return The resource if successfull.
|
|
|
|
*/
|
|
|
|
virtual R load(const P ¶meters) const;
|
|
|
|
/**
|
|
|
|
* @brief Heuristic to determine if this resource can be loaded via this loaded.
|
|
|
|
*
|
|
|
|
* For example, a Loader that requires the network to be available should return false
|
|
|
|
* if the network is not available.
|
|
|
|
* @return True if this loader is available, false otherwise.
|
|
|
|
*/
|
|
|
|
virtual bool isAvailable() const;
|
|
|
|
protected:
|
2021-03-20 02:30:50 +00:00
|
|
|
Jellyfin::ApiClient *m_apiClient;
|
2021-03-05 14:34:10 +00:00
|
|
|
};
|
|
|
|
|
2021-03-20 02:30:50 +00:00
|
|
|
/**
|
|
|
|
* Implementation of Loader that loads Items over HTTP
|
|
|
|
*/
|
2021-03-05 14:34:10 +00:00
|
|
|
template <typename R, typename P>
|
|
|
|
class HttpLoader : public Loader<R, P> {
|
|
|
|
public:
|
2021-03-20 02:30:50 +00:00
|
|
|
explicit HttpLoader(Jellyfin::ApiClient *apiClient)
|
|
|
|
: Loader<R, P> (apiClient) {}
|
|
|
|
|
|
|
|
virtual R load(const P ¶meters) const override {
|
|
|
|
QNetworkReply *reply = this->m_apiClient->get(url(parameters), query(parameters));
|
2021-03-05 14:34:10 +00:00
|
|
|
QByteArray array;
|
|
|
|
while (!reply->atEnd()) {
|
|
|
|
if (!reply->waitForReadyRead(HTTP_TIMEOUT)) {
|
|
|
|
if (reply->error() == QNetworkReply::NoError) {
|
|
|
|
reply->deleteLater();
|
|
|
|
throw LoadException("HTTP timeout");
|
|
|
|
}
|
|
|
|
reply->deleteLater();
|
|
|
|
throw LoadException("HTTP error");
|
|
|
|
}
|
|
|
|
array.append(reply->readAll());
|
|
|
|
}
|
|
|
|
reply->deleteLater();
|
|
|
|
QJsonParseError error;
|
|
|
|
QJsonDocument document = QJsonDocument::fromJson(array, &error);
|
|
|
|
if (error.error != QJsonParseError::NoError) {
|
|
|
|
throw LoadException(error.errorString().toLocal8Bit().constData());
|
|
|
|
}
|
|
|
|
return parse(document);
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual const QString url(const P ¶meters) const;
|
|
|
|
virtual const QUrlQuery query(const P ¶meters) const;
|
|
|
|
virtual R parse(const QJsonObject &object) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // NS Support
|
|
|
|
} // NS Jellyfin
|
|
|
|
|
|
|
|
#endif // JELLYFIN_SUPPORT_LOADER_H
|