Skip to content

Commit

Permalink
Trackernet on TfL Cloud decommissioned (#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
TWiStErRob authored Nov 1, 2024
1 parent 46ce4f9 commit efbd5a0
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 92 deletions.
7 changes: 4 additions & 3 deletions .idea/runConfigurations/Run_status_history_server.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ public class DownloadFeedTask<T extends BaseFeed<T>> extends android.os.AsyncTas
protected final Logger LOG = LoggerFactory.getLogger(getClass());

private Map<String, ?> m_args;

public DownloadFeedTask() {
this(null);
}

public DownloadFeedTask(Map<String, ?> args) {
m_args = args != null? args : Collections.<String, Object>emptyMap();
}
Expand All @@ -46,7 +48,12 @@ public DownloadFeedTask(Map<String, ?> args) {
connection.setConnectTimeout(1000);
connection.setReadTimeout(2000);
connection.connect();
input = connection.getInputStream();
try {
input = connection.getInputStream();
} catch (IOException ex) {
String message = IOTools.readAll(connection.getErrorStream());
throw new IOException("Failed to download feed: " + url + "\n" + message, ex);
}

T root = feed.<T>getHandler().parse(input);
return new AsyncTaskResult<>(root);
Expand Down
3 changes: 2 additions & 1 deletion common/feed/feeds/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id("net.twisterrob.blt.convention")
id("org.gradle.java-library")
id("net.twisterrob.gradle.plugin.java")
id("net.twisterrob.gradle.plugin.kotlin")
id("com.android.lint")
}

Expand All @@ -11,4 +11,5 @@ dependencies {
implementation(projects.common.feed.trackernet)
implementation(projects.common.feed.timetable)
implementation(libs.jsr305)
implementation(libs.ktor.http)
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,18 @@ public enum Feed {
* <a href="http://web.archive.org/web/20110615000000&#42;/http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html">The Wayback Machine</a><br>
*/
TubeDepartureBoardsPredictionSummary(30 * SECOND, 30 * SECOND, 30 * SECOND, PredictionSummaryFeedHandler.class,
"http://cloud.tfl.gov.uk/TrackerNet/PredictionSummary/V",
"http://cloud.tfl.gov.uk/TrackerNet/PredictionSummary/"),
"https://api-preprod.tfl.gov.uk/TrackerNet/PredictionSummary/V?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/PredictionSummary/?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),
/**
* <h3>Tube departure boards, station details</h3><br>
* <b>Details</b>: <a href="http://www.tfl.gov.uk/businessandpartners/syndication/16493.aspx#17615">link</a><br>
* <b>Spec</b>: <a href="http://www.tfl.gov.uk/assets/downloads/businessandpartners/Trackernet_Data_Services_Guide_Beta_0_2.pdf">link</a> @ 3.2<br>
*/
TubeDepartureBoardsPredictionDetailed(30 * SECOND, 30 * SECOND, 30 * SECOND, PredictionDetailedFeedHandler.class,
"http://cloud.tfl.gov.uk/TrackerNet/PredictionDetailed/C/BNK",
"http://cloud.tfl.gov.uk/TrackerNet/PredictionDetailed/"),
"https://api-preprod.tfl.gov.uk/TrackerNet/PredictionDetailed/C/BNK?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/PredictionDetailed/?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),

/**
* <h3>Tube departure boards, line and station status</h3><br>
Expand All @@ -123,7 +125,9 @@ public enum Feed {
* <b>Spec</b>: <a href="http://www.tfl.gov.uk/assets/downloads/businessandpartners/tube-status-presentation-user-guide.pdf">link</a><br>
*/
TubeDepartureBoardsStationStatus(30 * SECOND, 30 * SECOND, 30 * SECOND, MISSING_HANDLER,
"http://cloud.tfl.gov.uk/TrackerNet/StationStatus", "http://cloud.tfl.gov.uk/TrackerNet/StationStatus"),
"https://api-preprod.tfl.gov.uk/TrackerNet/StationStatus?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/StationStatus?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),
/**
* <h3>Tube departure boards, line and station status</h3><br>
* <b>Details</b>: <a href="http://www.tfl.gov.uk/businessandpartners/syndication/16493.aspx#17615">link</a><br>
Expand All @@ -133,8 +137,9 @@ public enum Feed {
* <a href="http://web.archive.org/web/20110615000000&#42;/http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html">The Wayback Machine</a><br>
*/
TubeDepartureBoardsStationStatusIncidents(30 * SECOND, 30 * SECOND, 30 * SECOND, MISSING_HANDLER,
"http://cloud.tfl.gov.uk/TrackerNet/StationStatus/IncidentsOnly",
"http://cloud.tfl.gov.uk/TrackerNet/StationStatus/IncidentsOnly"),
"https://api-preprod.tfl.gov.uk/TrackerNet/StationStatus/IncidentsOnly?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/StationStatus/IncidentsOnly?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),

/**
* <h3>Tube departure boards, line and station status</h3><br>
Expand All @@ -143,7 +148,9 @@ public enum Feed {
* <b>Spec</b>: <a href="http://www.tfl.gov.uk/assets/downloads/businessandpartners/tube-status-presentation-user-guide.pdf">link</a> @ 3.4<br>
*/
TubeDepartureBoardsLineStatus(30 * SECOND, 30 * SECOND, 30 * SECOND, LineStatusFeedHandler.class,
"http://cloud.tfl.gov.uk/TrackerNet/LineStatus", "http://cloud.tfl.gov.uk/TrackerNet/LineStatus"),
"https://api-preprod.tfl.gov.uk/TrackerNet/LineStatus?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/LineStatus?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),
/**
* <h3>Tube departure boards, line and station status</h3><br>
* <b>Details</b>: <a href="http://www.tfl.gov.uk/businessandpartners/syndication/16493.aspx#17615">link</a><br>
Expand All @@ -153,8 +160,9 @@ public enum Feed {
* <a href="http://web.archive.org/web/20110615000000&#42;/http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html">The Wayback Machine</a><br>
*/
TubeDepartureBoardsLineStatusIncidents(30 * SECOND, 30 * SECOND, 30 * SECOND, LineStatusFeedHandler.class,
"http://cloud.tfl.gov.uk/TrackerNet/LineStatus/IncidentsOnly",
"http://cloud.tfl.gov.uk/TrackerNet/LineStatus/IncidentsOnly"),
"https://api-preprod.tfl.gov.uk/TrackerNet/LineStatus/IncidentsOnly?app_key=b6ccc4e6531f495b8d295316a8a1469b",
"https://api.tfl.gov.uk/TrackerNet/LineStatus/IncidentsOnly?app_key=e9e6e2143d6e471b90a9f964d69856fd"
),
/**
* <h3>Barclays Cycle Hire statistics</h3><br>
* <b>Details</b>: <a href="http://www.tfl.gov.uk/businessandpartners/syndication/16493.aspx#17855">link</a><br>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package net.twisterrob.blt.io.feeds

import io.ktor.http.URLBuilder
import io.ktor.http.appendPathSegments
import io.ktor.http.takeFrom
import io.ktor.http.toURI
import net.twisterrob.blt.io.feeds.trackernet.TrackerNetData
import net.twisterrob.blt.model.Line
import java.net.MalformedURLException
import java.net.URL
import java.util.Locale

/**
* From email: Thank you for registering for Transport for London (TfL) syndicated feeds.
*/
class TFLUrlBuilder(
private val email: String,
private val trackerNetData: TrackerNetData,
) : net.twisterrob.blt.io.feeds.URLBuilder {

@Throws(MalformedURLException::class)
fun getSyncdicationFeed(feedId: Int): URL {
val query = "?email=%s&feedId=%d".format(Locale.ROOT, email, feedId)
return URL(Feed.Type.Syndication.baseUrl, query)
}

@Throws(MalformedURLException::class)
fun getSyncdicationFeed(feed: Feed): URL {
require(feed.type == Feed.Type.Syndication) {
"Only syndication feeds are allowed here, got ${feed}."
}
return getSyncdicationFeed(feed.feedId)
}

@Throws(MalformedURLException::class)
override fun getFeedUrl(feed: Feed, args: Map<String, *>): URL {
if (feed.type == Feed.Type.Syndication) {
return getSyncdicationFeed(feed)
}
return URLBuilder()
.takeFrom(feed.url)
.run { handleArgs(feed, args) }
.build()
.toURI()
.toURL()
}

private fun URLBuilder.handleArgs(feed: Feed, args: Map<String, *>): URLBuilder =
when (feed) {
Feed.TubeDepartureBoardsPredictionSummary -> {
val line = args["line"] as Line
appendPathSegments(trackerNetData.getTrackerNetCodeOf(line))
}

Feed.TubeDepartureBoardsPredictionDetailed -> {
val line = args["line"] as Line
require(line in Line.UNDERGROUND) {
"${line} line is not Underground, cannot request prediction for it."
}
val code = trackerNetData.getTrackerNetCodeOf(line)
appendPathSegments(code, args["station"] as String)
}

else -> {
this // No special handling.
}
}
}
5 changes: 5 additions & 0 deletions config/lint/lint.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<issue id="InvalidPackage">
<ignore regexp="Invalid package reference in .*; not included in Android: `javax\.xml\.stream`\. Referenced from `net\.twisterrob\.blt\.io\.feeds\.timetable\.JourneyPlannerTimetableFeedKmlOut`\." />
<ignore regexp="Invalid package reference in .*; not included in Android: `javax\.xml\.stream`\. Referenced from `net\.twisterrob\.java\.io\.IndentingXMLStreamWriter`\." />
<!--
Suppress invalid reference, it's safe because it's wrapped in a try-catch(Throwable).
Location: %GRADLE_USER_HOME%\caches\modules-2\files-2.1\io.ktor\ktor-utils-jvm\3.0.0\3bc434db6eea43499f330eb49fd8d562147cd820\ktor-utils-jvm-3.0.0.jar
-->
<ignore regexp="Invalid package reference in library; not included in Android: `java\.lang\.management`\. Referenced from `io\.ktor\.util\.debug\.IntellijIdeaDebugDetector`\." />
</issue>
<issue id="UseTomlInstead">
<ignore path="**/Shared/build.gradle" />
Expand Down
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ kotlin-ksp = "2.0.21-1.0.26"
kotlin-datetime = "0.6.1"
kotlin-serialization = "1.7.3"

ktor = "3.0.0"

jsr305 = "3.0.2"
kxml2 = "2.3.0"

Expand Down Expand Up @@ -56,6 +58,8 @@ plugin-gretty = { module = "org.gretty:gretty", version.ref = "gretty" }
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
plugin-ksp = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "kotlin-ksp" }

ktor-http = { module = "io.ktor:ktor-http", version.ref = "ktor" }

plugin-micronaut = { module = "io.micronaut.application:io.micronaut.application.gradle.plugin", version.ref = "micronaut-gradle" }
#noinspection unused versions.micronaut is used for micronaut { version = ... }, micronaut-platform is added here to help Renovate.
micronaut-platform = { module = "io.micronaut.platform:micronaut-platform", version.ref = "micronaut" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package net.twisterrob.travel.statushistory.infrastructure
import io.micronaut.context.annotation.Bean
import kotlinx.datetime.Clock
import net.twisterrob.blt.io.feeds.URLBuilder
import net.twisterrob.java.io.IOTools
import net.twisterrob.java.utils.ObjectTools
import net.twisterrob.travel.domain.london.status.Feed
import net.twisterrob.travel.domain.london.status.Stacktrace
Expand All @@ -13,7 +12,6 @@ import net.twisterrob.travel.domain.london.status.api.StatusDataSource
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import net.twisterrob.blt.io.feeds.Feed as RawFeed

Expand All @@ -36,21 +34,20 @@ internal class HttpStatusDataSource(

@Throws(IOException::class)
fun downloadFeed(feed: RawFeed?): String {
var input: InputStream? = null
val result: String
val url = urlBuilder.getFeedUrl(feed, emptyMap<String, Any>())
LOG.debug("Requesting feed '{}': '{}'...", feed, url)
val connection = (url.openConnection() as HttpURLConnection)
.apply {
connectTimeout = 5000
readTimeout = 5000
connect()
}
try {
val url = urlBuilder.getFeedUrl(feed, emptyMap<String, Any>())
LOG.debug("Requesting feed '{}': '{}'...", feed, url)
val connection = url.openConnection() as HttpURLConnection
connection.connectTimeout = 5000
connection.readTimeout = 5000
connection.connect()
input = connection.inputStream
result = IOTools.readAll(input)
} finally {
IOTools.ignorantClose(input)
return connection.inputStream.bufferedReader().use { it.readText() }
} catch(ex: IOException) {
val result = connection.errorStream.bufferedReader().use { it.readText() }
throw IOException("Error while downloading feed: ${feed}: ${result}", ex)
}
return result
}

companion object {
Expand Down
5 changes: 3 additions & 2 deletions web/status-history/src/main/resources/views/LineStatus.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
</style>
</head>
<body>
{{#each feedChanges as | feedChange | }}{{! feedChange: ResultChangeModel --}}
{{#each feedChanges as | feedChange | }}{{! LineStatusModel.feedChange: ResultChangeModel --}}
<table class="info">
<thead>
<tr>
Expand All @@ -88,7 +88,7 @@
{{/if}}
</thead>
<tbody>
{{#each feedChange.statuses as | status | }}{{! status: LineStatusModel --}}
{{#each feedChange.statuses as | status | }}{{! ResultChangeModel.statuses: ResultChangeModel.LineStatusModel --}}
{{assign "delayStyle" ""}}
{{#if (not (empty status.description))}}
{{assign "delayStyle" (concat delayStyle " hasDetails")}}
Expand Down Expand Up @@ -130,6 +130,7 @@
<tfoot>
<tr>
<td colspan="3">
{{!-- feedChange.error: ResultChangeModel.ErrorChange --}}
{{#if (not (empty feedChange.error.header))}}
<a rel="htmltooltip">{{feedChange.error.type.title}}: {{feedChange.error.header}}</a>
<div class="htmltooltip">
Expand Down

0 comments on commit efbd5a0

Please sign in to comment.