allow checking into traewelling

This commit is contained in:
Daniel Friesel 2020-10-01 19:36:35 +02:00
parent 590d3de518
commit 07e0f89706
4 changed files with 103 additions and 65 deletions

View file

@ -259,6 +259,26 @@ sub run {
)->wait;
}
for my $candidate ( $self->app->traewelling->get_pushable_accounts ) {
$self->app->log->debug(
"Pushing to Traewelling for UID $candidate->{uid}");
my $trip_id = $candidate->{journey_data}{trip_id};
if ( not $trip_id ) {
$self->app->log->debug("... trip_id is missing");
# TODO log traewelling error
return;
}
if ( $candidate->{data}{latest_push_ts}
and $candidate->{data}{latest_push_ts} == $candidate->{checkin_ts} )
{
$self->app->log->debug("... already handled");
return;
}
$self->app->traewelling_api->checkin( %{$candidate},
trip_id => $trip_id );
}
# Computing yearly stats may take a while, but we've got all time in the
# world here. This means users won't have to wait when loading their
# own by-year journey log.

View file

@ -267,66 +267,72 @@ sub logout_p {
}
sub checkin {
my ( $self, $uid ) = @_;
if ( my $token = $self->get_traewelling_push_token($uid) ) {
my $user = $self->get_user_status;
my ( $self, %opt ) = @_;
# TODO delete previous traewelling status if the train's destination has been changed
# TODO delete traewelling status when undoing a travelynx checkin
if ( $user->{checked_in} and $user->{extra_data}{trip_id} ) {
my $traewelling = $self->{model}->get($uid);
if ( $traewelling->{data}{trip_id} eq $user->{extra_data}{trip_id} )
{
my $header = {
'User-Agent' => $self->{header}{'User-Agent'},
'Authorization' => "Bearer $opt{token}",
};
my $request = {
tripID => $opt{trip_id},
start => q{} . $opt{dep_eva},
destination => q{} . $opt{arr_eva},
};
my $trip_req = sprintf(
"tripID=%s&lineName=%s%%20%s&start=%s",
$opt{trip_id}, $opt{train_type}, $opt{train_line} // $opt{train_no},
$opt{dep_eva}
);
$self->{user_agent}->request_timeout(20)
->get_p(
"https://traewelling.de/api/v0/trains/trip?$trip_req" => $header )
->then(
sub {
return $self->{user_agent}->request_timeout(20)
->post_p( "https://traewelling.de/api/v0/trains/checkin" =>
$header => json => $request );
}
)->then(
sub {
my ($tx) = @_;
if ( my $err = $tx->error ) {
my $err_msg = "HTTP $err->{code} $err->{message}";
$self->{log}->debug("... error: $err_msg");
$self->{model}->log(
uid => $opt{uid},
message =>
"Fehler bei $opt{train_type} $opt{train_no}: $err_msg",
is_error => 1
);
return;
}
my $header = {
'User-Agent' => 'travelynx/' . $self->{version},
'Authorization' => "Bearer $token",
};
my $request = {
tripID => $user->{extra_data}{trip_id},
start => q{} . $user->{dep_eva},
destination => q{} . $user->{arr_eva},
};
my $trip_req = sprintf(
"tripID=%s&lineName=%s%%20%s&start=%s",
$user->{extra_data}{trip_id}, $user->{train_type},
$user->{train_line} // $user->{train_no}, $user->{dep_eva}
$self->{log}->debug("... success!");
$self->{model}->log(
uid => $opt{uid},
message => "Eingecheckt in $opt{train_type} $opt{train_no}",
status_id => $tx->res->json->{statusId}
);
$self->{model}->set_latest_push_ts(
uid => $opt{uid},
ts => $opt{checkin_ts}
);
$self->{user_agent}->request_timeout(20)
->get_p(
"https://traewelling.de/api/v0/trains/trip?$trip_req" =>
$header )->then(
sub {
return $self->{user_agent}->request_timeout(20)
->post_p(
"https://traewelling.de/api/v0/trains/checkin" =>
$header => json => $request );
}
)->then(
sub {
my ($tx) = @_;
if ( my $err = $tx->error ) {
my $err_msg = "HTTP $err->{code} $err->{message}";
$self->mark_trwl_checkin_error( $uid, $user, $err_msg );
}
else {
# TODO check for traewelling error ("error" key in response)
# TODO store ID of resulting status (request /user/{name} and store status ID)
$self->mark_trwl_checkin_success( $uid, $user );
# mark success: checked into (trip_id, start, destination)
}
}
)->catch(
sub {
my ($err) = @_;
$self->mark_trwl_checkin_error( $uid, $user, $err );
}
)->wait;
# TODO store status_id in in_transit object so that it can be shown
# on the user status page
}
}
)->catch(
sub {
my ($err) = @_;
$self->{log}->debug("... error: $err");
$self->{model}->log(
uid => $opt{uid},
message => "Fehler bei $opt{train_type} $opt{train_no}: $err",
is_error => 1
);
}
)->wait;
}
1;

View file

@ -146,16 +146,16 @@ sub set_latest_pull_status_id {
);
}
sub set_latest_push_status_id {
sub set_latest_push_ts {
my ( $self, %opt ) = @_;
my $uid = $opt{uid};
my $status_id = $opt{status_id};
my $db = $opt{db} // $self->{pg}->db;
my $uid = $opt{uid};
my $ts = $opt{ts};
my $db = $opt{db} // $self->{pg}->db;
my $res_h
= $db->select( 'traewelling', 'data', { user_id => $uid } )->expand->hash;
$res_h->{data}{latest_push_status_id} = $status_id;
$res_h->{data}{latest_push_ts} = $ts;
$db->update(
'traewelling',
@ -181,12 +181,24 @@ sub set_sync {
);
}
sub get_push_accounts {
sub get_pushable_accounts {
my ($self) = @_;
my $res = $self->{pg}->db->select(
'traewelling',
[ 'user_id', 'token', 'data' ],
{ push_sync => 1 }
my $now = $self->now->epoch;
my $res = $self->{pg}->db->query(
qq{select t.user_id as uid, t.token as token, t.data as data,
i.checkin_station_id as dep_eva, i.checkout_station_id as arr_eva,
i.data as journey_data, i.train_type as train_type,
i.train_line as train_line, i.train_no as train_no,
extract(epoch from i.checkin_time) as checkin_ts
from traewelling as t
join in_transit as i on t.user_id = i.user_id
where t.push_sync = True
and i.checkout_station_id is not null
and i.cancelled = False
and (extract(epoch from i.sched_departure) > ?
or extract(epoch from i.real_departure) > ?)
and extract(epoch from i.sched_departure) < ?
}, $now - 300, $now - 300, $now + 600
);
return $res->expand->hashes->each;
}

View file

@ -135,7 +135,7 @@
<div class="input-field col s12">
<div>
<label>
%= radio_button sync_source => 'travelynx', disabled => undef
%= radio_button sync_source => 'travelynx'
<span>Checkin-Synchronisierung travelynx → Träwelling</span>
</label>
</div>