diff options
author | Birte Kristina Friesel <derf@finalrewind.org> | 2025-06-09 12:46:08 +0200 |
---|---|---|
committer | Birte Kristina Friesel <derf@finalrewind.org> | 2025-06-09 12:46:08 +0200 |
commit | c695494dbd6aaf252199da42ad763bdffa1d64b9 (patch) | |
tree | 85f794a8ded7bbb6fd034a98028adf3932b44350 /lib/Travelynx | |
parent | e5da62bcfc7953d5109ba53ae1fcc34f509f251b (diff) | |
parent | 3322ca23669871fff79a229b9167f2e3169c4352 (diff) |
Merge branch 'main' into motis
Diffstat (limited to 'lib/Travelynx')
-rw-r--r-- | lib/Travelynx/Command/work.pm | 12 | ||||
-rwxr-xr-x | lib/Travelynx/Controller/Profile.pm | 28 | ||||
-rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 15 | ||||
-rw-r--r-- | lib/Travelynx/Helper/DBRIS.pm | 11 | ||||
-rw-r--r-- | lib/Travelynx/Model/InTransit.pm | 183 | ||||
-rw-r--r-- | lib/Travelynx/Model/Users.pm | 2 |
6 files changed, 186 insertions, 65 deletions
diff --git a/lib/Travelynx/Command/work.pm b/lib/Travelynx/Command/work.pm index 4363d9f..4ff5c9e 100644 --- a/lib/Travelynx/Command/work.pm +++ b/lib/Travelynx/Command/work.pm @@ -135,6 +135,18 @@ sub run { $found_arr->eva ); } } + if ( $found_arr and $found_arr->is_cancelled ) { + + # check out (adds a cancelled journey and resets journey state + # to destination selection) + $self->app->checkout_p( + station => $arr, + force => 0, + dep_eva => $dep, + arr_eva => $arr, + uid => $uid + )->wait; + } } )->catch( sub { diff --git a/lib/Travelynx/Controller/Profile.pm b/lib/Travelynx/Controller/Profile.pm index c35642d..db30d36 100755 --- a/lib/Travelynx/Controller/Profile.pm +++ b/lib/Travelynx/Controller/Profile.pm @@ -111,6 +111,13 @@ sub profile { $status->{arr_name} = undef; } + my $map_data = {}; + if ( $status->{checked_in} ) { + $map_data = $self->journeys_to_map_data( + journeys => [$status], + ); + } + my @journeys; if ( @@ -190,6 +197,8 @@ sub profile { : 0, journey => $status, journeys => [@journeys], + with_map => 1, + %{$map_data}, } ); } @@ -494,6 +503,13 @@ sub user_status { $og_data{description} = $tw_data{description} = q{}; } + my $map_data = {}; + if ( $status->{checked_in} ) { + $map_data = $self->journeys_to_map_data( + journeys => [$status], + ); + } + $self->respond_to( json => { json => { @@ -516,7 +532,9 @@ sub user_status { journey => $status, twitter => \%tw_data, opengraph => \%og_data, - version => $self->app->config->{version} // 'UNKNOWN', + with_map => 1, + %{$map_data}, + version => $self->app->config->{version} // 'UNKNOWN', }, ); } @@ -555,6 +573,7 @@ sub status_card { my $status = $self->get_user_status( $user->{id} ); my $visibility; + my $map_data = {}; if ( $status->{checked_in} or $status->{arr_name} ) { my $visibility = $status->{effective_visibility}; if ( @@ -579,12 +598,19 @@ sub status_card { $status->{arr_name} = undef; } + if ( $status->{checked_in} ) { + $map_data = $self->journeys_to_map_data( + journeys => [$status], + ); + } + $self->render( '_public_status_card', name => $name, privacy => $user, journey => $status, from_profile => $self->param('profile') ? 1 : 0, + %{$map_data}, ); } diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 8a8ac7a..aa7ee9b 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -359,6 +359,9 @@ sub homepage { $self->stash( timeline => [@timeline] ); my @recent_targets; if ( $status->{checked_in} ) { + my $map_data = $self->journeys_to_map_data( + journeys => [$status], + ); my $journey_visibility = $self->compute_effective_visibility( $user->{default_visibility_str}, @@ -377,6 +380,8 @@ sub homepage { journey_visibility => $journey_visibility, connections_iris => $connections_iris, connections_hafas => $connections_hafas, + with_map => 1, + %{$map_data}, ); $self->users->mark_seen( uid => $uid ); } @@ -387,6 +392,8 @@ sub homepage { user => $user, user_status => $status, journey_visibility => $journey_visibility, + with_map => 1, + %{$map_data}, ); $self->users->mark_seen( uid => $uid ); } @@ -399,6 +406,8 @@ sub homepage { user => $user, user_status => $status, journey_visibility => $journey_visibility, + with_map => 1, + %{$map_data}, ); $self->users->mark_seen( uid => $uid ); return; @@ -437,6 +446,9 @@ sub status_card { $self->stash( timeline => [@timeline] ); if ( $status->{checked_in} ) { + my $map_data = $self->journeys_to_map_data( + journeys => [$status], + ); my $journey_visibility = $self->compute_effective_visibility( $self->current_user->{default_visibility_str}, @@ -454,6 +466,7 @@ sub status_card { journey_visibility => $journey_visibility, connections_iris => $connections_iris, connections_hafas => $connections_hafas, + %{$map_data}, ); } )->catch( @@ -462,6 +475,7 @@ sub status_card { '_checked_in', journey => $status, journey_visibility => $journey_visibility, + %{$map_data}, ); } )->wait; @@ -471,6 +485,7 @@ sub status_card { '_checked_in', journey => $status, journey_visibility => $journey_visibility, + %{$map_data}, ); } elsif ( $status->{cancellation} ) { diff --git a/lib/Travelynx/Helper/DBRIS.pm b/lib/Travelynx/Helper/DBRIS.pm index 80c9c03..0a46758 100644 --- a/lib/Travelynx/Helper/DBRIS.pm +++ b/lib/Travelynx/Helper/DBRIS.pm @@ -97,7 +97,16 @@ sub get_journey_p { my $now = DateTime->now( time_zone => 'Europe/Berlin' ); my $agent = $self->{user_agent}; - if ( my $proxy = $self->{service_config}{'bahn.de'}{proxy} ) { + my $proxy; + if ( my @proxies = @{ $self->{service_config}{'bahn.de'}{proxies} // [] } ) + { + $proxy = $proxies[ int( rand( scalar @proxies ) ) ]; + } + elsif ( my $p = $self->{service_config}{'bahn.de'}{proxy} ) { + $proxy = $p; + } + + if ($proxy) { $agent = Mojo::UserAgent->new; $agent->proxy->http($proxy); $agent->proxy->https($proxy); diff --git a/lib/Travelynx/Model/InTransit.pm b/lib/Travelynx/Model/InTransit.pm index c12f03c..aa8fd4f 100644 --- a/lib/Travelynx/Model/InTransit.pm +++ b/lib/Travelynx/Model/InTransit.pm @@ -1,6 +1,7 @@ package Travelynx::Model::InTransit; # Copyright (C) 2020-2023 Birte Kristina Friesel +# Copyright (C) 2020-2025 Birte Kristina Friesel # Copyright (C) 2025 networkException <git@nwex.de> # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -13,11 +14,12 @@ use DateTime; use JSON; my %visibility_itoa = ( - 100 => 'public', - 80 => 'travelynx', - 60 => 'followers', - 30 => 'unlisted', - 10 => 'private', + 100 => 'public', + 80 => 'travelynx', + 60 => 'followers', + 30 => 'unlisted', + 10 => 'private', + default => 'default', ); my %visibility_atoi = ( @@ -103,8 +105,10 @@ sub add { my $checkin_station_id = $opt{departure_eva}; my $route = $opt{route}; my $data = $opt{data}; + my $persistent_data; my $json = JSON->new; + my $now = DateTime->now( time_zone => 'Europe/Berlin' ); if ($train) { @@ -116,16 +120,16 @@ sub add { cancelled => $train->departure_is_cancelled ? 1 : 0, checkin_station_id => $checkin_station_id, - checkin_time => DateTime->now( time_zone => 'Europe/Berlin' ), - dep_platform => $train->platform, - train_type => $train->type, - train_line => $train->line_no, - train_no => $train->train_no, - train_id => $train->train_id, - sched_departure => $train->sched_departure, - real_departure => $train->departure, - route => $json->encode($route), - messages => $json->encode( + checkin_time => $now, + dep_platform => $train->platform, + train_type => $train->type, + train_line => $train->line_no, + train_no => $train->train_no, + train_id => $train->train_id, + sched_departure => $train->sched_departure, + real_departure => $train->departure, + route => $json->encode($route), + messages => $json->encode( [ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ] ), data => JSON->new->encode( @@ -176,16 +180,16 @@ sub add { ? 1 : 0, checkin_station_id => $stop->loc->eva, - checkin_time => DateTime->now( time_zone => 'Europe/Berlin' ), - dep_platform => $stop->{platform}, - train_type => $product->type // q{}, - train_line => $product->line_no, - train_no => $product->number // q{}, - train_id => $journey->id, - sched_departure => $stop->{sched_dep}, - real_departure => $stop->{rt_dep} // $stop->{sched_dep}, - route => $json->encode( \@route ), - data => JSON->new->encode( + checkin_time => $now, + dep_platform => $stop->{platform}, + train_type => $product->type // q{}, + train_line => $product->line_no, + train_no => $product->number // q{}, + train_id => $journey->id, + sched_departure => $stop->{sched_dep}, + real_departure => $stop->{rt_dep} // $stop->{sched_dep}, + route => $json->encode( \@route ), + data => JSON->new->encode( { rt => $stop->{rt_dep} ? 1 : 0, %{ $data // {} } @@ -244,6 +248,13 @@ sub add { lead => $msg->{text} } ); + push( + @{ $persistent_data->{him_msg} }, + { + prio => $msg->{prioritaet}, + lead => $msg->{text} + } + ); } } $db->insert( @@ -254,21 +265,22 @@ sub add { ? 1 : 0, checkin_station_id => $stop->eva, - checkin_time => DateTime->now( time_zone => 'Europe/Berlin' ), - dep_platform => $stop->platform, - train_type => $journey->type // q{}, - train_line => $line, - train_no => $number, - train_id => $data->{trip_id}, - sched_departure => $stop->sched_dep, - real_departure => $stop->rt_dep // $stop->sched_dep, - route => $json->encode( \@route ), - data => JSON->new->encode( + checkin_time => $now, + dep_platform => $stop->platform, + train_type => $journey->type // q{}, + train_line => $line, + train_no => $number, + train_id => $data->{trip_id}, + sched_departure => $stop->sched_dep, + real_departure => $stop->rt_dep // $stop->sched_dep, + route => $json->encode( \@route ), + data => JSON->new->encode( { rt => $stop->{rt_dep} ? 1 : 0, %{ $data // {} } } ), + user_data => JSON->new->encode($persistent_data), backend_id => $backend_id, } ); @@ -400,18 +412,17 @@ sub postprocess { $ret->{route_after} = \@route_after; $ret->{extra_data} = $ret->{data}; $ret->{comment} = $ret->{user_data}{comment}; + $ret->{wagongroups} = $ret->{user_data}{wagongroups}; $ret->{platform_type} = 'Gleis'; - if ( $ret->{train_type} =~ m{ ast | bus | ruf }ix ) { + if ( $ret->{train_type} and $ret->{train_type} =~ m{ ast | bus | ruf }ix ) { $ret->{platform_type} = 'Steig'; } $ret->{visibility_str} - = $ret->{visibility} - ? $visibility_itoa{ $ret->{visibility} } - : 'default'; + = $visibility_itoa{ $ret->{visibility} // 'default' }; $ret->{effective_visibility_str} - = $visibility_itoa{ $ret->{effective_visibility} }; + = $visibility_itoa{ $ret->{effective_visibility} // 'default' }; my @parsed_messages; for my $message ( @{ $ret->{messages} // [] } ) { @@ -435,7 +446,7 @@ sub postprocess { = $dep_info->{rt_arr}->epoch - $epoch; } - for my $station (@route_after) { + for my $station (@route) { if ( @{$station} > 1 ) { # Note: $station->[2]{sched_arr} may already have been @@ -503,7 +514,7 @@ sub get { my $table = 'in_transit'; - if ( $opt{with_timestamps} ) { + if ( $opt{with_timestamps} or $opt{with_polyline} ) { $table = 'in_transit_str'; } @@ -517,13 +528,16 @@ sub get { $ret = $res->hash; } + if ( $opt{with_polyline} and $ret ) { + $ret->{dep_latlon} = [ $ret->{dep_lat}, $ret->{dep_lon} ]; + $ret->{arr_latlon} = [ $ret->{arr_lat}, $ret->{arr_lon} ]; + } + if ( $opt{with_visibility} and $ret ) { $ret->{visibility_str} - = $ret->{visibility} - ? $visibility_itoa{ $ret->{visibility} } - : 'default'; + = $visibility_itoa{ $ret->{visibility} // 'default' }; $ret->{effective_visibility_str} - = $visibility_itoa{ $ret->{effective_visibility} }; + = $visibility_itoa{ $ret->{effective_visibility} // 'default' }; } if ( $opt{postprocess} and $ret ) { @@ -877,21 +891,34 @@ sub update_departure_dbris { my $stop = $opt{stop}; my $json = JSON->new; - my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) - ->expand->hash; - my $data = $res_h ? $res_h->{data} : {}; + my $res_h = $db->select( 'in_transit', [ 'data', 'user_data' ], + { user_id => $uid } )->expand->hash; + my $ephemeral_data = $res_h ? $res_h->{data} : {}; + my $persistent_data = $res_h ? $res_h->{user_data} : {}; - $data->{him_msg} = []; + if ( $stop->{rt_dep} ) { + $ephemeral_data->{rt} = 1; + } + + $ephemeral_data->{him_msg} = []; + $persistent_data->{him_msg} = []; for my $msg ( $journey->messages ) { if ( not $msg->{ueberschrift} ) { push( - @{ $data->{him_msg} }, + @{ $ephemeral_data->{him_msg} }, { header => q{}, prio => $msg->{prioritaet}, lead => $msg->{text} } ); + push( + @{ $persistent_data->{him_msg} }, + { + prio => $msg->{prioritaet}, + lead => $msg->{text} + } + ); } } @@ -902,7 +929,8 @@ sub update_departure_dbris { 'in_transit', { real_departure => $stop->{rt_dep}, - data => $json->encode($data), + data => $json->encode($ephemeral_data), + user_data => $json->encode($persistent_data), }, { user_id => $uid, @@ -950,12 +978,20 @@ sub update_departure_hafas { my $stop = $opt{stop}; my $json = JSON->new; + my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) + ->expand->hash; + my $ephemeral_data = $res_h ? $res_h->{data} : {}; + if ( $stop->{rt_dep} ) { + $ephemeral_data->{rt} = 1; + } + # selecting on user_id and train_no avoids a race condition if a user checks # into a new train while we are fetching data for their previous journey. In # this case, the new train would receive data from the previous journey. $db->update( 'in_transit', { + data => $json->encode($ephemeral_data), real_departure => $stop->{rt_dep}, }, { @@ -1019,21 +1055,34 @@ sub update_arrival_dbris { my $stop = $opt{stop}; my $json = JSON->new; - my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } ) - ->expand->hash; - my $data = $res_h ? $res_h->{data} : {}; + my $res_h = $db->select( 'in_transit', [ 'data', 'user_data' ], + { user_id => $uid } )->expand->hash; + my $ephemeral_data = $res_h ? $res_h->{data} : {}; + my $persistent_data = $res_h ? $res_h->{user_data} : {}; - $data->{him_msg} = []; + if ( $stop->{rt_arr} ) { + $ephemeral_data->{rt} = 1; + } + + $ephemeral_data->{him_msg} = []; + $persistent_data->{him_msg} = []; for my $msg ( $journey->messages ) { if ( not $msg->{ueberschrift} ) { push( - @{ $data->{him_msg} }, + @{ $ephemeral_data->{him_msg} }, { header => q{}, prio => $msg->{prioritaet}, lead => $msg->{text} } ); + push( + @{ $persistent_data->{him_msg} }, + { + prio => $msg->{prioritaet}, + lead => $msg->{text} + } + ); } } @@ -1049,6 +1098,7 @@ sub update_arrival_dbris { sched_dep => _epoch( $j_stop->sched_dep ), rt_arr => _epoch( $j_stop->rt_arr ), rt_dep => _epoch( $j_stop->rt_dep ), + platform => $j_stop->platform, isCancelled => $j_stop->is_cancelled, arr_delay => $j_stop->arr_delay, dep_delay => $j_stop->dep_delay, @@ -1070,8 +1120,10 @@ sub update_arrival_dbris { 'in_transit', { real_arrival => $stop->{rt_arr}, + arr_platform => $stop->{platform}, route => $json->encode( [@route] ), - data => $json->encode($data), + data => $json->encode($ephemeral_data), + user_data => $json->encode($persistent_data), }, { user_id => $uid, @@ -1141,6 +1193,16 @@ sub update_arrival_hafas { my $stop = $opt{stop}; my $json = JSON->new; + my $res_h + = $db->select( 'in_transit', [ 'data', 'route' ], { user_id => $uid } ) + ->expand->hash; + my $ephemeral_data = $res_h ? $res_h->{data} : {}; + my $old_route = $res_h ? $res_h->{route} : []; + + if ( $stop->{rt_arr} ) { + $ephemeral_data->{rt} = 1; + } + my @route; for my $j_stop ( $journey->route ) { push( @@ -1166,10 +1228,6 @@ sub update_arrival_hafas { } } - my $res_h = $db->select( 'in_transit', ['route'], { user_id => $uid } ) - ->expand->hash; - my $old_route = $res_h ? $res_h->{route} : []; - for my $i ( 0 .. $#route ) { if ( $old_route->[$i] and $old_route->[$i][1] == $route[$i][1] ) { for my $k (qw(rt_arr rt_dep arr_delay dep_delay)) { @@ -1184,6 +1242,7 @@ sub update_arrival_hafas { $db->update( 'in_transit', { + data => $json->encode($ephemeral_data), real_arrival => $stop->{rt_arr}, route => $json->encode( [@route] ), }, diff --git a/lib/Travelynx/Model/Users.pm b/lib/Travelynx/Model/Users.pm index ae9ff2f..10ab17e 100644 --- a/lib/Travelynx/Model/Users.pm +++ b/lib/Travelynx/Model/Users.pm @@ -440,7 +440,7 @@ sub get { past_all => $user->{public_level} & 0x10000 ? 1 : 0, email => $user->{email}, sb_template => - 'https://dbf.finalrewind.org/{name}?rt=1&hafas={hafas}#{tt}{tn}', +'https://dbf.finalrewind.org/{name}?rt=1&dbris={dbris}&hafas={hafas}#{id_or_tttn}', registered_at => DateTime->from_epoch( epoch => $user->{registered_at_ts}, time_zone => 'Europe/Berlin' |