File indexing completed on 2024-05-12 04:42:39

0001 /*
0002     SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "oebbbackend.h"
0008 #include "oebbvehiclelayoutparser.h"
0009 #include "cache.h"
0010 #include "uic/uicstationcode.h"
0011 
0012 #include <KPublicTransport/Stopover>
0013 #include <KPublicTransport/VehicleLayoutReply>
0014 #include <KPublicTransport/VehicleLayoutRequest>
0015 
0016 #include <QNetworkReply>
0017 #include <QNetworkRequest>
0018 #include <QRegularExpression>
0019 #include <QUrl>
0020 #include <QUrlQuery>
0021 
0022 using namespace KPublicTransport;
0023 
0024 static QString trainNumber(const Route &route)
0025 {
0026     if (!route.name().isEmpty()) {
0027         static QRegularExpression regex(QStringLiteral("[A-Z]*\\s*(\\d+)"));
0028         const auto match = regex.match(route.name());
0029         if (match.hasMatch()) {
0030             return match.captured(1);
0031         }
0032     }
0033 
0034     const auto line = route.line();
0035     static QRegularExpression regex(QStringLiteral("(?:ICE|IC|EC|RJ|RJX|NJ|CAT|D)\\s*(\\d+)"));
0036     const auto match = regex.match(line.modeString() + line.name());
0037     if (match.hasMatch()) {
0038         return match.captured(1);
0039     }
0040     return {};
0041 }
0042 
0043 bool OebbBackend::queryVehicleLayout(const VehicleLayoutRequest &request, VehicleLayoutReply *reply, QNetworkAccessManager *nam) const
0044 {
0045     const auto ibnr = request.stopover().stopPoint().identifier(QStringLiteral("ibnr"));
0046     if (!UicStationCode::isValid(ibnr)) {
0047         return false;
0048     }
0049     const auto trainNum = trainNumber(request.stopover().route());
0050     if (trainNum.isEmpty()) {
0051         return false;
0052     }
0053     const auto dt = request.stopover().scheduledDepartureTime().isValid() ? request.stopover().scheduledDepartureTime() : request.stopover().scheduledArrivalTime();
0054 
0055     QUrl url;
0056     url.setScheme(QStringLiteral("https"));
0057     url.setHost(QStringLiteral("live.oebb.at"));
0058     url.setPath(QLatin1String("/backend/info"));
0059     QUrlQuery query;
0060     query.addQueryItem(QStringLiteral("trainNr"), trainNum);
0061     query.addQueryItem(QStringLiteral("station"), ibnr);
0062     query.addQueryItem(QStringLiteral("date"), dt.toString(QStringLiteral("yyyy-MM-dd")));
0063     url.setQuery(query);
0064 
0065     QNetworkRequest netReq(url);
0066     logRequest(request, netReq);
0067     auto netReply = nam->get(netReq);
0068     netReply->setParent(reply);
0069 
0070     QObject::connect(netReply, &QNetworkReply::finished, reply, [this, reply, netReply] {
0071         const auto data = netReply->readAll();
0072         logReply(reply, netReply, data);
0073 
0074         if (netReply->error() == QNetworkReply::NoError) {
0075             OebbVehicleLayoutParser p;
0076             if (p.parse(data)) {
0077                 Cache::addVehicleLayoutCacheEntry(backendId(), reply->request().cacheKey(), p.stopover, {}, std::chrono::minutes(2));
0078                 addResult(reply, p.stopover);
0079             } else {
0080                 addError(reply, Reply::UnknownError, {});
0081             }
0082         } else if (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 404) {
0083             Cache::addNegativeVehicleLayoutCacheEntry(backendId(), reply->request().cacheKey());
0084             addError(reply, Reply::NotFoundError, reply->errorString());
0085         } else {
0086             addError(reply, Reply::NetworkError, reply->errorString());
0087         }
0088         netReply->deleteLater();
0089     });
0090 
0091     return true;
0092 }