diff options
Diffstat (limited to 'lib/Travelynx/Helper/HAFAS.pm')
-rw-r--r-- | lib/Travelynx/Helper/HAFAS.pm | 235 |
1 files changed, 168 insertions, 67 deletions
diff --git a/lib/Travelynx/Helper/HAFAS.pm b/lib/Travelynx/Helper/HAFAS.pm index 1c36925..c35dfdb 100644 --- a/lib/Travelynx/Helper/HAFAS.pm +++ b/lib/Travelynx/Helper/HAFAS.pm @@ -7,11 +7,13 @@ package Travelynx::Helper::HAFAS; use strict; use warnings; use 5.020; +use utf8; use DateTime; use Encode qw(decode); use JSON; use Mojo::Promise; +use Mojo::UserAgent; use Travel::Status::DE::HAFAS; sub _epoch { @@ -33,69 +35,138 @@ sub new { return bless( \%opt, $class ); } -sub get_json_p { - my ( $self, $url, %opt ) = @_; +sub class_to_product { + my ( $self, $hafas ) = @_; - my $cache = $self->{main_cache}; - my $promise = Mojo::Promise->new; + my $bits = $hafas->get_active_service->{productbits}; + my $ret; - if ( $opt{realtime} ) { - $cache = $self->{realtime_cache}; + for my $i ( 0 .. $#{$bits} ) { + $ret->{ 2**$i } + = ref( $bits->[$i] ) eq 'ARRAY' ? $bits->[$i][0] : $bits->[$i]; } - $opt{encoding} //= 'ISO-8859-15'; - if ( my $content = $cache->thaw($url) ) { - return $promise->resolve($content); + return $ret; +} + +sub get_service { + my ( $self, $service ) = @_; + + return Travel::Status::DE::HAFAS::get_service($service); +} + +sub get_departures_p { + my ( $self, %opt ) = @_; + + $opt{service} //= 'ÖBB'; + + my $agent = $self->{user_agent}; + if ( my $proxy = $self->{service_config}{ $opt{service} }{proxy} ) { + $agent = Mojo::UserAgent->new; + $agent->proxy->http($proxy); + $agent->proxy->https($proxy); } - $self->{user_agent}->request_timeout(5)->get_p( $url => $self->{header} ) - ->then( + my $when = ( + $opt{timestamp} + ? $opt{timestamp}->clone + : DateTime->now( time_zone => 'Europe/Berlin' ) + )->subtract( minutes => $opt{lookbehind} ); + return Travel::Status::DE::HAFAS->new_p( + service => $opt{service}, + station => $opt{eva}, + datetime => $when, + lookahead => $opt{lookahead} + $opt{lookbehind}, + results => 300, + cache => $self->{realtime_cache}, + promise => 'Mojo::Promise', + user_agent => $agent->request_timeout(5), + ); +} + +sub search_location_p { + my ( $self, %opt ) = @_; + + $opt{service} //= 'ÖBB'; + + my $agent = $self->{user_agent}; + if ( my $proxy = $self->{service_config}{ $opt{service} }{proxy} ) { + $agent = Mojo::UserAgent->new; + $agent->proxy->http($proxy); + $agent->proxy->https($proxy); + } + + return Travel::Status::DE::HAFAS->new_p( + service => $opt{service}, + locationSearch => $opt{query}, + cache => $self->{realtime_cache}, + promise => 'Mojo::Promise', + user_agent => $agent->request_timeout(5), + ); +} + +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{^- }{}; + + $opt{service} //= 'ÖBB'; + + my $agent = $self->{user_agent}; + if ( my $proxy = $self->{service_config}{ $opt{service} }{proxy} ) { + $agent = Mojo::UserAgent->new; + $agent->proxy->http($proxy); + $agent->proxy->https($proxy); + } + + Travel::Status::DE::HAFAS->new_p( + service => $opt{service}, + journeyMatch => $train_desc, + datetime => $train->start, + cache => $self->{realtime_cache}, + promise => 'Mojo::Promise', + user_agent => $agent->request_timeout(10), + )->then( sub { - my ($tx) = @_; + my ($hafas) = @_; + my @results = $hafas->results; - if ( my $err = $tx->error ) { + if ( not @results ) { + $self->{log}->debug("get_tripid_p($train_desc): no results"); $promise->reject( -"hafas->get_json_p($url) returned HTTP $err->{code} $err->{message}" - ); + "journeyMatch($train_desc) returned no results"); return; } - my $body = decode( $opt{encoding}, $tx->res->body ); + $self->{log}->debug("get_tripid_p($train_desc): success"); + + my $result = $results[0]; + if ( @results > 1 ) { + for my $journey (@results) { + if ( ( $journey->route )[0]->loc->name eq $train->origin ) { + $result = $journey; + last; + } + } + } - $body =~ s{^TSLs[.]sls = }{}; - $body =~ s{;$}{}; - $body =~ s{(}{(}g; - $body =~ s{)}{)}g; - my $json = JSON->new->decode($body); - $cache->freeze( $url, $json ); - $promise->resolve($json); + $promise->resolve( $result->id ); return; } )->catch( sub { my ($err) = @_; - $self->{log}->info("hafas->get_json_p($url): $err"); - $promise->reject("hafas->get_json_p($url): $err"); + $self->{log}->debug("get_tripid_p($train_desc): error $err"); + $promise->reject($err); return; } )->wait; - return $promise; -} - -sub get_departures_p { - my ( $self, %opt ) = @_; - my $when = DateTime->now( time_zone => 'Europe/Berlin' ) - ->subtract( minutes => $opt{lookbehind} ); - return Travel::Status::DE::HAFAS->new_p( - station => $opt{eva}, - datetime => $when, - duration => $opt{lookahead}, - results => 300, - cache => $self->{realtime_cache}, - promise => 'Mojo::Promise', - user_agent => $self->{user_agent}->request_timeout(5), - ); + return $promise; } sub get_journey_p { @@ -104,29 +175,42 @@ sub get_journey_p { my $promise = Mojo::Promise->new; my $now = DateTime->now( time_zone => 'Europe/Berlin' ); + $opt{service} //= 'ÖBB'; + + my $agent = $self->{user_agent}; + if ( my $proxy = $self->{service_config}{ $opt{service} }{proxy} ) { + $agent = Mojo::UserAgent->new; + $agent->proxy->http($proxy); + $agent->proxy->https($proxy); + } + Travel::Status::DE::HAFAS->new_p( + service => $opt{service}, journey => { id => $opt{trip_id}, }, - with_polyline => 0, + with_polyline => $opt{with_polyline}, cache => $self->{realtime_cache}, promise => 'Mojo::Promise', - user_agent => $self->{user_agent}->request_timeout(10), + user_agent => $agent->request_timeout(10), )->then( sub { my ($hafas) = @_; my $journey = $hafas->result; if ($journey) { + $self->{log}->debug("get_journey_p($opt{trip_id}): success"); $promise->resolve($journey); return; } + $self->{log}->debug("get_journey_p($opt{trip_id}): no journey"); $promise->reject('no journey'); return; } )->catch( sub { my ($err) = @_; + $self->{log}->debug("get_journey_p($opt{trip_id}): error $err"); $promise->reject($err); return; } @@ -135,13 +219,23 @@ sub get_journey_p { return $promise; } -sub get_route_timestamps_p { +sub get_route_p { my ( $self, %opt ) = @_; my $promise = Mojo::Promise->new; my $now = DateTime->now( time_zone => 'Europe/Berlin' ); + $opt{service} //= 'ÖBB'; + + my $agent = $self->{user_agent}; + if ( my $proxy = $self->{service_config}{ $opt{service} }{proxy} ) { + $agent = Mojo::UserAgent->new; + $agent->proxy->http($proxy); + $agent->proxy->https($proxy); + } + Travel::Status::DE::HAFAS->new_p( + service => $opt{service}, journey => { id => $opt{trip_id}, @@ -150,46 +244,51 @@ sub get_route_timestamps_p { with_polyline => $opt{with_polyline}, cache => $self->{realtime_cache}, promise => 'Mojo::Promise', - user_agent => $self->{user_agent}->request_timeout(10), + user_agent => $agent->request_timeout(10), )->then( sub { my ($hafas) = @_; my $journey = $hafas->result; - my $ret = {}; + my $ret = []; my $polyline; my $station_is_past = 1; for my $stop ( $journey->route ) { - my $name = $stop->{name}; - $ret->{$name} = $ret->{ $stop->{eva} } = { - name => $stop->{name}, - eva => $stop->{eva}, - 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}, - load => $stop->{load} + my $entry = { + name => $stop->loc->name, + eva => $stop->loc->eva, + 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, + load => $stop->load, + lat => $stop->loc->lat, + lon => $stop->loc->lon, }; - if ( ( $stop->{arr_cancelled} or not $stop->{sched_arr} ) - and ( $stop->{dep_cancelled} or not $stop->{sched_dep} ) ) + if ( $stop->tz_offset ) { + $entry->{tz_offset} = $stop->tz_offset; + } + if ( ( $stop->arr_cancelled or not $stop->sched_arr ) + and ( $stop->dep_cancelled or not $stop->sched_dep ) ) { - $ret->{$name}{isCancelled} = 1; + $entry->{isCancelled} = 1; } if ( $station_is_past - and not $ret->{$name}{isCancelled} + and not $entry->{isCancelled} and $now->epoch < ( - $ret->{$name}{rt_arr} // $ret->{$name}{rt_dep} - // $ret->{$name}{sched_arr} - // $ret->{$name}{sched_dep} // $now->epoch + $entry->{rt_arr} // $entry->{rt_dep} + // $entry->{sched_arr} // $entry->{sched_dep} + // $now->epoch ) ) { $station_is_past = 0; } - $ret->{$name}{isPast} = $station_is_past; + $entry->{isPast} = $station_is_past; + push( @{$ret}, $entry ); } if ( $journey->polyline ) { @@ -218,8 +317,8 @@ sub get_route_timestamps_p { or index( $hafas_stations, $iris_stations ) != -1 ) { $polyline = { - from_eva => ( $journey->route )[0]{eva}, - to_eva => ( $journey->route )[-1]{eva}, + from_eva => ( $journey->route )[0]->loc->eva, + to_eva => ( $journey->route )[-1]->loc->eva, coords => \@coordinate_list, }; } @@ -231,12 +330,14 @@ sub get_route_timestamps_p { } } + $self->{log}->debug("get_route_p($opt{trip_id}): success"); $promise->resolve( $ret, $journey, $polyline ); return; } )->catch( sub { my ($err) = @_; + $self->{log}->debug("get_route_p($opt{trip_id}): error $err"); $promise->reject($err); return; } |