Blob Blame History Raw
From 55644fae34ab49834dd52c834c211e765d41f8ab Mon Sep 17 00:00:00 2001
From: Raphael Geissert <atomo64@gmail.com>
Date: Sat, 15 Feb 2014 15:20:26 +0100
Subject: [PATCH 1/3] Update to BBC's new json-based search and modified xml

BUG:330773
---
 .../weather/ions/bbcukmet/ion_bbcukmet.cpp         |   93 ++++++++++++--------
 1 file changed, 54 insertions(+), 39 deletions(-)

diff --git a/plasma/generic/dataengines/weather/ions/bbcukmet/ion_bbcukmet.cpp b/plasma/generic/dataengines/weather/ions/bbcukmet/ion_bbcukmet.cpp
index 746a734..c656e40 100644
--- a/plasma/generic/dataengines/weather/ions/bbcukmet/ion_bbcukmet.cpp
+++ b/plasma/generic/dataengines/weather/ions/bbcukmet/ion_bbcukmet.cpp
@@ -80,6 +80,7 @@ QMap<QString, IonInterface::ConditionIcons> UKMETIon::setupDayIconMappings(void)
     //dayList["sunny intervals night"] = ClearNight;
     dayList["partly cloudy"] = PartlyCloudyDay;
     dayList["cloudy"] = Overcast;
+    dayList["light cloud"] = Overcast;
     dayList["white cloud"] = Overcast;
     dayList["grey cloud"] = Overcast;
     //dayList["low level cloud"] = NotAvailable;
@@ -131,6 +132,7 @@ QMap<QString, IonInterface::ConditionIcons> UKMETIon::setupNightIconMappings(voi
     nightList["sunny intervals"] = PartlyCloudyDay; // it's not really sunny
     nightList["sunny"] = ClearDay;
     nightList["cloudy"] = Overcast;
+    nightList["light cloud"] = Overcast;
     nightList["white cloud"] = Overcast;
     nightList["grey cloud"] = Overcast;
     nightList["partly cloudy"] = PartlyCloudyNight;
@@ -252,7 +254,8 @@ void UKMETIon::getXMLData(const QString& source)
 void UKMETIon::findPlace(const QString& place, const QString& source)
 {
     KUrl url;
-    url = "http://news.bbc.co.uk/weather/util/search/SearchResultsNode.xhtml?&search=" + place + "&region=world&startIndex=0&count=500";
+    /* There's a page= parameter, results are limited to 10 by page */
+    url = "http://www.bbc.com/locator/default/en-GB/search.json?search="+place+"&filter=international&postcode_unit=false&postcode_district=true";
 
     m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
     m_job->addMetaData("cookies", "none"); // Disable displaying cookies
@@ -281,7 +284,7 @@ void UKMETIon::getFiveDayForecast(const QString& source)
     
     int splitIDPos = xmlPath.lastIndexOf('/');
     QString stationID = xmlPath.midRef(splitIDPos + 1).toString();
-    m_place[source].XMLforecastURL = "http://newsrss.bbc.co.uk/weather/forecast/" + stationID + "/Next3DaysRSS.xml" + xmlMap.query();
+    m_place[source].XMLforecastURL = "http://open.live.bbc.co.uk/weather/feeds/en/" + stationID + "/3dayforecast.rss" + xmlMap.query();
     KUrl url(m_place[source].XMLforecastURL);
 
     m_job = KIO::get(url.url(), KIO::Reload, KIO::HideProgressInfo);
@@ -303,47 +306,43 @@ void UKMETIon::readSearchHTMLData(const QString& source, const QByteArray& html)
     QStringList tokens;
     QString url;
     QString tmp;
-    int flag = 0;
     int counter = 2;
 
-    // "<p><a id="result_40" href ="/weather/forecast/4160?count=200">Vitoria, Brazil</a></p>"
-    QRegExp grabURL("/[a-z]+/[a-z]+/([0-9]+)(\\?[^\"]+)?");
-    QRegExp grabPlace(">([^<]*[a-z()])"); // FIXME: It would be better to strip away the extra '>'
+#ifdef __GNUC__
+#warning FIXME: use a json parser instead of regexes
+#endif
+
+    QRegExp grabURL("\"id\":\\s*\"([0-9]+)\"");
+    QRegExp grabPlace("\"fullName\":\\s*\"([^\"]+)\"");
 
     while (!stream.atEnd()) {
        line = stream.readLine();
-       if (line.contains("<p class=\"response\">") > 0) {
-           flag = 1;
-       }
 
-       if (line.contains("There are no forecasts matching") > 0) {
+       if (line.contains("Sorry, no results found for") > 0) {
            break;
        }
 
-       if (flag) {
+       if (line.contains("\"results\"") > 0) {
 
             if (grabURL.indexIn(line.trimmed()) > 0) {
-                url = "http://newsrss.bbc.co.uk/weather/forecast/" + grabURL.cap(1) + "/ObservationsRSS.xml";
-                if (grabURL.captureCount() > 1) {
-                    url += grabURL.cap(2);
-                }
-                grabPlace.indexIn(line.trimmed());
-                tmp = QString("bbcukmet|").append(grabPlace.cap(1));
 
-                // Duplicate places can exist
-                if (m_locations.contains(tmp)) {
-                    tmp = QString("bbcukmet|").append(QString("%1 (#%2)").arg(grabPlace.cap(1)).arg(counter));
-                    counter++;
-                }
+                for (int captureIndex = 1; captureIndex <= grabURL.captureCount(); captureIndex++) {
 
-                m_place[tmp].XMLurl = url;
-                m_place[tmp].place = grabPlace.cap(1);
-                m_locations.append(tmp);
-            }
-       }
+                    url = "http://open.live.bbc.co.uk/weather/feeds/en/" + grabURL.cap(captureIndex) + "/observations.rss";
+                    grabPlace.indexIn(line.trimmed());
+                    tmp = QString("bbcukmet|").append(grabPlace.cap(captureIndex));
+
+                    // Duplicate places can exist
+                    if (m_locations.contains(tmp)) {
+                        tmp = QString("bbcukmet|").append(QString("%1 (#%2)").arg(grabPlace.cap(captureIndex)).arg(counter));
+                        counter++;
+                    }
 
-       if (line.contains("<div class=\"line\">") > 0) {
-           flag = 0;
+                    m_place[tmp].XMLurl = url;
+                    m_place[tmp].place = grabPlace.cap(captureIndex);
+                    m_locations.append(tmp);
+                }
+            }
        }
     }
 
@@ -557,12 +556,13 @@ void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data,
                 QStringRef conditionData = conditionString.midRef(splitIndex + 1); // Include ':'
                 data.obsTime = conditionString.midRef(0, splitIndex).toString();
 
-                // Friday at 0200 GMT
-                m_dateFormat =  QDateTime::fromString(data.obsTime.split("at")[1].trimmed(), "hhmm 'GMT'");
+                // Saturday - 13:00 CET
+                // Saturday - 12:00 GMT
+                m_dateFormat = QDateTime::fromString(data.obsTime.split("-")[1].trimmed(), "hh:mm 'GMT'");
                 data.iconPeriodHour = m_dateFormat.toString("hh").toInt();
                 data.iconPeriodMinute = m_dateFormat.toString("mm").toInt();
 
-                data.condition = conditionData.toString().split('.')[0].trimmed();
+                data.condition = conditionData.toString().split(',')[0].trimmed();
 
             } else if (xml.name() == "link") {
                 m_place[source].forecastHTMLUrl = xml.readElementText();
@@ -575,21 +575,32 @@ void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data,
 #endif
 
                 data.temperature_C = observeData[1].split(QChar(176))[0].trimmed();
-
-                // Temperature might be not available
-                if (data.temperature_C.contains("N/A")) {
+                if (data.temperature_C.contains("N/A") || data.temperature_C.contains("null")) {
                     data.temperature_C = i18n("N/A");
                 }
 
                 data.windDirection = observeData[2].split(',')[0].trimmed();
+		if (data.windDirection.contains("null")) {
+		    data.windDirection = "";
+		}
+
                 data.windSpeed_miles = observeData[3].split(',')[0].split(' ')[1].remove("mph");
+		if (data.windSpeed_miles.contains("null")) {
+		    data.windSpeed_miles = "N/A";
+		}
 
                 data.humidity = observeData[4].split(',')[0].split(' ')[1];
                 if (data.humidity.endsWith('%')) {
                     data.humidity.chop(1);
                 }
+		if (data.humidity.contains("null")) {
+		    data.humidity = "N/A";
+		}
 
                 data.pressure = observeData[5].split(',')[0].split(' ')[1].split("mb")[0];
+		if (data.pressure.contains("null")) {
+		    data.pressure = "N/A";
+		}
                 data.pressureTendency = observeData[5].split(',')[1].trimmed();
 
                 data.visibilityStr = observeData[6].trimmed();
@@ -600,6 +611,10 @@ void UKMETIon::parseWeatherObservation(const QString& source, WeatherData& data,
             } else if (xml.name() == "long") {
                 const QString ordinate = xml.readElementText();
                 data.longitude = ordinate.toDouble();
+            } else if (xml.name() == "georss:point") {
+                const QString ordinates = xml.readElementText();
+                data.latitude = ordinates.split(' ')[0].toDouble();
+                data.longitude = ordinates.split(' ')[1].toDouble();
             } else {
                 parseUnknownElement(xml);
             }
@@ -675,8 +690,8 @@ void UKMETIon::parseFiveDayForecast(const QString& source, QXmlStreamReader& xml
     QString line;
     QString period;
     QString summary;
-    QRegExp high("-?\\d+");
-    QRegExp low("-?\\d+");
+    QRegExp high("-?\\d+.C");
+    QRegExp low("-?\\d+.C");
     while (!xml.atEnd()) {
         xml.readNext();
         if (xml.name() == "title") {
@@ -687,8 +702,8 @@ void UKMETIon::parseFiveDayForecast(const QString& source, QXmlStreamReader& xml
 
             period = line.split(',')[0].split(':')[0];
             summary = line.split(',')[0].split(':')[1].trimmed();
-            high.indexIn(line.split(',')[1]);
-            low.indexIn(line.split(',')[2]);
+            high.indexIn(line.split(',')[1].split(':')[1]);
+            low.indexIn(line.split(',')[1].split(':')[2]);
 
             forecast->period = period;
             forecast->iconName = getWeatherIcon(dayIcons(), summary.toLower());
-- 
1.7.10