diff options
author | Birte Kristina Friesel <derf@finalrewind.org> | 2025-02-02 18:25:47 +0100 |
---|---|---|
committer | Birte Kristina Friesel <derf@finalrewind.org> | 2025-02-02 18:25:47 +0100 |
commit | 7cb9cb9836af5db19568886f9804b7032d27312f (patch) | |
tree | 5327fea154cda3a6fbad33241f1d1c61f08273f1 | |
parent | 43f9af3c356a0607e3fcc121311f11bf57746e2b (diff) |
add ticket offer API client and --with-offers option
-rwxr-xr-x | bin/dbris | 27 | ||||
-rw-r--r-- | lib/Travel/Routing/DE/DBRIS.pm | 118 | ||||
-rw-r--r-- | lib/Travel/Routing/DE/DBRIS/Connection.pm | 3 | ||||
-rw-r--r-- | lib/Travel/Routing/DE/DBRIS/Offer.pm | 39 |
4 files changed, 151 insertions, 36 deletions
@@ -16,9 +16,9 @@ use Travel::Routing::DE::DBRIS; my ( $date, $time, $arrival, $from, $to, $language ); my $mots; +my ( $show_jid, $show_full_route, $show_offers ); my ( $first_class, $passengers ); my ( $developer_mode, $verbose ); -my ( $show_jid, $show_full_route ); my ( $json_output, $raw_json_output ); my $use_cache = 1; my $cache; @@ -55,6 +55,7 @@ GetOptions( 'j|with-jid' => \$show_jid, 'm|modes-of-transit=s' => \$mots, 'l|language=s' => \$language, + 'o|with-offers' => \$show_offers, 'p|passengers=s' => \$passengers, 't|time=s' => \$time, 'v|verbose' => \$verbose, @@ -369,6 +370,30 @@ for my $connection ( $ris->connections ) { $header, ); + if ($show_offers) { + my $offers_req = Travel::Routing::DE::DBRIS->new( + developer_mode => $developer_mode, + offers => { + recon => $connection->recon, + }, + passengers => $opt{passengers}, + first_class => $opt{first_class}, + ); + if ( my $err = $offers_req->errstr ) { + say STDERR "Request error while looking up offers: ${err}"; + } + for my $offer ($offers_req->offers) { + printf('- %5.2f %s %s', $offer->price, $offer->price_unit =~ s{EUR}{€}r, $offer->name); + if ($first_class and $offer->class == 2 or not $first_class and $offer->class == 1) { + printf(" %d. Klasse", $offer->class); + } + if (scalar $offer->conditions) { + printf(' (%s)', join(q{ · }, map { $_->{textKurz} } $offer->conditions)); + } + say q{}; + } + } + if ($verbose) { for my $note ( $connection->notes ) { printf( "| %s (%s)\n", $note->{value}, $note->{key} ); diff --git a/lib/Travel/Routing/DE/DBRIS.pm b/lib/Travel/Routing/DE/DBRIS.pm index f596bfd..07399a3 100644 --- a/lib/Travel/Routing/DE/DBRIS.pm +++ b/lib/Travel/Routing/DE/DBRIS.pm @@ -16,6 +16,7 @@ use JSON; use LWP::UserAgent; use Travel::Status::DE::DBRIS; use Travel::Routing::DE::DBRIS::Connection; +use Travel::Routing::DE::DBRIS::Offer; our $VERSION = '0.03'; @@ -60,37 +61,67 @@ sub new { @mots = @{ $conf{modes_of_transit} // [] }; } - my $req_url - = $self->{language} eq 'de' - ? 'https://www.bahn.de/web/api/angebote/fahrplan' - : 'https://int.bahn.de/web/api/angebote/fahrplan'; - my $req = { - abfahrtsHalt => $conf{from}->id, - ankunftsHalt => $conf{to}->id, - anfrageZeitpunkt => $dt->strftime('%Y-%m-%dT%H:%M:00'), - ankunftSuche => $conf{arrival} ? 'ANKUNFT' : 'ABFAHRT', - klasse => $conf{first_class} ? 'KLASSE_1' : 'KLASSE_2', - produktgattungen => \@mots, - reisende => [ - { - typ => 'ERWACHSENER', - ermaessigungen => [ - { - art => 'KEINE_ERMAESSIGUNG', - klasse => 'KLASSENLOS' - }, - ], - alter => [], - anzahl => 1, - } - ], - schnelleVerbindungen => \1, - sitzplatzOnly => \0, - bikeCarriage => \0, - reservierungsKontingenteVorhanden => \0, - nurDeutschlandTicketVerbindungen => \0, - deutschlandTicketVorhanden => \0 - }; + my ($req_url, $req); + + if ($conf{from} and $conf{to}) { + $req_url + = $self->{language} eq 'de' + ? 'https://www.bahn.de/web/api/angebote/fahrplan' + : 'https://int.bahn.de/web/api/angebote/fahrplan'; + $req = { + abfahrtsHalt => $conf{from}->id, + ankunftsHalt => $conf{to}->id, + anfrageZeitpunkt => $dt->strftime('%Y-%m-%dT%H:%M:00'), + ankunftSuche => $conf{arrival} ? 'ANKUNFT' : 'ABFAHRT', + klasse => $conf{first_class} ? 'KLASSE_1' : 'KLASSE_2', + produktgattungen => \@mots, + reisende => [ + { + typ => 'ERWACHSENER', + ermaessigungen => [ + { + art => 'KEINE_ERMAESSIGUNG', + klasse => 'KLASSENLOS' + }, + ], + alter => [], + anzahl => 1, + } + ], + schnelleVerbindungen => \1, + sitzplatzOnly => \0, + bikeCarriage => \0, + reservierungsKontingenteVorhanden => \0, + nurDeutschlandTicketVerbindungen => \0, + deutschlandTicketVorhanden => \0 + }; + } + elsif ($conf{offers}) { + $req_url + = $self->{language} eq 'de' + ? 'https://www.bahn.de/web/api/angebote/recon' + : 'https://int.bahn.de/web/api/angebote/recon'; + $req = { + klasse => $conf{first_class} ? 'KLASSE_1' : 'KLASSE_2', + ctxRecon => $conf{offers}{recon}, + reisende => [ + { + typ => 'ERWACHSENER', + ermaessigungen => [ + { + art => 'KEINE_ERMAESSIGUNG', + klasse => 'KLASSENLOS' + }, + ], + alter => [], + anzahl => 1, + } + ], + reservierungsKontingenteVorhanden => \0, + nurDeutschlandTicketVerbindungen => \0, + deutschlandTicketVorhanden => \0 + }; + } for my $via ( @{ $conf{via} } ) { my $via_stop = { id => $via->{stop}->id }; @@ -184,7 +215,12 @@ sub new { } $self->{raw_json} = $json->decode($content); - $self->parse_connections; + if ($conf{from} and $conf{to}) { + $self->parse_connections; + } + elsif ($conf{offers}) { + $self->parse_offers; + } } return $self; @@ -258,7 +294,6 @@ sub post_with_cache { ); if ( $reply->is_error ) { - say $reply->status_line; return ( undef, $reply->status_line ); } my $content = $reply->content; @@ -294,6 +329,16 @@ sub parse_connections { } } +sub parse_offers { + my ($self) = @_; + + for my $offer (@{$self->{raw_json}{verbindungen}[0]{reiseAngebote} // []}) { + push(@{$self->{offers}}, Travel::Routing::DE::DBRIS::Offer->new( + json => $offer + )); + } +} + # }}} # {{{ Public Functions @@ -305,7 +350,12 @@ sub errstr { sub connections { my ($self) = @_; - return @{ $self->{connections} }; + return @{ $self->{connections} // []}; +} + +sub offers { + my ($self) = @_; + return @{$self->{offers} // [] }; } # }}} diff --git a/lib/Travel/Routing/DE/DBRIS/Connection.pm b/lib/Travel/Routing/DE/DBRIS/Connection.pm index b090e01..8062929 100644 --- a/lib/Travel/Routing/DE/DBRIS/Connection.pm +++ b/lib/Travel/Routing/DE/DBRIS/Connection.pm @@ -18,7 +18,7 @@ Travel::Routing::DE::DBRIS::Connection->mk_ro_accessors( sched_dep rt_dep dep sched_arr rt_arr arr occupancy occupancy_first occupancy_second - price price_unit + price price_unit recon ) ); @@ -35,6 +35,7 @@ sub new { // -1, is_unscheduled => $json->{isAlternativeVerbindung}, id => $json->{tripId}, + recon => $json->{ctxRecon}, price => $json->{angebotsPreis}{betrag}, price_unit => $json->{angebotsPreis}{waehrung}, strptime_obj => $strptime, diff --git a/lib/Travel/Routing/DE/DBRIS/Offer.pm b/lib/Travel/Routing/DE/DBRIS/Offer.pm new file mode 100644 index 0000000..47bf543 --- /dev/null +++ b/lib/Travel/Routing/DE/DBRIS/Offer.pm @@ -0,0 +1,39 @@ +package Travel::Routing::DE::DBRIS::Offer; + +use strict; +use warnings; +use 5.020; +use utf8; + +use parent 'Class::Accessor'; + +our $VERSION = '0.03'; + +Travel::Routing::DE::DBRIS::Offer->mk_ro_accessors( + qw(class name price price_unit)); + +sub new { + my ( $obj, %opt ) = @_; + + my $json = $opt{json}; + + my $ref = { + class => $json->{klasse} =~ s{KLASSE_}{}r, + name => $json->{name}, + price => $json->{preis}{betrag}, + price_unit => $json->{preis}{waehrung}, + conditions => $json->{konditionsAnzeigen}, + }; + + bless( $ref, $obj ); + + return $ref; +} + +sub conditions { + my ($self) = @_; + + return @{ $self->{conditions} // [] }; +} + +1; |