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 }