basic webhook support, onwards to betatesting

This commit is contained in:
Daniel Friesel 2019-05-06 16:59:48 +02:00
parent b36ba45aef
commit 2ddab75644
4 changed files with 106 additions and 79 deletions

View file

@ -574,9 +574,10 @@ sub startup {
} }
if ( $has_arrived or $force ) { if ( $has_arrived or $force ) {
return ( 0, undef );
$self->run_hook( $uid, 'checkout' ); $self->run_hook( $uid, 'checkout' );
return ( 0, undef );
} }
$self->run_hook( $uid, 'update' );
return ( 1, undef ); return ( 1, undef );
} }
); );
@ -1009,6 +1010,10 @@ sub startup {
$opt{uid} //= $self->current_user->{id}; $opt{uid} //= $self->current_user->{id};
if ( $opt{token} ) {
$opt{token} =~ tr{\r\n}{}d;
}
my $res = $self->pg->db->insert( my $res = $self->pg->db->insert(
'webhooks', 'webhooks',
{ {
@ -1029,8 +1034,8 @@ sub startup {
'mark_hook_status' => sub { 'mark_hook_status' => sub {
my ( $self, $uid, $url, $success, $text ) = @_; my ( $self, $uid, $url, $success, $text ) = @_;
if ( length($text) > 1024 ) { if ( length($text) > 1000 ) {
$text = "(output too long)"; $text = substr( $text, 0, 1000 ) . '…';
} }
$self->pg->db->update( $self->pg->db->update(
@ -1059,7 +1064,7 @@ sub startup {
return; return;
} }
my $status = { todo => 1 }; my $status = $self->get_user_status_json_v1($uid);
my $header = {}; my $header = {};
my $hook_body = { my $hook_body = {
reason => $reason, reason => $reason,
@ -1067,7 +1072,6 @@ sub startup {
}; };
if ( $hook->{token} ) { if ( $hook->{token} ) {
$hook->{token} =~ tr{\r\n}{}d;
$header->{Authorization} = "Bearer $hook->{token}"; $header->{Authorization} = "Bearer $hook->{token}";
} }
@ -1699,6 +1703,76 @@ sub startup {
} }
); );
$self->helper(
'get_user_status_json_v1' => sub {
my ( $self, $uid ) = @_;
my $status = $self->get_user_status($uid);
my $ret = {
deprecated => \0,
checkedIn => (
$status->{checked_in}
or $status->{cancelled}
) ? \1 : \0,
fromStation => {
ds100 => $status->{dep_ds100},
name => $status->{dep_name},
uic => undef,
longitude => undef,
latitude => undef,
scheduledTime => $status->{sched_departure}->epoch || undef,
realTime => $status->{real_departure}->epoch || undef,
},
toStation => {
ds100 => $status->{arr_ds100},
name => $status->{arr_name},
uic => undef,
longitude => undef,
latitude => undef,
scheduledTime => $status->{sched_arrival}->epoch || undef,
realTime => $status->{real_arrival}->epoch || undef,
},
train => {
type => $status->{train_type},
line => $status->{train_line},
no => $status->{train_no},
id => $status->{train_id},
},
actionTime => $status->{timestamp}->epoch,
};
if ( $status->{dep_ds100} ) {
my @station_descriptions
= Travel::Status::DE::IRIS::Stations::get_station(
$status->{dep_ds100} );
if ( @station_descriptions == 1 ) {
(
undef, undef,
$ret->{fromStation}{uic},
$ret->{fromStation}{longitude},
$ret->{fromStation}{latitude}
) = @{ $station_descriptions[0] };
}
}
if ( $status->{arr_ds100} ) {
my @station_descriptions
= Travel::Status::DE::IRIS::Stations::get_station(
$status->{arr_ds100} );
if ( @station_descriptions == 1 ) {
(
undef, undef,
$ret->{toStation}{uic},
$ret->{toStation}{longitude},
$ret->{toStation}{latitude}
) = @{ $station_descriptions[0] };
}
}
return $ret;
}
);
$self->helper( $self->helper(
'get_travel_distance' => sub { 'get_travel_distance' => sub {
my ( $self, $from, $to, $route_ref ) = @_; my ( $self, $from, $to, $route_ref ) = @_;

View file

@ -244,6 +244,7 @@ sub webhook {
token => $hook->{token}, token => $hook->{token},
enabled => $hook->{enabled} enabled => $hook->{enabled}
); );
$self->run_hook( $self->current_user->{id}, 'ping' );
$hook = $self->get_webhook; $hook = $self->get_webhook;
} }
else { else {

View file

@ -142,70 +142,7 @@ sub get_v1 {
return; return;
} }
if ( $api_action eq 'status' ) { if ( $api_action eq 'status' ) {
my $status = $self->get_user_status($uid); $self->render( json => $self->get_user_status_json_v1($uid) );
my $ret = {
deprecated => \0,
checkedIn => (
$status->{checked_in}
or $status->{cancelled}
) ? \1 : \0,
fromStation => {
ds100 => $status->{dep_ds100},
name => $status->{dep_name},
uic => undef,
longitude => undef,
latitude => undef,
scheduledTime => $status->{sched_departure}->epoch || undef,
realTime => $status->{real_departure}->epoch || undef,
},
toStation => {
ds100 => $status->{arr_ds100},
name => $status->{arr_name},
uic => undef,
longitude => undef,
latitude => undef,
scheduledTime => $status->{sched_arrival}->epoch || undef,
realTime => $status->{real_arrival}->epoch || undef,
},
train => {
type => $status->{train_type},
line => $status->{train_line},
no => $status->{train_no},
id => $status->{train_id},
},
actionTime => $status->{timestamp}->epoch,
};
if ( $status->{dep_ds100} ) {
my @station_descriptions
= Travel::Status::DE::IRIS::Stations::get_station(
$status->{dep_ds100} );
if ( @station_descriptions == 1 ) {
(
undef, undef,
$ret->{fromStation}{uic},
$ret->{fromStation}{longitude},
$ret->{fromStation}{latitude}
) = @{ $station_descriptions[0] };
}
}
if ( $status->{arr_ds100} ) {
my @station_descriptions
= Travel::Status::DE::IRIS::Stations::get_station(
$status->{arr_ds100} );
if ( @station_descriptions == 1 ) {
(
undef, undef,
$ret->{toStation}{uic},
$ret->{toStation}{longitude},
$ret->{toStation}{latitude}
) = @{ $station_descriptions[0] };
}
}
$self->render( json => $ret );
} }
else { else {
$self->render( $self->render(

View file

@ -8,14 +8,9 @@
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<p> <p>
Die im Web Hook konfigurierte URL wird bei jedem Checkin und Checkout Die im Web Hook konfigurierte URL wird bei Änderungen des aktuellen
des ausgewählten Zuges aufgerufen. Falls ein Token eingetragen Reisestatus (z.B. Checkin oder Ankunft am Ziel) aufgerufen. Falls ein
ist, wird er als Bearer Token verwendet. Token eingetragen ist, wird er als Bearer Token verwendet.
</p>
<p>
Events werden als JSON POST übertragen. Das JSON-Dokument besteht aus
zwei Feldern: „reason“ gibt den Grund des API-Aufrufs an (checkin,
checkout, undo), „status“ den <a href="/api">aktuellen Status</a>.
</p> </p>
</div> </div>
%= form_for '/account/hooks' => (method => 'POST') => begin %= form_for '/account/hooks' => (method => 'POST') => begin
@ -28,7 +23,7 @@
</div> </div>
<div class="input-field col s12"> <div class="input-field col s12">
<i class="material-icons prefix">link</i> <i class="material-icons prefix">link</i>
%= text_field 'url', id => 'url', class => 'validate', maxlength => 1000 %= text_field 'url', id => 'url', class => 'validate', pattern => 'https?://.+', maxlength => 1000
<label for="url">URL</label> <label for="url">URL</label>
</div> </div>
<div class="input-field col s12"> <div class="input-field col s12">
@ -38,7 +33,7 @@
</div> </div>
<div class="col s12"> <div class="col s12">
% if ($hook->{latest_run}->epoch) { % if ($hook->{latest_run}->epoch) {
Zuletzt ausgeführt: <%= $hook->{latest_run} %><br/> Zuletzt ausgeführt <%= $hook->{latest_run}->strftime('am %d.%m.%Y um %H:%M:%S') %><br/>
% if ($hook->{errored}) { % if ($hook->{errored}) {
<i class="material-icons left">error</i> <i class="material-icons left">error</i>
Status: <%= $hook->{output} %> Status: <%= $hook->{output} %>
@ -59,4 +54,24 @@
</button> </button>
</div> </div>
%= end %= end
<div class="col s12">
<p>Events werden als JSON POST mit folgender Payload übertragen.</p>
<p style="font-family: Monospace;">
{<br/>
"reason" : "Grund für den Webhook-Aufruf",<br/>
"status" : { <a href="/api">Aktueller Nutzerstatus</a> }<br/>
}<br/>
</p>
<p>
Gültige Werte für reason sind derzeit:
<ul>
<li><b>ping</b> (nach jeder gespeicherten Änderung in diesem Formular)</li>
<li><b>checkin</b> (in einen Zug eingecheckt Zielstation ist noch nicht bekannt)</li>
<li><b>update</b> (eingecheckt und Ziel gewählt oder geändert)</li>
<li><b>checkout</b> (aus einem Zug ausgecheckt)</li>
<li><b>undo</b> (checkin oder checkout wurde rückgängig gemacht)</li>
</ul>
Falls der Zug das Ziel bei der Zielwahl schon erreicht hat, wird ohne
<b>update</b> direkt ein <b>checkout</b> abgeschickt.
</p>
</div> </div>