#!perl use strict; use warnings; use 5.014; our $VERSION = '6.15'; use utf8; use DateTime; use Encode qw(decode); use JSON; use Getopt::Long qw(:config no_ignore_case); use List::MoreUtils qw(uniq); use List::Util qw(first max); use Travel::Status::DE::HAFAS; my ( $date, $time, $language ); my $arrivals; my $show_jid; my $num_results = 30; my $types = q{}; my $developer_mode; my $via; my $use_cache = 1; my $cache; my ( $json_output, $raw_json_output ); my ( $list_services, $service ); my ( @excluded_mots, @exclusive_mots ); my @output; binmode( STDOUT, ':encoding(utf-8)' ); for my $arg (@ARGV) { $arg = decode( 'UTF-8', $arg ); } my $output_bold = -t STDOUT ? "\033[1m" : q{}; my $output_reset = -t STDOUT ? "\033[0m" : q{}; GetOptions( 'a|arrivals' => \$arrivals, 'd|date=s' => \$date, 'h|help' => sub { show_help(0) }, 'j|with-jid' => \$show_jid, 'l|language=s' => \$language, 'm|mot=s' => \$types, 'n|num-results=s' => \$num_results, 's|service=s' => \$service, 't|time=s' => \$time, 'v|via=s' => \$via, 'V|version' => \&show_version, 'cache!' => \$use_cache, 'devmode' => \$developer_mode, 'json' => \$json_output, 'raw-json' => \$raw_json_output, 'list' => \$list_services, ) or show_help(1); if ($list_services) { printf( "%-40s %-14s %-15s %s\n\n", 'operator', 'abbr. (-s)', 'languages (-l)', 'time zone' ); for my $service ( Travel::Status::DE::HAFAS::get_services() ) { printf( "%-40s %-14s %-15s %s\n", @{$service}{qw(name shortname)}, join( q{ }, @{ $service->{languages} // [] } ), $service->{time_zone} // q{}, ); } exit 0; } if ($use_cache) { my $cache_path = ( $ENV{XDG_CACHE_HOME} // "$ENV{HOME}/.cache" ) . '/Travel-Status-DE-HAFAS'; eval { require Cache::File; $cache = Cache::File->new( cache_root => $cache_path, default_expires => '90 seconds', lock_level => Cache::File::LOCK_LOCAL(), ); }; if ($@) { $cache = undef; } } parse_mot_options(); my %opt = ( cache => $cache, excluded_mots => \@excluded_mots, exclusive_mots => \@exclusive_mots, station => shift || show_help(1), arrivals => $arrivals, developer_mode => $developer_mode, service => $service, language => $language, results => $num_results, ); if ( $opt{station} =~ m{ ^ (? [0-9.]+ ) : (? [0-9].+ ) $ }x ) { $opt{geoSearch} = { lat => $+{lat}, lon => $+{lon}, }; delete $opt{station}; } elsif ( $opt{station} =~ m{ ^ [?] (? .*) $ }x ) { $opt{locationSearch} = $+{query}; delete $opt{station}; } elsif ( $opt{station} =~ m{[|]} ) { $opt{journey} = { id => $opt{station} }; delete $opt{station}; } elsif ( $opt{station} =~ m{ ^ [!] (? .*) $ }x ) { $opt{journeyMatch} = $+{query}; delete $opt{station}; } if ( $date or $time ) { my $desc = Travel::Status::DE::HAFAS::get_service($service) // {}; my $dt = DateTime->now( time_zone => $desc->{time_zone} // 'Europe/Berlin' ); if ($date) { if ( $date =~ m{ ^ (? \d{1,2} ) [.] (? \d{1,2} ) [.] (? \d{4})? $ }x ) { $dt->set( day => $+{day}, month => $+{month} ); if ( $+{year} ) { $dt->set( year => $+{year} ); } } else { say "--date must be specified as DD.MM.[YYYY]"; exit 1; } } if ($time) { if ( $time =~ m{ ^ (? \d{1,2} ) : (? \d{1,2} ) $ }x ) { $dt->set( hour => $+{hour}, minute => $+{minute}, second => 0, ); } else { say "--time must be specified as HH:MM"; exit 1; } } $opt{datetime} = $dt; } my $status = Travel::Status::DE::HAFAS->new(%opt); sub show_help { my ($code) = @_; print 'Usage: hafas-m [-d ] [-m ] [-t