From dafeb838dc245176444acc7c0338290dbbf0307b Mon Sep 17 00:00:00 2001
From: Birte Kristina Friesel <derf@finalrewind.org>
Date: Sat, 24 Feb 2024 20:11:11 +0100
Subject: [PATCH] Use journeyMatch rather than legacy trainsearch.exe API to
 find tripIDs

---
 lib/Travelynx.pm              | 59 +++--------------------------------
 lib/Travelynx/Helper/HAFAS.pm | 50 +++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 55 deletions(-)

diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index 41abeed3..6d371b55 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -1169,6 +1169,8 @@ sub startup {
 		}
 	);
 
+	# This helper is only ever called from an IRIS context.
+	# HAFAS already has all relevant information.
 	$self->helper(
 		'add_route_timestamps' => sub {
 			my ( $self, $uid, $train, $is_departure, $update_polyline ) = @_;
@@ -1190,64 +1192,11 @@ sub startup {
 				return;
 			}
 
-			my ($platform) = ( ( $train->platform // 0 ) =~ m{(\d+)} );
-
 			my $route = $in_transit->{route};
 
-			my $base
-			  = 'https://reiseauskunft.bahn.de/bin/trainsearch.exe/dn?L=vs_json.vs_hap&start=yes&rt=1';
-			my $date_yy   = $train->start->strftime('%d.%m.%y');
-			my $date_yyyy = $train->start->strftime('%d.%m.%Y');
-			my $train_no  = $train->type . ' ' . $train->train_no;
-
-			$self->hafas->get_json_p(
-				"${base}&date=${date_yy}&trainname=${train_no}")->then(
+			$self->hafas->get_tripid_p( train => $train )->then(
 				sub {
-					my ($trainsearch) = @_;
-
-					# Fallback: Take first result
-					my $result = $trainsearch->{suggestions}[0];
-
-					# Try finding a result for the current date
-					for
-					  my $suggestion ( @{ $trainsearch->{suggestions} // [] } )
-					{
-
-						# Drunken API, sail with care. Both date formats are used interchangeably
-						if (
-							$suggestion->{depDate}
-							and (  $suggestion->{depDate} eq $date_yy
-								or $suggestion->{depDate} eq $date_yyyy )
-						  )
-						{
-							# Train numbers are not unique, e.g. IC 149 refers both to the
-							# InterCity service Amsterdam -> Berlin and to the InterCity service
-							# Koebenhavns Lufthavn st -> Aarhus.  One workaround is making
-							# requests with the stationFilter=80 parameter.  Checking the origin
-							# station seems to be the more generic solution, so we do that
-							# instead.
-							if ( $suggestion->{dep} eq $train->origin ) {
-								$result = $suggestion;
-								last;
-							}
-						}
-					}
-
-					if ( not $result ) {
-						$self->app->log->debug("trainlink not found");
-						return Mojo::Promise->reject("trainlink not found");
-					}
-
-					# Calculate and store trip_id.
-					# The trip_id's date part doesn't seem to matter -- so far,
-					# HAFAS is happy as long as the date part starts with a number.
-					# HAFAS-internal tripIDs use this format (withouth leading zero
-					# for day of month < 10) though, so let's stick with it.
-					my $date_map = $date_yyyy;
-					$date_map =~ tr{.}{}d;
-					my $trip_id = sprintf( '1|%d|%d|%d|%s',
-						$result->{id},   $result->{cycle},
-						$result->{pool}, $date_map );
+					my ($trip_id) = @_;
 
 					$self->in_transit->update_data(
 						uid  => $uid,
diff --git a/lib/Travelynx/Helper/HAFAS.pm b/lib/Travelynx/Helper/HAFAS.pm
index d7f2a10c..5a20515f 100644
--- a/lib/Travelynx/Helper/HAFAS.pm
+++ b/lib/Travelynx/Helper/HAFAS.pm
@@ -109,6 +109,56 @@ sub search_location_p {
 	);
 }
 
+sub get_tripid_p {
+	my ( $self, %opt ) = @_;
+
+	my $promise = Mojo::Promise->new;
+
+	my $train      = $opt{train};
+	my $train_desc = $train->type . ' ' . $train->train_no;
+	$train_desc =~ s{^- }{};
+
+	Travel::Status::DE::HAFAS->new_p(
+		journeyMatch => $train_desc,
+		datetime     => $train->start,
+		cache        => $self->{realtime_cache},
+		promise      => 'Mojo::Promise',
+		user_agent   => $self->{user_agent}->request_timeout(10),
+	)->then(
+		sub {
+			my ($hafas) = @_;
+			my @results = $hafas->results;
+
+			if ( not @results ) {
+				$promise->reject(
+					"journeyMatch($train_desc) returned no results");
+				return;
+			}
+
+			my $result = $results[0];
+			if ( @results > 1 ) {
+				for my $journey (@results) {
+					if ( ( $journey->route )[0]->loc->name eq $train->origin ) {
+						$result = $journey;
+						last;
+					}
+				}
+			}
+
+			$promise->resolve( $result->id );
+			return;
+		}
+	)->catch(
+		sub {
+			my ($err) = @_;
+			$promise->reject($err);
+			return;
+		}
+	)->wait;
+
+	return $promise;
+}
+
 sub get_journey_p {
 	my ( $self, %opt ) = @_;
 
-- 
GitLab