diff options
| author | Daniel Friesel <derf@finalrewind.org> | 2022-11-05 19:19:52 +0100 | 
|---|---|---|
| committer | Daniel Friesel <derf@finalrewind.org> | 2022-11-05 19:19:52 +0100 | 
| commit | 087d3871e127175652c5acc8e44c3c7e358ce05f (patch) | |
| tree | 244e6dbcfbbaf6dfa35462ad8ed04abab888144d /lib/Travelynx | |
| parent | bde634640113a19e62c92a96c65cddd5e11dd19d (diff) | |
Use Travel::Status::DE::HAFAS instead of traininfo.exe for journey details
Diffstat (limited to 'lib/Travelynx')
| -rw-r--r-- | lib/Travelynx/Helper/HAFAS.pm | 167 | 
1 files changed, 58 insertions, 109 deletions
| diff --git a/lib/Travelynx/Helper/HAFAS.pm b/lib/Travelynx/Helper/HAFAS.pm index c8e0ef4..62814b6 100644 --- a/lib/Travelynx/Helper/HAFAS.pm +++ b/lib/Travelynx/Helper/HAFAS.pm @@ -12,8 +12,15 @@ use DateTime;  use Encode qw(decode);  use JSON;  use Mojo::Promise; +use Travel::Status::DE::HAFAS;  use XML::LibXML; +sub _epoch { +	my ($dt) = @_; + +	return $dt ? $dt->epoch : 0; +} +  sub new {  	my ( $class, %opt ) = @_; @@ -167,129 +174,71 @@ sub get_json_p {  	return $promise;  } -sub get_xml_p { -	my ( $self, $url ) = @_; +sub get_route_timestamps_p { +	my ( $self, %opt ) = @_; -	my $cache   = $self->{realtime_cache};  	my $promise = Mojo::Promise->new; - -	if ( my $content = $cache->thaw($url) ) { -		return $promise->resolve($content); -	} - -	$self->{user_agent}->request_timeout(5)->get_p( $url => $self->{header} ) -	  ->then( +	my $now     = DateTime->now( time_zone => 'Europe/Berlin' ); + +	Travel::Status::DE::HAFAS->new_p( +		journey => { +			id => $opt{trip_id}, + +			# name => $opt{train_no}, +		}, +		cache      => $self->{realtime_cache}, +		promise    => 'Mojo::Promise', +		user_agent => $self->{user_agent}->request_timeout(10) +	)->then(  		sub { -			my ($tx) = @_; - -			if ( my $err = $tx->error ) { -				$promise->reject( -"hafas->get_xml_p($url) returned HTTP $err->{code} $err->{message}" -				); -				return; -			} - -			my $body = decode( 'ISO-8859-15', $tx->res->body ); -			my $tree; - -			my $traininfo = { -				station  => {}, -				messages => [], -			}; - -			# <SDay text="... > ..."> is invalid XML, but present in -			# regardless. As it is the last tag, we just throw it away. -			$body =~ s{<SDay [^>]*/>}{}s; - -			# More fixes for invalid XML -			$body =~ s{P&R}{P&R}; -			$body =~ s{& }{& }g; - -			# <Attribute [...] text="[...]"[...]"" /> is invalid XML. -			# Work around it. -			$body -			  =~ s{<Attribute([^>]+)text="([^"]*)"([^"=>]*)""}{<Attribute$1text="$2*$3*"}s; - -			# Same for <HIMMessage lead="[...]"[...]"[...]" /> -			$body -			  =~ s{<HIMMessage([^>]+)lead="([^"]*)"([^"=>]*)"([^"]*)"}{<Attribute$1text="$2*$3*$4"}s; - -			# ... and <HIMMessage [...] lead="[...]<>[...]"> -			# (replace <> with t$t) -			while ( $body -				=~ s{<HIMMessage([^>]+)lead="([^"]*)<>([^"=]*)"}{<HIMMessage$1lead="$2⬌$3"}gis -			  ) -			{ -			} - -			# Dito for <HIMMessage [...] lead="[...]<br>[...]">. -			while ( $body -				=~ s{<HIMMessage([^>]+)lead="([^"]*)<br/?>([^"=]*)"}{<HIMMessage$1lead="$2 $3"}is -			  ) -			{ -			} - -			# ... and any other HTML tag inside an XML attribute -			while ( $body -				=~ s{<HIMMessage([^>]+)lead="([^"]*)<[^>]+>([^"=]*)"}{<HIMMessage$1lead="$2$3"}is -			  ) -			{ -			} - -			eval { $tree = XML::LibXML->load_xml( string => $body ) }; -			if ( my $err = $@ ) { -				if ( $err =~ m{extra content at the end}i ) { - -					# We requested XML, but received an HTML error page -					# (which was returned with HTTP 200 OK). -					$self->{log}->debug("load_xml($url): $err"); -				} -				else { -					# There is invalid XML which we might be able to fix via -					# regular expressions, so dump it into the production log. -					$self->{log}->info("load_xml($url): $err"); -				} -				$cache->freeze( $url, $traininfo ); -				$promise->reject("hafas->get_xml_p($url): $err"); -				return; -			} - -			for my $station ( $tree->findnodes('/Journey/St') ) { -				my $name   = $station->getAttribute('name'); -				my $adelay = $station->getAttribute('adelay'); -				my $ddelay = $station->getAttribute('ddelay'); -				$traininfo->{station}{$name} = { -					adelay => $adelay, -					ddelay => $ddelay, +			my ($hafas) = @_; +			my $journey = $hafas->result; +			my $ret     = {}; + +			my $station_is_past = 1; +			for my $stop ( $journey->route ) { +				my $name = $stop->{name}; +				$ret->{$name} = { +					sched_arr   => _epoch( $stop->{sched_arr} ), +					sched_dep   => _epoch( $stop->{sched_dep} ), +					rt_arr      => _epoch( $stop->{rt_arr} ), +					rt_dep      => _epoch( $stop->{rt_dep} ), +					arr_delay   => $stop->{arr_delay}, +					dep_delay   => $stop->{dep_delay}, +					eva         => $stop->{eva}, +					load        => $stop->{load}, +					isCancelled => ( +						( $stop->{arr_cancelled} or not $stop->{sched_arr} ) +						  and +						  ( $stop->{dep_cancelled} or not $stop->{sched_dep} ) +					),  				}; +				if ( +					    $station_is_past +					and not $ret->{$name}{isCancelled} +					and $now->epoch < ( +						$ret->{$name}{rt_arr} // $ret->{$name}{rt_dep} +						  // $ret->{$name}{sched_arr} +						  // $ret->{$name}{sched_dep} // $now->epoch +					) +				  ) +				{ +					$station_is_past = 0; +				} +				$ret->{$name}{isPast} = $station_is_past;  			} -			for my $message ( $tree->findnodes('/Journey/HIMMessage') ) { -				my $header  = $message->getAttribute('header'); -				my $lead    = $message->getAttribute('lead'); -				my $display = $message->getAttribute('display'); -				push( -					@{ $traininfo->{messages} }, -					{ -						header  => $header, -						lead    => $lead, -						display => $display -					} -				); -			} - -			$cache->freeze( $url, $traininfo ); -			$promise->resolve($traininfo); +			$promise->resolve( $ret, $journey );  			return;  		}  	)->catch(  		sub {  			my ($err) = @_; -			$self->{log}->info("hafas->get_xml_p($url): $err"); -			$promise->reject("hafas->get_xml_p($url): $err"); +			$promise->reject($err);  			return;  		}  	)->wait; +  	return $promise;  } | 
